/***************************************************************************
 *   Copyright (C) 2004 by Armando Navarro Vázquez                         *
 *   armando@rmntec                                                        *
 *                                                                         *
 *   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 <iostream>
#include <sstream>


#include "psi3parser.h"
#include "tokenizer.h"
#include "molecule.h"

const double bohrtoangs=0.529189379;

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

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

Psi3Parser::~Psi3Parser()
{
}

bool Psi3Parser::ParseFile(std::streampos pos/*0*/)
{
  return GetGeometry();
}

bool Psi3Parser::GetGeometry()
{

  std::string	line;
  std::vector<std::streampos> steps;
  while(std::getline(*m_file,line))
  {
     std::streampos pos=m_file->tellg();
     if(line.find("Cartesian geometry and possibly gradient",0)!=std::string::npos )
     {
       steps.push_back(pos);
     }
  }
  bool singlepoint=false;
  
  m_file->clear();
  m_file->seekg(0);
  
  if( steps.size() == 0 )
 {
   singlepoint=true;
   bool bfound=false;
     while(std::getline(*m_file,line))
  {
     std::streampos pos=m_file->tellg();
     if(line.find("Geometry in the reference coordinate system (a.u.)",0)!=std::string::npos )
     {
       steps.push_back(pos);
       bfound=true;
     }
     if(bfound) break;
  }
 }
 
  std::vector<std::streampos>::iterator it;
  size_t cols=5;
  if( singlepoint)
  {
    std::getline(*m_file,line);
    std::getline(*m_file,line);
    cols=4;
  }
  else
  {
    m_file->clear();
    m_file->seekg(0,std::ios::beg);
  }
  for(it=steps.begin();it!=steps.end();it++)
  {
    CMolecule molecule;
    if(!singlepoint)
      m_file->seekg(*it,std::ios::beg);
    while(std::getline(*m_file,line))
    {
    
     StringTokenizer token(line," \t");
     size_t size=token.size();
     std::stringstream label;
     int counter=0;

     if(token.size() == cols)
     {
       counter++;
       CAtom atom;
       atom.c.x=bohrtoangs*std::atof(token[size-3].c_str());
       atom.c.y=bohrtoangs*std::atof(token[size-2].c_str());
       atom.c.z=bohrtoangs*std::atof(token[size-1].c_str());
       label << counter;
//       atom.label=label.str();
       if(counter == 1 )
         atom.name="O";//CMolecule::GetAtomName(std::atoi(token[0].c_str()));
       else atom.name="H";
       molecule.m_atom.push_back(atom);
     }
     else
       break;
    }
    molecule.SetConexions();
    m_molecule->push_back(molecule);
  }

  return true;
}

bool Psi3Parser::ParseFrequencies(std::streampos pos)
{
  m_file->clear();
  m_file->seekg(pos,std::ios::beg);
  if( !GetFrequencies()) return false;
  else return true;
 /* m_file->clear();
  m_file->seekg(pos,std::ios::beg);
  //Ok lets get the vectors;
  scounter=0;
  std::string line;
  CMolecule& molecule=m_molecule->back();
  molecule.AllocateVectors();
  while(std::getline(*m_file,line))
  {
    StringTokenizer token(line," ");
    if(token.size() >=2)
      if ( token[1]=="AN" )
      {

        GetVectors();
      }
  }

  return true;*/
  
}

bool Psi3Parser::GetFrequencies()
{
  CMolecule& molecule=m_molecule->back();

  std::vector<frequency>& frequencies=molecule.GetFrequencies();

  std::string line;
  //rewind

  size_t counter=0;
  size_t counter1=0;
  size_t counter2=0;
  bool bfound=false;
  while(std::getline(*m_file,line))
  {
    std::cout << line << std::endl;
    if ( line.find("Infrared Intensity") != std::string::npos )
      bfound =true;
    if(bfound) break;
  }
  
  if(!bfound) return false;
  
  std::getline(*m_file,line);
  std::getline(*m_file,line);
  std::getline(*m_file,line);
  std::cout << "line is " << std::endl;
  int nmodes=molecule.GetNVib();
  int modes=0;
  do
  {
   StringTokenizer tok(line," \t\n");
   if( tok.size() == 3 && modes < nmodes )
   {  
   frequencies.push_back( frequency( atof(tok[1].c_str()),atof(tok[2].c_str()) ) );
   std::cout << "freq=" << frequencies.back().x << " Ins " << frequencies.back().y << std::endl;
   modes++;
   }
   else break;
  }  while(std::getline(*m_file,line));
  

  return true;
}

std::vector<Quantum::jobheader>& Psi3Parser::GetJobs()
{
  Quantum::jobtype tjob=Quantum::dens;
  std::string line;
  bool bfound=false;
  while(std::getline(*m_file,line))
  {

      if(line.find("CPHF") != std::string::npos) tjob=Quantum::freq;
      {
        tjob=Quantum::freq;
        bfound=true;
      }
       if(bfound) break;

  }
  
  m_jobpos.push_back(Quantum::jobheader(tjob,m_file->tellg()));
  return m_jobpos;
}
