/**********************************************************************
 *
 * gsdlsitecfg.cpp -- 
 * Copyright (C) 2008  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 "fileutil.h"
#include "gsdlsitecfg.h"
#include <stdlib.h> // for get/putenv
#include <string.h> // for get/putenv

#if defined(GSDL_USE_OBJECTSPACE)
#  include <ospace/std/iostream>
#  include <ospace/std/fstream>
#elif defined(GSDL_USE_IOS_H)
#  include <iostream.h>
#  include <fstream.h>
#else
#  include <iostream>
#  include <fstream>
#endif


class __site_configuration : public configurable {
private:
  text_t *gsdlhome;
  text_t *collecthome;
  text_t *httpdomain;
  text_t *httpprefix;
  text_t *collection;
  text_tset *actions;
  text_tset *browsers;
  int    *maxrequests;
public:
  __site_configuration (text_t *_gsdlhome, text_t* _collecthome, int *_maxrequests) {
    gsdlhome = _gsdlhome;
    collecthome = _collecthome;
    httpdomain = NULL;
    httpprefix = NULL;
    collection = NULL;
    actions = NULL;
    browsers = NULL;
    maxrequests = _maxrequests;
  }

  __site_configuration (text_t *_gsdlhome, text_t* _collecthome, 
			text_t *_httpdomain, text_t *_httpprefix) {
    gsdlhome    = _gsdlhome;
    collecthome  = _collecthome;
    httpdomain = _httpdomain;
    httpprefix = _httpprefix;
    collection = NULL;
    actions = NULL;
    browsers = NULL;
    maxrequests = NULL;
  }

  __site_configuration (text_t *_gsdlhome, text_t* _collecthome, 
			text_t *_httpdomain,
			text_t *_httpprefix, text_t *_collection) {
    gsdlhome    = _gsdlhome;
    collecthome  = _collecthome;
    httpdomain = _httpdomain;
    httpprefix = _httpprefix;
    collection = _collection;
    actions = NULL;
    browsers = NULL;
    maxrequests = NULL;
  }

  __site_configuration (text_t *_httpprefix, text_tset *_actions, text_tset *_browsers) {
    gsdlhome    = NULL;
    collecthome  = NULL;
    httpdomain = NULL;
    httpprefix = _httpprefix;
    collection = NULL;
    actions = _actions;
    browsers = _browsers;
    maxrequests = NULL;
  }

  inline void configure (const text_t &key, const text_tarray &cfgline) {
    if (gsdlhome != NULL && key == "gsdlhome") {
      *gsdlhome = cfgline[0];

      if ((collecthome != NULL) && (collecthome->empty())) {
	// defaults to <gsdlhome>/collect
	*collecthome = filename_cat(*gsdlhome,"collect");
      }
    }

    if (collecthome != NULL && key == "collecthome") {
      if (!collecthome->empty()) {
	// if it has been previously set to default, free and then reassign
	collecthome->clear();
      }
      *collecthome = cfgline[0];
    }

    if (httpprefix != NULL && key == "httpprefix") {
      *httpprefix = cfgline[0];
    }

    if (httpdomain != NULL && key == "httpdomain") {
      *httpdomain = cfgline[0];
    }

    if (collection != NULL && key == "collection") {
      *collection = cfgline[0];
    } 

    if(key == "javahome") {

      // javahome is a special variable that may or may not be set by the user in gsdlsite.cfg.
      // It specifies a custom java install that the user wants to use. If set, assume this is 
      // meant to override the default JAVA_HOME. Any javahome read in from gsdlsite.cfg 
      // will not be stored into the __site_configuration struct however. Instead, directly 
      // do putenv(javahome), just like gtiaction.cpp uses putenv, after printing out a warning 
      // to StdErr if getenv(JAVA_HOME) shows that JAVA_HOME is already set to something.

      text_t javahome(cfgline[0]);
      text_t oldjavahome = "";

      // getenv returns NULL if not set, http://www.cplusplus.com/reference/cstdlib/getenv/
      // 'The string pointed by the pointer returned by this function shall not be modified by the program.'
      char* existing_javahome = getenv("JAVA_HOME"); 

      if(existing_javahome != NULL) {
	oldjavahome += existing_javahome;
	if(javahome != oldjavahome) {
	  // cerr goes to: apache-httpd/<OS>/logs/error_log
	  cerr << "Warning: JAVA_HOME is already set to: " << existing_javahome << endl;
	  cerr << "But overwriting with javahome set in gsdlsite.cfg: " << javahome << endl;	
	}
      }

      if(javahome != oldjavahome) {
	// http://www.kev.pulo.com.au/pp/RESOURCES/cplusplus/ref/cstdlib/putenv.html
	// putenv is not defined in ANSI-C, but is supported by many compilers, and is 
	// already used in gtiaction.cpp
	javahome = "JAVA_HOME=" + javahome;
	char* set_javahome_cstr = javahome.getcstr();
	putenv(set_javahome_cstr);
	
	// can't use locally declared char array that we string-copy the cstr into, 
	// since the array's value expires from putenv, possibly after this function's local scope
	// Forced to assign the dynamically allocated cstr and resist the urge to delete this:
	//delete[] set_javahome_cstr; // may not delete it, else the env var just set will become empty      
      }    
    }

    if (actions != NULL && key == "actions") {
      actions->clear();
      text_tarray::const_iterator thisAction = cfgline.begin();
      text_tarray::const_iterator endAction = cfgline.end();
      while (thisAction != endAction) {
	actions->insert(*thisAction);
	++thisAction;
      }
    } 

    if (browsers != NULL && key == "browsers") {
      browsers->clear();
      text_tarray::const_iterator thisBrowser = cfgline.begin();
      text_tarray::const_iterator endBrowser = cfgline.end();
      while (thisBrowser != endBrowser) {
	browsers->insert(*thisBrowser);
	++thisBrowser;
      }
    }

    if (maxrequests != NULL && key == "maxrequests") {
      *maxrequests = cfgline[0].getint();
      if ((*maxrequests) < 1) {
	*maxrequests = 1;
      }
    }
  }
};


// reads site configuration file returning true on success
// also sets gsdlhome and maxrequests 
// gsdlsite.cfg should be in same directory as library executable
bool site_cfg_read (configurator gsdlconfigurator, text_t &gsdlhome, 
		    text_t& collecthome, int &maxrequests)
{
  __site_configuration sitecfg(&gsdlhome, &collecthome, &maxrequests);
  gsdlconfigurator.add_configurable(&sitecfg);

  // blank the gsdlhome and collecthome text
  gsdlhome.clear();
  collecthome.clear();

  if (gsdlconfigurator.configure("gsdlsite.cfg"))
  {
    return true;
  }

  return false;
}


// this version grabs gsdlhome, collecthome, httpdomain and httpprefix, 
// returns false if it can't find all of them
bool site_cfg_read (text_t &gsdlhome, text_t& collecthome, text_t &httpdomain, 
		    text_t &httpprefix)
{
  // get gsdlhome etc
  __site_configuration sitecfg(&gsdlhome, &collecthome, &httpdomain, &httpprefix);
  configurator gsdlconfigurator(&sitecfg);

  gsdlhome.clear();
  collecthome.clear();
  httpdomain.clear();
  httpprefix.clear();

  if (gsdlconfigurator.configure("gsdlsite.cfg"))
  {
    return true;
  }

  return false;
}


// this version grabs gsdlhome, collecthome, httpdomain, httpprefix, collection, 
// returns false if it can't find gsdlhome, httpdomain and httpprefix
bool site_cfg_read (text_t &gsdlhome, text_t& collecthome, text_t &httpdomain, 
		    text_t &httpprefix, text_t &collection)
{
  // get gsdlhome etc
  __site_configuration sitecfg(&gsdlhome, &collecthome, &httpdomain, &httpprefix, &collection);
  configurator gsdlconfigurator(&sitecfg);
	
  gsdlhome.clear();
  collecthome.clear();
  httpdomain.clear();
  httpprefix.clear();
  collection.clear();
	
  if (gsdlconfigurator.configure("gsdlsite.cfg") &&
      !gsdlhome.empty() && !collecthome.empty() 
      && !httpdomain.empty() && !httpprefix.empty())
  {
    return true;
  }	

  return false;
}
