/**********************************************************************
 *
 * configaction.cpp -- 
 * Copyright (C) 2003 DL Consulting Ltd
 *
 * 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 "configaction.h"

#ifdef GSDL_LOCAL_LIBRARY
// for PostMessage()
#  include <windows.h>
#endif

// constant for restart/reconfigure windows message (same as in w32server/fnord)
// http://msdn.microsoft.com/en-us/library/ms644931%28v=VS.85%29.aspx on WM_USER
// (also RegisterWindowMessage Function at http://msdn.microsoft.com/en-us/library/ms644947%28v=VS.85%29.aspx
// http://msdn.microsoft.com/en-us/library/ms644927%28v=VS.85%29.aspx)
#define WM_RESTART WM_USER+1

configaction::configaction () {

  recpt = NULL;

  cgiarginfo arg_ainfo;
  arg_ainfo.shortname = "a";
  arg_ainfo.longname = "action";
  arg_ainfo.multiplechar = true;
  arg_ainfo.multiplevalue = false;
  arg_ainfo.defaultstatus = cgiarginfo::weak;
  arg_ainfo.argdefault = "config";
  arg_ainfo.savedarginfo = cgiarginfo::must;
  argsinfo.addarginfo (NULL, arg_ainfo);

  /* 
     The cmd argument may be one of the following:
     -- release-collection - release the collection specified by the "c"
        argument
     -- add-collection - add and configure a collection server for the
        collection specified by the "c" argument
     -- kill - if running as the local library this will kill the server
  */
  arg_ainfo.shortname = "cmd";
  arg_ainfo.longname = "config command";
  arg_ainfo.multiplechar = true;
  arg_ainfo.multiplevalue = false;  
  arg_ainfo.defaultstatus = cgiarginfo::weak;
  arg_ainfo.argdefault = g_EmptyText;
  arg_ainfo.savedarginfo = cgiarginfo::mustnot;
  argsinfo.addarginfo (NULL, arg_ainfo);
}

configaction::~configaction () {
}

void configaction::get_cgihead_info (cgiargsclass &args, recptprotolistclass *protos,
				     response_t &response, text_t &response_data, 
				     ostream &logout) {
  response = content;
  response_data = "text/html";
}

bool configaction::do_action (cgiargsclass &args, recptprotolistclass *protos, 
			      browsermapclass *browsers, displayclass &disp,
			      outconvertclass &outconvert, ostream &textout,
			      ostream &logout) {

  if (recpt == NULL) return false;

  if ((args["cmd"] == "add-collection") && (!args["c"].empty())) {
    create_colservr(args["c"], logout);
    textout << "configured add-collection\n";

  } else if ((args["cmd"] == "release-collection") && (!args["c"].empty())) {
    remove_colservr(args["c"], logout);
    textout << "configured release-collection\n";

  } else if ((args["cmd"] == "restart")) {	
    textout << "configured for restart\n";
#ifdef GSDL_LOCAL_LIBRARY
    HWND gw = FindWindow("Greenstone Digital Library Software",
			 "Greenstone Digital Library Software");
    PostMessage(gw, WM_RESTART, 0, 0);
#endif
  } else if (args["cmd"] == "kill") {
    textout << "killed\n";
#ifdef GSDL_LOCAL_LIBRARY
    HWND gw = FindWindow("Greenstone Digital Library Software",
			 "Greenstone Digital Library Software");
    PostMessage(gw, WM_DESTROY, 0, 0);
#endif
  }

  return true;
}


// create and initialize a new collection server and
// add it to the null protocol.
void configaction::create_colservr (const text_t &collection, ostream &logout) {

  // just in case we're adding a collection that already exists
  recpt->uncache_collection(collection);

  recptprotolistclass *protos = recpt->get_recptprotolist_ptr();
  recptprotolistclass::iterator rprotolist_here = protos->begin();
  recptprotolistclass::iterator rprotolist_end = protos->end();
  while (rprotolist_here != rprotolist_end) {
    comerror_t err = noError;
    if ((*rprotolist_here).p != NULL) {
      if ((*rprotolist_here).p->get_protocol_name(err) == "nullproto") {
	// create collection server and add it to nullproto
	(*rprotolist_here).p->add_collection(collection, recpt, gsdlhome, collecthome, gsdlhome);
	// re-initialize the null protocol
	if (!(*rprotolist_here).p->init(err, logout)) {
	  logout << "configaction::create_colservr: nullproto init failed\n";
	}
	return;
      }
    }
    ++rprotolist_here;
  }

  logout << "configaction::create_colservr: no valid nullproto found\n";
}

// delete a collection server from the null protocol
void configaction::remove_colservr (const text_t &collection, ostream &logout) {

  recpt->uncache_collection(collection);

  recptprotolistclass *protos = recpt->get_recptprotolist_ptr();
  recptprotolistclass::iterator rprotolist_here = protos->begin();
  recptprotolistclass::iterator rprotolist_end = protos->end();
  while (rprotolist_here != rprotolist_end) {
    comerror_t err = noError;
    if ((*rprotolist_here).p != NULL) {
      if ((*rprotolist_here).p->get_protocol_name(err) == "nullproto") {
	(*rprotolist_here).p->remove_collection(collection, logout);
	return;
      }
    }
    ++rprotolist_here;
  }

  logout << "configaction::create_colserver: no valid nullproto found\n";
}
