#ifndef ATOM_CACHE_H
#define ATOM_CACHE_H

#ifndef FLAG_H
#include "Flag.h"
#endif

#ifndef ATOM_H
#include "Atom.h"
#endif

#ifndef ATOM_KIT_H
#include "Atom_kit.h"
#endif

#ifndef BOND_H
#include "Bond.h"
#endif

#ifndef BOND_KIT_H
#include "Bond_kit.h"
#endif

#ifndef ARRAY_H
#include "Array.h"
#endif

//#ifndef NEXT_ATOM_H
//#include "Next_atom.h"
//#endif

namespace MM
{
struct Bond_cache;

struct Atom_cache
{
#ifndef NDEBUG
    virtual ~Atom_cache ()
    {
        x___ = y___ = z___ = 0;
        F_nonbonded_x___ = F_nonbonded_y___ =  F_nonbonded_z___ = 0;
        force_x___ = force_y___ = force_z___ = 0;
        origin___ = 0;
        mol___    = 0;
        number___ = -1;
    }
#endif

    /*enum   //fix remove unnecessary
    {
        already_used = 1,
        mark_1_2 = 2,
        mark_1_3 = 4,
        mark_1_4 = 8,
        hetero = 16,
        has_improper_torsion = 32,
        united = 64,
        selected = 128,
        coords_was_changed = 256,
        already_calculated = 512,
        missed = 1024
    };//*/

    double          x___, y___, z___;
    double          F_nonbonded_x___,    F_nonbonded_y___,    F_nonbonded_z___;
    double          force_x___,          force_y___,          force_z___;
    double          F_bond_stretch_x___, F_bond_stretch_y___, F_bond_stretch_z___;
    double          F_angle_x___,        F_angle_y___,        F_angle_z___;
    double          F_torsion_x___,      F_torsion_y___,      F_torsion_z___;
    double          F_improper_x___,     F_improper_y___,     F_improper_z___;
    //double          FS_nonbonded_x___,   FS_nonbonded_y___,   FS_nonbonded_z___;
    //double          FL_nonbonded_x___,   FL_nonbonded_y___,   FL_nonbonded_z___;
    double          charge___;
    double          induction_charge___;
    mutable double  transparency___;
    //float           x___, y___, z___;
    //float           charge___;
    int             mm_type___;
    mutable Flag    flag___;
    Atom          * origin___;
    int             number___;
    Molecule const* mol___;

    double              x () const {return x___;}
    double              y () const {return y___;}
    double              z () const {return z___;}

    Atom_cache &        bound (int i)       {return *origin___->bound (i).kit().cache___;} //fix cache
    Atom_cache const &  bound (int i) const {return *origin___->bound (i).kit().cache___;} //fix cache
    int                 bound_count() const {return  origin___->bound_count();}
    Bond_cache &        bond  (int i)       {return *origin___->bond (i).kit().cache___;}
    Bond_cache const &  bond  (int i) const {return *origin___->bond (i).kit().cache___;}
};

}//MM

#endif //ATOM_CACHE_H
