/**********************************************************************
 *
 * action.cpp -- 
 * Copyright (C) 1999  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 "action.h"
#include <assert.h>


// define all the macros which are related to pages generated
// by this action
void action::define_internal_macros (displayclass &/*disp*/, cgiargsclass &/*args*/, 
				     recptprotolistclass * /*protos*/, ostream &/*logout*/) {
}

action::action () {
}

action::~action () {
}

// configure should be called once for each configuration line
void action::configure (const text_t &key, const text_tarray &cfgline) {
  if (key == "gsdlhome") {
    gsdlhome = cfgline[0];
    if (collecthome.empty()) collecthome = filename_cat(gsdlhome,"collect");
    if (dbhome.empty()) dbhome = cfgline[0];
  }
  if (key == "collecthome") {collecthome = cfgline[0];}
  if (key == "gdbmhome") {dbhome = cfgline[0];}
}

// init should be called after all the configuration is done but
// before any other methods are called
bool action::init (ostream &/*logout*/) {
  return true;
}

// returns the "a" argument value that will specify this action
// this name should be short but does not have to be one character
// long
text_t action::get_action_name () {
  return "nzdl";
}

// check_cgiargs should be called before get_cgihead_info, 
// define_external_macros, and do_action. If an error is found
// a message will be written to logout, if the error is severe
// then the function will return false and no page content
// should be produced based on the arguments.
bool action::check_cgiargs (cgiargsinfoclass &/*argsinfo*/, cgiargsclass &/*args*/, 
			    recptprotolistclass * /*protos*/, ostream &/*logout*/) {
  return true;
}

// check_external_cgiargs should be called after check_cgiargs
// for all actions. It should only be used to override some other
// normal behaviour, for example, producing a login page when
// the requested page needs authentication.
bool action::check_external_cgiargs (cgiargsinfoclass &/*argsinfo*/,
				     cgiargsclass &/*args*/,
				     outconvertclass &/*outconvert*/,
				     const text_t &/*saveconf*/,
				     ostream &/*logout*/) {
  return true;
}

// get_cgihead_info determines the cgi header information for
// a set of cgi arguments. If response contains location then
// response_data contains the redirect address. If reponse
// contains content then reponse_data contains the content-type.
// Note that images can now be produced by the receptionist.
void action::get_cgihead_info (cgiargsclass &/*args*/, recptprotolistclass * /*protos*/,
			       response_t &response, text_t &response_data, 
			       ostream &/*logout*/) {
  response = location;
  response_data = "http://www.nzdl.org";
}
  
// uses_display should return true if the receptionist should return
// true if the display class is needed to output the page content
// The default is to return true.
bool action::uses_display (cgiargsclass &/*args*/) {
  return true;
}


// define all the macros which might be used by other actions
// to produce pages. These macros should be well documented.
void action::define_external_macros (displayclass &/*disp*/, cgiargsclass &/*args*/, 
				     recptprotolistclass * /*protos*/, ostream &/*logout*/) {
}

// returns false if there was an error which prevented the action
// from outputing anything.
bool action::do_action (cgiargsclass &/*args*/, recptprotolistclass * /*protos*/, 
			browsermapclass * /*browsers*/, displayclass &/*disp*/, 
			outconvertclass &/*outconvert*/, ostream &/*textout*/, 
			ostream &/*logout*/) {
  return true;
}


bool operator==(const actionptr &x, const actionptr &y) {
  return (x.a == y.a);
}

bool operator<(const actionptr &x, const actionptr &y) {
  return (x.a < y.a);
}


// theaction remains the property of the calling code but
// should not be deleted until it is removed from this list.
void actionmapclass::addaction (action *theaction) {
  // can't add a null action
  assert (theaction != NULL);
  if (theaction == NULL) return;
  
  // can't add an action with no name
  assert (!(theaction->get_action_name()).empty());
  if ((theaction->get_action_name()).empty()) return;

  actionptr aptr;
  aptr.a = theaction;
  actionptrs[theaction->get_action_name()] = aptr;
}

// getaction will return NULL if the action could not be found
action *actionmapclass::getaction (const text_t &key) {
  // can't find an action with no name
  if (key.empty()) return NULL;

  iterator here = actionptrs.find (key);
  if (here == actionptrs.end()) return NULL;
  
  return (*here).second.a;
}
