/*
 * Project: MoleCuilder
 * Description: creates and alters molecular systems
 * Copyright (C)  2010-2012 University of Bonn. All rights reserved.
 * 
 *
 *   This file is part of MoleCuilder.
 *
 *    MoleCuilder 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.
 *
 *    MoleCuilder 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 MoleCuilder.  If not, see .
 */
/*
 * MpqcParser_Parameters.cpp
 *
 *  Created on: Feb 3, 2011
 *      Author: heber
 */
// include config.h
#ifdef HAVE_CONFIG_H
#include 
#endif
#include "CodePatterns/MemDebug.hpp"
#include 
#include "CodePatterns/Log.hpp"
#include "MpqcParser.hpp"
#include "MpqcParser_Parameters.hpp"
#include "Parameters/Parameter.hpp"
template <>
const std::string Value::getAsString() const throw(ParameterValueException)
{
  if(!ValueSet)
    throw ParameterValueException();
  if (value)
    return std::string("yes");
  else
    return std::string("no");
}
template <>
void Value::setAsString(const std::string _value) throw(ParameterException)
{
  if (_value == std::string("yes")) {
    set(true);
  } else if (_value == std::string("no")) {
    set(false);
  } else {
    throw ParameterValueException();
  }
}
MpqcParser_Parameters::MpqcParser_Parameters()
{
  Init();
}
void MpqcParser_Parameters::Init()
{
  // add all known basis
  initBasis();
  // add all parameter names
  {
    ParamNames.clear();
    ParamNames.resize(unknownParam);
    ParamNames[hessianParam] = "Hessian";
    ParamNames[savestateParam] = "savestate";
    ParamNames[do_gradientParam] = "do_gradient";
    ParamNames[maxiterParam] = "maxiter";
    ParamNames[memoryParam] = "memory";
    ParamNames[stdapproxParam] = "stdapprox";
    ParamNames[nfzcParam] = "nfzc";
    ParamNames[basisParam] = "basis";
    ParamNames[aux_basisParam] = "aux_basis";
    ParamNames[integrationParam] = "integration";
    ParamNames[theoryParam] = "theory";
  }
  // create theory parameter
  {
    ValidTheories.clear();
    ValidTheories.resize(unknownTheory);
    ValidTheories[CLHF]="CLHF";
    ValidTheories[CLKS]="CLKS";
    ValidTheories[MBPT2]="MBPT2";
    ValidTheories[MBPT2_R12]="MBPT2_R12";
    appendParameter(
        new Parameter(
            ParamNames[theoryParam],
            ValidTheories,
            ValidTheories[MBPT2]));
  }
  //InvertMap(TheoryNames,TheoryLookup);
  // create integration parameter
  {
    ValidIntegrationMethods.clear();
    ValidIntegrationMethods.resize(unknownIntegration);
    ValidIntegrationMethods[IntegralCints] = "IntegralCints";
    appendParameter(
        new Parameter(
            ParamNames[integrationParam],
            ValidIntegrationMethods,
            ValidIntegrationMethods[IntegralCints]));
  }
  // add all continuous parameters
  {
    appendParameter(new Parameter(ParamNames[hessianParam], false));
    appendParameter(new Parameter(ParamNames[savestateParam], false));
    appendParameter(new Parameter(ParamNames[do_gradientParam], true));
    appendParameter(new Parameter(ParamNames[maxiterParam], 1000));
    appendParameter(new Parameter(ParamNames[memoryParam], 16000000));
    appendParameter(new Parameter(ParamNames[stdapproxParam], "A'"));
    appendParameter(new Parameter(ParamNames[nfzcParam], 1));
    appendParameter(new Parameter(ParamNames[basisParam], "3-21G"));
    appendParameter(new Parameter(ParamNames[aux_basisParam], "aug-cc-pVDZ"));
  }
}
MpqcParser_Parameters::~MpqcParser_Parameters()
{}
/** Getter for a specific Parameter.
 *
 * @param param index among enum Parameters
 * @return value of the desired Parameters
 */
const std::string MpqcParser_Parameters::getParameter(const enum Parameters param) const
{
  return FormatParser_Parameters::getParameter(ParamNames[param])->getAsString();
}
/** Setter for a specific Parameter.
 *
 * @param param index among enum Parameters
 * @param _value value to set desired Parameter to
 */
void MpqcParser_Parameters::setParameter(const enum Parameters param, const std::string &_value)
{
  const std::string &name = getParameterName(param);
  FormatParser_Parameters::getParameter(name)->setAsString(_value);
}
/** Getter for name of a specific Parameter.
 *
 * @param param index among enum Parameters
 * @return name of the desired Parameter
 */
const std::string &MpqcParser_Parameters::getParameterName(const enum Parameters param) const
{
  return ParamNames[param];
}
/** Getter for name of a specific Parameter.
 *
 * @param param index among enum Theory
 * @return name of the desired Theory
 */
const std::string &MpqcParser_Parameters::getTheoryName(const enum Theory theory) const
{
  return ValidTheories[theory];
}
/** Getter for the name of specific of IntegrationMethod.
 *
 * @param param index among enum IntegrationMethod
 * @return value of the desired IntegrationMethod
 */
const std::string &MpqcParser_Parameters::getIntegrationMethodName(const enum IntegrationMethod integration) const
{
  return ValidIntegrationMethods[integration];
}
/** Checks whether all elements in the world also have parameters in the basis.
 *
 * @return true - all elements parametrized, false - at least one element is missing.
 */
bool MpqcParser_Parameters::checkWorldElementsAgainstCurrentBasis() const
{
  ELOG(0, "MpqcParser_Parameters::checkWorldElementsAgainstCurrentBasis() - not implemented yet.");
  return false;
}