/***************************************************************************
 *   Copyright (C) 2005 by Armando Navarro-Vazquez                         *
 *   armando@linux                                                         *
 *                                                                         *
 *   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 "maestroparser.h"
#include "molecule.h"
#include "tokenizer.h"

MaestroParser::MaestroParser(const char* file)
    : QuantumParser(file)
{}

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

MaestroParser::~MaestroParser()
{}

bool MaestroParser::ParseFile(std::streampos pos)
{
  m_file->clear();
  m_file->seekg(pos);
  GetGeometries();
}

void MaestroParser::GetGeometries()
{
  std::string line;
  while(std::getline(*m_file,line))
  {
    if (line.find("f_m_ct") != std::string::npos)
    {
      GetBlock(true);
    }
    if (line.find("p_m_ct") != std::string::npos)
    {
      GetBlock(false);
    }
  }

  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;
  }
}


void MaestroParser::GetBlock(bool full)
{
  int counter=0;
  bool hasenergy=false;
  std::string line;
  CMolecule molecule;
  if (!full) molecule=m_molecule->back();
  while(std::getline(*m_file,line))
  {
    if (!hasenergy)
      counter++;
    if (line.find("Potential_Energy") != std::string::npos) hasenergy=true;
    if (line.find(":::") != std::string::npos) break;
  }
  if (hasenergy)
  {
    
    for(int i=0;i<counter;i++)
    {
      std::getline(*m_file,line);
    }

   StringTokenizer token(line," \t\r");
   molecule.SetPotentialEnergy(atof(token.back().c_str())*0.2390);
   
  }
  //find the atoms
  while(std::getline(*m_file,line))
  {
   if (line.find("m_atom") != std::string::npos)
   {
     StringTokenizer token(line," \t\r[]{}");
     std::cout << " new molecule " << std::endl;
     molecule.m_atom.resize(atoi(token.back().c_str()));
     goto lb;
   }

  }
lb:
  while( std::getline(*m_file,line))
  {
    if (line.find(":::") != std::string::npos) break;

  }

  //OK lets do the parsering
  while( std::getline(*m_file,line))
  {
   if (line.find(":::") != std::string::npos ) break;
   StringTokenizer token(line," \t\r");
   // std::cout << atoi(token.at(0).c_str()) << " " << atoi(token.at(1).c_str())  << " " << atof(token.at(2).c_str()) << " " << std::endl;
   CAtom& atom=molecule.m_atom.at(atoi(token.at(0).c_str())-1);
   if (!full)
   {
   atom.XYZ().x=atof(token.at(1).c_str());
   atom.XYZ().y=atof(token.at(2).c_str());
   atom.XYZ().z=atof(token.at(3).c_str());
   }
   else
   {
//   atom.label=token.at(0);
   atom.SetZ(AtomType(atoi(token.at(1).c_str())));
   atom.XYZ().x=atof(token.at(2).c_str());
   atom.XYZ().y=atof(token.at(3).c_str());
   atom.XYZ().z=atof(token.at(4).c_str());
   }
     //std::cout << atoi(token.at(0).c_str()) << " " << atoi(token.at(1).c_str())  << " " << AtomType(atoi(token.at(1).c_str())) << atom.name << std::endl;
  if (line.find(":::") != std::string::npos ) break;
  }
  if (full)
    molecule.SetConexions();
  m_molecule->push_back(molecule);
}

int MaestroParser::AtomType(int type)
{
  switch(type)
  {
  case 1: //carbon sp
  case 2:  //carbon sp2
  case 3:  //carbon sp3
    return 6;
  case 4:  //UA CH-sp3
  case 5:  //UA CH2-sp3
  case 6:  //UA CH3-sp3
  case 7:  //UA CH-sp2
  case 8:  //UA CH2-sp2
  case 9:  //UA CH-sp
    //throw error("Not support yet for united atoms");
    return -1;
  case 10: //C-
  case 11: //C+
  case 12: //C
  case 14: //any carbon
    return 6;  //carbon sp2
  case 15: //O single bond
  case 16: //O single bond
    return 8;
  case 17:
   // throw error("Not support yet for united atoms");
    return -1;
  case 18: //O-
    return 8;
  case 19: //H2O united ignore
    return 0;
  case 20: //R2=O+
  case 21: //R3O+
  case 23: //any oxygen
    return 8;
  case 24: //N sp
  case 25: //N sp2
  case 26: //N sp3
    return 7;
  case 27:  //UA NH-sp3
  case 28:  //UA NH2-sp3
  case 29:  //UA NH-sp2
  case 30:  //UA NH2-sp2
   // throw error("Not support yet for united atoms");
    return -1;
  case 31:  //N+-sp2
  case 32:  //N+-sp3
    return 7;
  case 33:  //UA NH+-sp3
  case 34:  //UA NH2+-sp3
  case 35:  //UA NH3+-sp3
  case 36: //UA NH+-sp2
  case 37: //UA NH2+-sp2
   // throw error("Not support yet for united atoms");
    return -1;
  case 38: //N- sp3
  case 39: //N- sp2
  case 40: //Any nitrogen
    return 7;
  case 41: //H-Electroneut (C,S)
  case 42: //H-O
  case 43: //H-N
  case 44: //H-cation
  case 45: //H-Anion
  case 48: //Any hydrogen
    return 1;
  case 49: //sulfur
    return 16;
  case 50: //United atom SH
 //   throw error("Not support yet for united atoms");
    return -1;
  case 51: //S-
  case 52: //any sulphur
    return 16;
  case 53: //P
    return 15;
  case 54: //B sp2
  case 55: //B sp3
    return 5;
  case 56: //F
    return 9;
  case 57: //Cl
    return 17;
  case 58: //Br
    return 35;
  case 59: //I
    return 53;
  case 60: //Si
    return 14;
  case 61: //dummy atom for FEP
  case 62: //Special atom to be defined
  case 63: //Lp
  case 64: //Any atom
    return 0;
  case 65: //Li+
    return 3;
  case 66: //Na++
    return 11;
  case 67: //K+
    return 19;
  case 68://Rb+
    return 37;
  case 69: //Cs+
    return 55;
  case 70: //Ca++
    return 20;
  case 71: //Ba++
    return 56;
  case 72: //Mg++
    return 12;
  case 73: //Mn+2
  case 74: //Mn+3
  case 75: //Mn+4
  case 76: //Mn+5
  case 77: //Mn+6
  case 78: //Mn+7
    return 25;
  case 79: //Fe+2
  case 80: //Fe+3
    return 26;
  case 81: //Co+2
  case 82: //Co+3
    return 27;
  case 83: //Ni+2
  case 84: //Ni+3
    return 28;
  case 85: //Cu+
  case 86: //Cu+2
    return 29;
  case 87: //Zn+2
    return 30;
  case 88: //Mo+3
  case 89: //Mo+4
  case 90: //Mo+5
  case 91: //Mo+6
    return 42;
  case 100: //S+
  case 101: //S sp2
    return 16;
  case 102: //Cl-
    return 17;
  default:
    return 0;
  }
}

