/*
    ChemCon - molecular mechanics and molecular graphics
    Copyright (C) 1998-2002  Alexei Nikitin

    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 "MOT.h"

//#include "Log.h"

#include "Path.h"
#include "Text.h"
//#include "resource.h"
//#include "error.h"
#include "ChemDefs.h"
#include "File_ptr.h"
#include "DbC.h"

#include <iostream>
#include <string.h>

//------------------- Base ---------------------------------
//................... Micro_object_type....................

Micro_object_type & 
mot ()
{
    static Micro_object_type instance;
    return instance;
}

Micro_object_type::
Micro_object_type ()
: 
    type_(0), counter_(0)  
{
//    load ((MM::Path::force_field() + "AMBER94_0_atom_types.xls").c_str());//fix
//    load ((MM::Path::force_field() + "OPLS-UA_0_atom_types.xls").c_str());//fix
    load ((MM::Path::force_field() + "OPLS_and_AMBER94_atom_types.xls").c_str());//fix
}

Micro_object_type::
~Micro_object_type ()
{
    for (int i=counter_-1;  i>=0;  i--) 
        delete [] type_[i];
    delete [] type_;
}


void  Micro_object_type::
load (const char * fileName)
{
    try 
    {
    char    buf[128];
    int     i;
    counter_ = 1;
    MM::File_ptr fp (fileName, "rt");

    fgets (buf, 128, fp);
    fgets (buf, 128, fp);
    while (fgets( buf, 127, fp ) != NULL) 
        counter_++;

    counter_ += 1;
    
    if (counter_ >= TYPE_N)
    {
        MM::Text message;
        message += "Types more then ";
        message += TYPE_N;
        message += " - ";
        message += counter_;
        message += ".";
        FLAW (message);
    }

    type_ = new char* [counter_];
    for (i=0;  i<counter_;  i++)
    {
        type_[i] = new char [TYPE_LEN];
        type_[i][0] = '\0';
    }

    fseek (fp, 0, SEEK_SET);
    fgets (buf, 128, fp);
    fgets (buf, 128, fp);

    mass_.resize (counter_);

    for (i=2;  i<counter_;  i++)
    {
        fgets  (buf, 128, fp);
        sscanf (buf, "%4s%lg", type_[i], &mass_[i]);
    }

    // #define undefined_type 0   in microsys.hpp
    type_[0][0] = '?';       type_[0][1] = '\0';
    // #define any_type       1   in microsys.hpp
    type_[1][0] = '*';       type_[1][1] = '*';       type_[1][2] = '\0';

#if TEST_DE
    cout << "\nTable of types in file " << fileName
        << "   "  << "counter = " << counter << endl;
    for (i=0;  i<counter;  i++)
        cout << Type[i] << endl;
#endif
    }//try
//    catch ( File_ptr::OpenError oe )
//                {  error(  "\nCan not open file ", oe.fName ); }
    catch (...)
        {throw;}
  }

void  Micro_object_type::
save (const char * fileName) const //fix
{
    try 
    {
        MM::File_ptr fp (fileName, "wt");

        fprintf (fp, "string\n");
        fprintf (fp, "Type\n");
        for (int i=0; i<counter_; i++) 
            fprintf (fp, "%s\n", type_[i]);
    }
//    catch ( FilePtr::OpenError oe )
//      {  error(  "\nCan not open file ", oe.fName ); }
    catch (...)
    {throw;}
  }

unsigned int  Micro_object_type::
atoi (const char * t) const
{
//fix    MM::CONTRACT REQUIRE ("MOT was initialized.", counter_ != 0);
    CONTRACT REQUIRE ("", t != 0);

    //MM::log () << " " << t << " =>";

    if (t == 0 || strlen (t) == 0)
        return undefined_type;

    for (int i=0;  i<counter_;  i++)
    {
        if (!strcmp (t, type_[i])) 
            return i;
        //MM::log () << " " << type_[i];
    }
    
    //MM::log () << " (" << counter_ << ");";
     
    return undefined_type;
}

const char *  Micro_object_type::
itoa (int i) const                     //fix
{
//fix    MM::CONTRACT REQUIRE ("MOT was initialized.", counter_ != 0);

    if (i == undefined_type)   return "?";
    if (i == any_type      )   return "*";
    return type_[i];
}

int Micro_object_type::
get_counter (void) const
{
    return  counter_;
}
