/**********************************************************************
 *
 * metaformatsaction.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 "metaformatsaction.h"
#include "metaformat.h"
#include "recptprototools.h"
#include "oaitools.h"

bool metaformatsaction::validateAction(recptproto *protocol, oaiargs &params)
{ 
  // ----------------------------------------------------------------------------
  //  1. Check for invalid arguments
  // ----------------------------------------------------------------------------
  bool invalid_argument_supplied = false;
  text_tmap::const_iterator param_iterator = params.begin();
  while (param_iterator != params.end())
  {
    // Check for arguments that aren't valid for this action
    if (param_iterator->first != "verb" &&
	param_iterator->first != "identifier")
    {
      // We've found an invalid argument
      invalid_argument_supplied = true;

      // Delete the invalid argument from the list so it doesn't end up in the <request> tag that is returned
      params.erase(param_iterator->first);
    }

    param_iterator++;
  }

  // If we found an invalid argument it's an error, so don't go any further 
  if (invalid_argument_supplied)
  {
    this->errorType = "badArgument";
    return false;
  }

  // ----------------------------------------------------------------------------
  //  2. Handle any exclusive arguments
  // ----------------------------------------------------------------------------

  // None!

  // ----------------------------------------------------------------------------
  //  3. Handle any required arguments
  // ----------------------------------------------------------------------------

  // None!

  // ----------------------------------------------------------------------------
  // 4. Check any remaining arguments
  // ----------------------------------------------------------------------------

  // Check "identifier" argument
  if (params["identifier"] != "")
  {
    text_t identifier = params["identifier"];
	
	text_t oai_OID_prefix = "oai:"+this->configuration->getRepositoryId()+":";
	if(identifier.replace(oai_OID_prefix, "") <= 0) {
		this->errorType = "idDoesNotExist";
		// Only throw an error if we're using v2.0. 
		if (this->configuration->getOAIVersion() >= 200) {
			return false;
		}
	}

    // Extract the collection name from the identifier specification
    text_t collection = "";
    oaiclassifier::toGSDL(collection, identifier);
  
    // Check a document with the specified identifier exists
    text_tset metadata;	
	
    if (!get_oai_info(identifier, collection, "", metadata, false, protocol, this->gsdlResponse, *logout))
    {
      this->errorType = "idDoesNotExist";

      // Only throw an error if we're using v2.0. 
      // v1.1 should simply return a response without a metadataFormat container. 1.1
      // should still set the errorType so we know that the error was encountered
      // the information retrieved here is retained for the output_content function below
      if (this->configuration->getOAIVersion() >= 200)
      {
	return false;
      }
    }
  }

  // If we've reached here everything must be fine
  this->errorType = "";
  return true;
}

bool metaformatsaction::output_content(ostream &output, recptproto *protocol, oaiargs &params)
{
  // if an identifier parameter is being used, then respond to it - currently we reject anything other
  // than dublin core (unqualified)
  //
  // TODO: only return the selected identifier (if given) and don't validate the entry; just
  //       return nothing if an invalid or unknown metadata format is given
  
  // give the required xml response

  text_t gsdlId = params["identifier"];
  text_t gsdlCollect;

  // convert record identifier into GSDL format from OAI
  if (gsdlId != "") {
    oaiclassifier::toGSDL(gsdlCollect, gsdlId);
  }
  
  metaformat_map::iterator here = this->formats->begin();
  metaformat_map::iterator end  = this->formats->end();

  // v1.1 should check that the id - if supplied - didn't cause an error. If it did,
  // don't output the metadataFormat tags. OAI v2.0 should already have bailed.
  if(this->errorType != "idDoesNotExist"){
    while (here != end) { // Loop through the repository's supported metadata formats
      bool doOutput = true;
      
      // if we were given an identifier, then check if it supports the metadata format in question
      if (gsdlId != "") {
	doOutput = here->second.get_class()->is_available(gsdlCollect, this->gsdlResponse.docInfo[0]);
      }

      if (doOutput) {
	output << "  <metadataFormat>" << endl;
	here->second.get_class()->output_formatdata(output);
	output << "  </metadataFormat>\n";
      }
      ++here;
    }
  }

  return true;
}

void metaformatsaction::setConfiguration(oaiconfig *configuration)
{
  this->configuration = configuration;

  metaformat_map::iterator here = this->formats->begin();
  metaformat_map::iterator end  = this->formats->end();
  while (here != end) {    
    here->second.set_configuration((oaiconfig *) configuration);
    ++here;
  }
}

