/***************************************************************************
 *   Copyright (C) 2005 by Armando Navarro-Vazquez                         *
 *   qoajnv@usc.es                                                         *
 *                                                                         *
 *   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.             *
 ***************************************************************************/

#include <sstream>
#include "macromodeldynparser.h"
#include "tokenizer.h"
#include "molecule.h"
using namespace strtools;

MacroModelDynParser::MacroModelDynParser(const char* inputfile) : QuantumParser(inputfile)
{}

MacroModelDynParser::MacroModelDynParser(std::istream* stream) : QuantumParser(stream)
{}

bool MacroModelDynParser::ParseFile(std::streampos pos)
{
  m_file->clear();
  m_file->seekg(0,std::ios::beg);
  std::string line;
  std::getline(*m_file,line);
  //Get the number of atoms
  StringTokenizer tok(line," \t=");
  int natoms=atoi(tok.front().c_str());
  StringTokenizer::iterator tt;
  double venergy=0;
  for(tt=tok.begin();tt!=tok.end();++tt)
  {
     if ( *tt == "E" ) venergy=atof((tt+1)->c_str());
  }

  CMolecule molecule;
  if( natoms < 1) return false;
  molecule.m_atom.resize(natoms);
  size_t i=0;
  //Setup first structure
  while(std::getline(*m_file,line))
  {
    StringTokenizer token(line," \t");
    if(token.size() < 10 ) break;
    molecule.m_atom.at(i).name=GetAtom(atoi(token.front().c_str()));
    std::stringstream str;
    str << i+1;
//    molecule.m_atom.at(i).label=str.str();
    StringTokenizer::iterator it;
    for(it=token.begin()+1;it!=token.begin()+12;++it)
    {
      int catom=atoi(it->c_str());
      if( catom  )
      {
        int bt=GetBondType(atoi((++it)->c_str()));
        if(bt)
        {
          molecule.m_atom.at(i).conexion.push_back(bond(catom-1,static_cast<bondtype>(bt)));
        }
      }
      else break;
    }
    //coordinates now
    molecule.m_atom.at(i).c.x=atof(token.at(13));
    molecule.m_atom.at(i).c.y=atof(token.at(14));
    molecule.m_atom.at(i).c.z=atof(token.at(15));
    i++;
  }
  molecule.SetKineticEnergy(0);
  molecule.SetPotentialEnergy(0.2390*venergy);
  molecule.CalculateMassCenter();
  m_molecule->push_back(molecule);

  bool hasconexions=true;
  do
  {
    //Get Energies
    StringTokenizer tok(line," \t=");
    if (tok.empty() )  break;
    StringTokenizer::iterator tt;
    if ( atoi(tok.front().c_str() ) < 0 ) hasconexions=false;
    for(tt=tok.begin();tt!=tok.end();++tt)
    {
      if ( *tt == "KE" )
        molecule.SetKineticEnergy(0.2390*atof((tt+1)->c_str()));
      if ( *tt == "PE" || *tt == "E" )
        molecule.SetPotentialEnergy(0.2390*atof((tt+1)->c_str()));
    }
    i=0;
    while(std::getline(*m_file,line))
    {


      StringTokenizer tok(line," \t");

      //std::cout << "coords = " << tok.at(1).c_str() << std::endl;
      if(!hasconexions)
      {
        molecule.m_atom.at(i).c.x=atof(tok.at(1).c_str());
        molecule.m_atom.at(i).c.y=atof(tok.at(2).c_str());
        molecule.m_atom.at(i).c.z=atof(tok.at(3).c_str());
      }
      else
      {
        molecule.m_atom.at(i).c.x=atof(tok.at(13).c_str());
        molecule.m_atom.at(i).c.y=atof(tok.at(14).c_str());
        molecule.m_atom.at(i).c.z=atof(tok.at(15).c_str());
      }
      i++;
      if( i == natoms ) break;
    }
    molecule.CalculateMassCenter();

    m_molecule->push_back(molecule);


  }
  while (std::getline(*m_file,line));
  //molecule.SetConexions();
  std::vector<CMolecule>::iterator mt;
  for(mt=m_molecule->begin();mt!=m_molecule->end();++mt)
  {
    std::cout << "PE=" << mt->PotentialEnergy() << " KE=" << mt->KineticEnergy() << std::endl;
  }
  return true;

}


MacroModelDynParser::~MacroModelDynParser()
{}

int MacroModelDynParser::GetBondType(int bt)
{
  switch(bt)
  {
  case 0:
    return 0;
  case 1:
  case 4:
    return 1;
  case 2:
    return 2;
  case 3:
    return 3;
  default:
    return 0;

  }
}
std::string MacroModelDynParser::GetAtom(int type)
{
  switch(type)
  {
  case 1:
  case 2:
  case 3:
  case 14:
    return "C";
  case 15:
  case 16:
  case 18:
  case 23:
    return "O";
  case 24:
  case 25:
  case 26:
  case 31:
  case 32:
  case 40:
    return "N";
  case 41:
  case 42:
  case 43:
  case 44:
  case 45:
  case 48:
    return "H";
  case 49:
  case 51:
  case 52:
    return "S";
  case 53:
    return "P";
  case 56:
    return "F";
  case 57:
    return "Cl";
  case 58:
    return "Br";
  case 59:
    return "I";
  case 60:
    return "Si";
  default:
    return "X";

  }
}


