/**********************************************************************
 *
 * oaimain.cpp --
 *
 * Copyright (C) 2004-2010  The New Zealand Digital Library Project
 *
 * A component of the Greenstone digital library software
 * from the New Zealand Digital Library Project at the
 * University of Waikato, New Zealand.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *********************************************************************/

#include "oaimain.h"
#include "gsdlconf.h"

#if defined(GSDL_USE_IOS_H)
#  if defined(__WIN32__)
#    include <strstrea.h> // vc4
#  else
#    include <strstream.h>
#  endif
#else
#  include <sstream>
#endif

#include "fileutil.h"
#include "nullproto.h"
#include "collectset.h"
#include "cgiargs.h"

#include "identifyaction.h"
#include "recordaction.h"
#include "listsetsaction.h"
#include "listrecsaction.h"
#include "listidsaction.h"
#include "metaformatsaction.h"
#include "oaidispatcher.h"
#include "oaiconfig.h"

void get_cgi_args(text_t &argstring)
{
  // get the query string if it is not being run as a fastcgi
  // script
  text_t argstr = "";
  char *aURIStr;
  char *request_method_str = getenv("REQUEST_METHOD");
  char *content_length_str = getenv("CONTENT_LENGTH");
  if (request_method_str != NULL && strcmp(request_method_str, "POST") == 0 &&
      content_length_str != NULL)  {
    // POST form data
    int content_length = text_t(content_length_str).getint();
    if (content_length > 0) {
      char c;
      do {
	cin.get(c);
	if (cin.eof()) 
	  break;
	argstr.push_back (c);
	--content_length;
      } while (content_length > 0);
    }
    
  } else {
    aURIStr = getenv("QUERY_STRING");
    if ((request_method_str != NULL && strcmp(request_method_str, "GET") == 0)
	|| aURIStr != NULL) {
      // GET form data
      if (aURIStr != NULL) 
	argstr = aURIStr;
    } else {
      // debugging from command line
      // debug = true;
      char inStr[1024];
      
      cin.get(inStr, 1024);
      argstr = inStr;
    }
  }
  argstring = argstr;
}


int main(int argc, char *argv[])
{
  text_t        cgiargstring;
  nullproto     nproto;
  collectset   *cservers;
  text_t        gsdlhome;
  text_t        collecthome;
  text_t        gsdlcollect = "";
  oaiargs       args;
  ofstream      logout("oai.log", ios::app);
  
  // convert cgi to oai map
  get_cgi_args(cgiargstring);
  
  char *cstr = cgiargstring.getcstr();
#if defined(GSDL_USE_IOS_H)
  istrstream cgi_in(cstr, cgiargstring.size());
#else
  istringstream cgi_in(cstr);
#endif

  // parse the arguments
  args.readArgs(cgi_in);

  delete []cstr;
  
  cservers = new collectset(gsdlhome,collecthome);

  // set up the null protocol
  nproto.set_collectset(cservers);
  
  // get the oai configuration
  oaiconfig config(gsdlhome, gsdlcollect);

  // set up the dispatcher
  oaidispatcher dispatcher;
  dispatcher.setConfiguration(&config);

  identifyaction *id   = new identifyaction;
  recordaction   *rec  = new recordaction(config.getMetadataSet());
  listsetsaction *sets = new listsetsaction;
  listrecsaction *records = new listrecsaction;
  records->set_recordMaker(rec);

  listidsaction  *ids     = new listidsaction;
  metaformatsaction *formats = new metaformatsaction;
  formats->set_formats(rec->get_formats());

  dispatcher.addAction(id);
  dispatcher.addAction(rec);
  dispatcher.addAction(sets);
  dispatcher.addAction(records);
  dispatcher.addAction(ids);
  dispatcher.addAction(formats);

  // deal with this request
  comerror_t error;
  nproto.init(error, logout);

  // GRB: any checks that a collection exists would be done here
  //      At present, I foresee no useful application of that requirement.

  dispatcher.doAction(cout, &nproto, args);
  
  delete cservers;
  return 0;
}
