/*
 Copyright (C) 2000-2004

 Code contributed by Greg Collecutt, Joseph Hope and Paul Cochrane

 This file is part of xmds.
 
 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/

/*
  $Id: xmdsargelement.cc,v 1.11 2004/07/13 08:46:23 paultcochrane Exp $
*/

/*! @file xmdsargelement.cc
  @brief Command line argument parsing classes and methods for argument elements

  More detailed explanation...
*/

#include<xmlbasics.h>
#include<dom3.h>
#include<xmdsutils.h>
#include<xmdsclasses.h>

// ******************************************************************************
// ******************************************************************************
//                              xmdsArgElement public
// ******************************************************************************
// ******************************************************************************

extern bool debugFlag;

long nxmdsArgElements=0;  //!< Number of xmds argument element objects

// ******************************************************************************
xmdsArgElement::xmdsArgElement(
			       const xmdsSimulation *const yourSimulation,
			       const bool& yourVerboseMode,
			       const xmdsArgv *const yourArgv) :
  xmdsArg(yourArgv),
  xmdsElement(yourSimulation,yourVerboseMode) {
  if(debugFlag) {
    nxmdsArgElements++;
    printf("xmdsArgElement::xmdsArgElement\n");
    printf("nxmdsArgElements=%li\n",nxmdsArgElements);
  }
};

// ******************************************************************************
xmdsArgElement::~xmdsArgElement() {
  if(debugFlag) {
    nxmdsArgElements--;
    printf("xmdsArgElement::~xmdsArgElement\n");
    printf("nxmdsArgElements=%li\n",nxmdsArgElements);
  }
};

// ******************************************************************************
void xmdsArgElement::processElement(
				    const Element *const yourElement) {
  if(debugFlag) {
    printf("xmdsArgElement::processElement\n");
  }

  list<XMLString> anXMLStringList;
  string aString;

  if(verbose()) {
    printf("Processing arg element ...\n");
  }

  // ************************************
  // find name

  getAssignmentStrings(yourElement,"name",1,1,anXMLStringList);

  const xmdsArg* possibleTwin;

  if(argv()->getArg(*anXMLStringList.begin(),possibleTwin)) {
    sprintf(errorMessage(),"an arg of name '%s' already exists in this argv",anXMLStringList.begin()->c_str());
    throw xmdsException(yourElement,errorMessage());
  }

  // I think by leaving this here, we can check for duplicate names
  setName(*anXMLStringList.begin());

  XMLString xmltempString = *anXMLStringList.begin();
  string nameString = ( string ) xmltempString.c_str();
  simulation()->argStruct()->nameList.push_back(nameString);

  if(verbose()) {
    printf("argument name is '%s'\n",nameString.c_str());
  }

  // now I need to work out what the short option should be
  string testChar;
  bool shortOptExists;
  for (unsigned long int j=0; j<nameString.length(); j++) {
    shortOptExists = false;
    testChar = nameString[j];
    list<string>::const_iterator ishort = simulation()->argStruct()->shortOptionList.begin();
    for (unsigned long int i=0; i<simulation()->argStruct()->shortOptionList.size(); i++) {
      if (verbose()) {
	printf("Testing %s with %s against %s\n",nameString.c_str(),testChar.c_str(),ishort->c_str());
      }
      // the short option can't be 'h' since this is used to output the help and usage information
      if ((testChar.find(*ishort) != string::npos) || (testChar.find("h") != string::npos)) {
	if (verbose()) {
	  printf("short option '%s' already exists\n",testChar.c_str());
	}
	// it exists already, set a flag to go around again.
	shortOptExists = true;
      }
      if (testChar.find(*ishort) == string::npos && shortOptExists) {
	sprintf(errorMessage(),
		"Haven't been able to make a short option for '%s'.\n"
		"Please use another name and retry.\n",
		nameString.c_str());
	throw xmdsException(yourElement,errorMessage());
      }
      ishort++;
    }
    if (!shortOptExists) {
      // if get to here without the option turning up, break.
      if (verbose()) {
	printf("Using %s as short option for %s\n",testChar.c_str(),nameString.c_str());
      }
      simulation()->argStruct()->shortOptionList.push_back(testChar);
      break;
    }
  }

  // ************************************
  // find type

  getAssignmentStrings(yourElement,"type",1,0,anXMLStringList);

  // now biff the XMLStringList into an XMLString and set that to the argument type
  XMLString xmltypeString, spaceString;
  spaceString = " ";
  list<XMLString>::const_iterator iType;
  iType = anXMLStringList.begin();
  for (unsigned long int i=0; i<anXMLStringList.size(); i++) {
    xmltypeString += *iType;
    xmltypeString += spaceString;
    iType++;
  }

  string typeString = ( string ) xmltypeString.c_str();
  simulation()->argStruct()->typeList.push_back(typeString);

  if (debugFlag) {
    printf("typeString is: %s\n",typeString.c_str());
  }

  if (verbose()) {
    printf("argument type is '%s'\n",typeString.c_str());
  }

  // now need to define the conversion function string
  // e.g. double -> atof()

  if (typeString.find("double") != string::npos) {
    // setting type to double
    if (verbose()) {
      printf("typeString matches 'double': using atof() as type conversion\n");
    }
    simulation()->argStruct()->typeConversionList.push_back("atof");
  }
  else if (typeString.find("float") != string::npos) {
    // setting type to double anyway...  (should I really do this?)
    if (verbose()) {
      printf("typeString matches 'float': using atof() as type conversion\n");
    }
    simulation()->argStruct()->typeConversionList.push_back("atof");
  }
  else if (typeString.find("string") != string::npos) {
    // setting type to string
    if (verbose()) {
      printf("typeString matches 'string': no need for type conversion\n");
    }
    simulation()->argStruct()->typeConversionList.push_back("");
  }
  else if (typeString.find("char") != string::npos) {
    // setting type to char *
    if (verbose()) {
      printf("typeString matches 'char': no need for type conversion\n");
    }
    simulation()->argStruct()->typeConversionList.push_back("");
  }
  else if (typeString.find("int") != string::npos) {
    // setting type to int
    if (verbose()) {
      printf("typeString matches 'int': using atoi() as type conversion\n");
    }
    simulation()->argStruct()->typeConversionList.push_back("atoi");
  }
  else {
    printf("Hmmm, I don't know how your type should be converted\n");
    printf("Hoping that double is ok...\n");
    simulation()->argStruct()->typeConversionList.push_back("atof");
  }

  // ************************************
  // find default_value

  getAssignmentStrings(yourElement,"default_value",1,1,anXMLStringList);

  xmltempString = *anXMLStringList.begin();
  string defaultValueString = ( string ) xmltempString.c_str();
  simulation()->argStruct()->defaultValueList.push_back(defaultValueString);

  if (verbose()) {
    printf("argument default value is '%s'\n",defaultValueString.c_str());
  }

};

// ******************************************************************************
// ******************************************************************************
//                              xmdsArgElement private
// ******************************************************************************
// ******************************************************************************




syntax highlighted by Code2HTML, v. 0.9.1