#ifndef MOLMECCANO_FILE_H
#define MOLMECCANO_FILE_H

#ifdef MM_WIN32
#pragma warning (disable : 4786)
#endif

#include <iosfwd>
#include <string>
#include <map>
#include <vector>

#ifndef MODEL_FILE_H
#include "Model_file.h"
#endif

#ifndef MOLECULE_H
#include "Molecule.h"
#endif

#ifndef RESIDUE_H
#include "Residue.h"
#endif

#ifndef TORSION_LIST_H
#include "Torsion_list.h"
#endif

#ifndef TEXT_H
#include "Text.h"
#endif

namespace MM
{

class MolMeccano_file : public Model_file
{
    static bool apply_torsions_;
    int         line_counter_;
    int         local_line_counter_;
    void    (MolMeccano_file::*read_data_line_function_)(std::string & line);

    std::string                         first_table_line_;
    std::string                         second_table_line_;
    //std::string                       third_table_line_;
    std::map <std::string, Atom*>       atom_map_;
    std::map <std::string, Molecule*>   molecular_map_;
    std::map <std::string, Residue*>    residue_map_;
    std::vector <std::string>           mm_types_column_;

    bool                                end_reached_;
    bool                                detect_molecules_;
    bool                                set_residues_;

    Torsion_list                        torsion_list_;
    Text                                FF_;

    static MolMeccano_file              prototype_;

public:
    explicit            MolMeccano_file (Prototype const &);
    explicit            MolMeccano_file (Model & model);
    Model_file *        clone (Model & model) const;
    Text const &        type_name       ()      const;

    bool                support_input     () const {return true;}
    bool                support_output    () const {return true;}
    bool                support_bonds     () const {return true;}
    bool                support_molecules () const {return true;}

    void                save (bool to_comment);
    void                add  (Text const & file_name);
    //void                clear();

    Torsion_list &      torsion_list () {return torsion_list_;}
    static void         apply_torsions (bool on) {apply_torsions_ = on;}

protected:
    void                check_file_name ();

private:
    bool            next_line       (std::ifstream & in, std::string & line);
    void            read_title_line (std::ifstream & in, std::string & line);
    void            read_data_line  (std::ifstream & in, std::string & line);

    void            read_Model          (std::istringstream & in);
    void            read_Alias          (std::istringstream & in);
    void            read_Short_alias    (std::istringstream & in);
    void            read_Comment_line   (std::istringstream & in);
    void            read_ForceField     (std::istringstream & in);
    void            read_Box            (std::istringstream & in);
    void            read_End            (std::istringstream & in);

    void            read_Atoms              (std::string & line);
    void            read_Bonds              (std::string & line);
    void            read_Residues           (std::string & line);
    void            read_Joints             (std::string & line);
    void            read_Restraints         (std::string & line);
    void            read_Torsion_types      (std::string & line);
    void            read_Torsions           (std::string & line);
    void            read_Distances          (std::string & line);
    void            read_Angles             (std::string & line);
    void            read_Dihedrals          (std::string & line);
    void            read_Groups             (std::string & line);

    void            read_MM_types_columns   (std::string & line);
    void            read_MM_types           (std::string & line);
};

}//MM

#endif //MOLMECCANO_FILE_H
