/*
 * 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 .
 */
/*
 * Psi3Parser_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 "Psi3Parser_Parameters.hpp"
#include "Parameters/Parameter.hpp"
Psi3Parser_Parameters::Psi3Parser_Parameters()
{
  Init();
}
void Psi3Parser_Parameters::Init()
{
  // add all known basis
  //initBasis();
  // add all parameter names
  {
    ParamNames.clear();
    ParamNames.resize(unknownParam);
    ParamNames[labelParam] = "label";
    ParamNames[jobtypeParam] = "jobtype";
    ParamNames[wavefunctionParam] = "wfn";
    ParamNames[maxiterParam] = "maxiter";
    ParamNames[referenceParam] = "reference";
    ParamNames[basisParam] = "basis";
    ParamNames[freeze_coreParam] = "freeze_core";
    ParamNames[unitsParam] = "units";
    ParamNames[dertypeParam] = "dertype";
    ParamNames[originParam] = "origin";
    ParamNames[multiplicityParam] = "multp";
    ParamNames[chargeParam] = "charge";
    ParamNames[soccParam] = "socc";
    ParamNames[doccParam] = "docc";
    ParamNames[subgroupParam] = "subgroup";
    ParamNames[unique_axisParam] = "unique_axis";
  }
  // create freeze_core parameter
  {
    ValidFreezeCore.clear();
    ValidFreezeCore.resize(unknownFreezeCore);
    ValidFreezeCore[YES]="yes";
    ValidFreezeCore[TRUE]="true";
    ValidFreezeCore[NO]="no";
    ValidFreezeCore[FALSE]="false";
    ValidFreezeCore[SMALL]="small";
    ValidFreezeCore[LARGE]="large";
    appendParameter(
        new Parameter(
            ParamNames[freeze_coreParam],
            ValidFreezeCore,
            ValidFreezeCore[YES]));
  }
  // create units parameter
  {
    ValidUnits.clear();
    ValidUnits.resize(unknownUnits);
    ValidUnits[angstrom]="angstrom";
    ValidUnits[bohr]="bohr";
    appendParameter(
        new Parameter(
            ParamNames[unitsParam],
            ValidUnits,
            ValidUnits[angstrom]));
  }
  // create dertype parameter
  {
    ValidDerivativeType.clear();
    ValidDerivativeType.resize(unknownDerivativeType);
    ValidDerivativeType[NONE]="none";
    appendParameter(
        new Parameter(
            ParamNames[dertypeParam],
            ValidDerivativeType,
            ValidDerivativeType[NONE]));
  }
  // create unique_axis parameter
  {
    ValidUniqueAxis.clear();
    ValidUniqueAxis.resize(unknownUniqueAxis);
    ValidUniqueAxis[X]="x";
    ValidUniqueAxis[Y]="y";
    ValidUniqueAxis[Z]="z";
    appendParameter(
        new Parameter(
            ParamNames[unique_axisParam],
            ValidUniqueAxis,
            ValidUniqueAxis[X]));
  }
  // create jobtype parameter
  {
    ValidJobtypes.clear();
    ValidJobtypes.resize(unknownJobtype);
    ValidJobtypes[SP]="sp";
    ValidJobtypes[OPT]="opt";
    ValidJobtypes[DISP]="disp";
    ValidJobtypes[FREQ]="freq";
    ValidJobtypes[SYMM_FREQ]="symm_freq";
    ValidJobtypes[DBOC]="dboc";
    ValidJobtypes[RESPONSE]="response";
    appendParameter(
        new Parameter(
            ParamNames[jobtypeParam],
            ValidJobtypes,
            ValidJobtypes[SP]));
  }
  // create wavefunction parameter
  {
    ValidWavefunction.clear();
    ValidWavefunction.resize(unknownWavefunction);
    ValidWavefunction[SCF]="scf";
    ValidWavefunction[MP2]="mp2";
    ValidWavefunction[MP2R12]="mp2r12";
    ValidWavefunction[CIS]="cis";
    ValidWavefunction[DETCI]="detci";
    ValidWavefunction[CASSCF]="casscf";
    ValidWavefunction[RASSCF]="rasscf";
    ValidWavefunction[CCSD]="ccsd";
    ValidWavefunction[CCSD_T]="ccsd_t";
    ValidWavefunction[BCCD]="bccd";
    ValidWavefunction[BCCD_T]="bccd_t";
    ValidWavefunction[EOM_CCSD]="eom_ccsd";
    ValidWavefunction[ZAPTN]="zaptn";
    appendParameter(
        new Parameter(
            ParamNames[wavefunctionParam],
            ValidWavefunction,
            ValidWavefunction[SCF]));
  }
  // create reference parameter
  {
    ValidReference.clear();
    ValidReference.resize(unknownReference);
    ValidReference[RHF]="rhf";
    ValidReference[ROHF]="rohf";
    ValidReference[UHF]="uhf";
    ValidReference[TWOCON]="twocon";
    appendParameter(
        new Parameter(
            ParamNames[referenceParam],
            ValidReference,
            ValidReference[RHF]));
  }
  // add all continuous parameters
  {
    appendParameter(new Parameter(ParamNames[labelParam], std::string("unknown job")));
    appendParameter(new Parameter(ParamNames[maxiterParam], 80));
    appendParameter(new Parameter(ParamNames[basisParam], std::string("cc-pVTZ")));
    appendParameter(new Parameter(ParamNames[originParam], std::string("(0.0\t0.0\t0.0)"))); // TODO: this should be a vector
    appendParameter(new Parameter(ParamNames[multiplicityParam], 1));
    appendParameter(new Parameter(ParamNames[chargeParam], 0));
    appendParameter(new Parameter(ParamNames[soccParam], std::string("()")));
    appendParameter(new Parameter(ParamNames[doccParam], std::string("()")));
    appendParameter(new Parameter(ParamNames[subgroupParam], std::string("")));
 }
}
Psi3Parser_Parameters::~Psi3Parser_Parameters()
{}
/** Getter for a specific Parameter.
 *
 * @param param index among enum Parameters
 * @return value of the desired Parameters
 */
const std::string Psi3Parser_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 Psi3Parser_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 &Psi3Parser_Parameters::getParameterName(const enum Parameters param) const
{
  return ParamNames[param];
}
/** Getter for name of a specific Reference.
 *
 * @param reference index among enum Reference
 * @return name of the desired Reference
 */
const std::string &Psi3Parser_Parameters::getReferenceName(const enum Reference reference) const
{
  return ValidReference[reference];
}
/** 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 Psi3Parser_Parameters::checkWorldElementsAgainstCurrentBasis() const
{
  ELOG(0, "Psi3Parser_Parameters::checkWorldElementsAgainstCurrentBasis() - not implemented yet.");
  return false;
}