#include "Atom_group_cache.h"
#include "MOT.h"

namespace MM
{

Atom_group_cache::
Atom_group_cache (Atom_group & atom_group)
:
    atom_group_ (atom_group),
    cache_flag_ (false) 
{
}

Atom_group_cache::
~Atom_group_cache () 
{
}

/*void Atom_group_cache::
set_lock (bool on)
{
    if (on)
    {
        REQUIRE ("Unlocked.", !cache_flag_);
        cache_atoms ();
        cache_flag_ = true;
    }
    else
    {
        REQUIRE ("Locked.", cache_flag_);
        flush_force ();
        atom_.clear ();
        cache_flag_ = false;
    }
}//*/

void Atom_group_cache::
cache_atoms ()
{
    atom_.clear ();

    int i, count = atom_group_.atom_count();
    
    for (i=0;  i<count;  ++i) //fix flag___
    {
        Atom &     current = atom_group_.atom (i);
        Atom_kit & kit     = current.kit();
        Atom_cache atom;
        atom.x___           = current.x();
        atom.y___           = current.y();
        atom.z___           = current.z();

        Vector_3D const & force = kit.potential_force ();
        atom.force_x___     = force.x();
        atom.force_y___     = force.y();
        atom.force_z___     = force.z();

        Vector_3D const & bond_stretch_force = kit.bond_stretch_force ();
        atom.F_bond_stretch_x___ = bond_stretch_force.x();
        atom.F_bond_stretch_y___ = bond_stretch_force.y();
        atom.F_bond_stretch_z___ = bond_stretch_force.z();

        Vector_3D const & angle_force = kit.angle_force ();
        atom.F_angle_x___        = angle_force.x();
        atom.F_angle_y___        = angle_force.y();
        atom.F_angle_z___        = angle_force.z();

        Vector_3D const & torsion_force = kit.torsion_force ();
        atom.F_torsion_x___      = torsion_force.x();
        atom.F_torsion_y___      = torsion_force.y();
        atom.F_torsion_z___      = torsion_force.z();

        Vector_3D const & improper_force = kit.improper_force ();
        atom.F_improper_x___     = improper_force.x();
        atom.F_improper_y___     = improper_force.y();
        atom.F_improper_z___     = improper_force.z();

        Vector_3D const & nonbonded_force = kit.nonbonded_force ();
        atom.F_nonbonded_x___    = nonbonded_force.x();
        atom.F_nonbonded_y___    = nonbonded_force.y();
        atom.F_nonbonded_z___    = nonbonded_force.z();

        //Vector_3D const & short_nonbonded_force = kit.short_nonbonded_force ();
        //atom.FS_nonbonded_x___   = short_nonbonded_force.x();
        //atom.FS_nonbonded_y___   = short_nonbonded_force.y();
        //atom.FS_nonbonded_z___   = short_nonbonded_force.z();

        //Vector_3D const & long_nonbonded_force = kit.long_nonbonded_force ();
        //atom.FL_nonbonded_x___   = long_nonbonded_force.x();
        //atom.FL_nonbonded_y___   = long_nonbonded_force.y();
        //atom.FL_nonbonded_z___   = long_nonbonded_force.z();

        atom.charge___           = current.charge();
        atom.induction_charge___ = kit.induction_charge ();
        //atom.born_radius___ = kit.born_radius();
        //atom.d_born_radius___ = 0;
        //atom.V___           = kit.volume();
        //atom.Gpol___        = kit.Gpol();              //fix
        //atom.Gpol13___      = kit.Gpol13();              //fix
        atom.transparency___= 1.;
        atom.mm_type___     = kit.mm_type();
        //atom.number___    = model__.atom(i).number_;

        atom.number___      = i;
        atom.origin___      = &atom_group_.atom (i);
        atom.mol___         = &kit.in_molecule();

        atom_.push_back (atom);

        //atom_.back ().short_list___.reserve (100);
    }//*/

    int stubs = 3;
    //int stubs = 30;

   
    for (i=0;  i<stubs;  ++i)
    {
        Atom_cache atom;
        atom.x___           = 123456789;
        atom.y___           = 0;
        atom.z___           = 0;

        atom.force_x___     = 0;
        atom.force_y___     = 0;
        atom.force_z___     = 0;

        atom.charge___      = 0.;
        atom.induction_charge___ = 0.;
        //atom.born_radius___ = 0;
        //atom.d_born_radius___ = 0;
        //atom.V___           = 0;
        //atom.Gpol___        = 0;
        //atom.Gpol13___      = 0;
        atom.transparency___= 0.;
        atom.mm_type___     = Micro_object_type::undefined_type;

        atom.number___      = -1;//fix
        atom.origin___      = &Atom::none();
        atom.mol___         = 0;

        atom_.push_back (atom);
    }//*/

    for (i=0;  i<count;  ++i)
    {
        Atom &     current = atom_group_.atom (i);
        Atom_kit & kit     = current.kit();
        kit.cache___ = &atom_[i];
    }
}

void Atom_group_cache::
flush_coords ()
{
    if (atom_.size() == 0)
        return;

    int i, count = atom_group_.atom_count();
    
    for (i=0;  i<count;  ++i)
    {
        Atom_cache & cache = atom_[i];
        Atom & atom = atom_group_.atom (i);
        //atom.set_x (cache.x___);
        //atom.set_y (cache.y___);
        //atom.set_z (cache.z___);
        atom.set_position_silent (cache.x___, cache.y___, cache.z___);
    }
}

void Atom_group_cache::
flush_force ()
{
    //fix REQUIRE ("Cached", atom_.size() != 0);
    if (atom_.size() == 0)
        return;

    int i, count = atom_group_.atom_count();
    
    for (i=0;  i<count;  ++i)
    {
        Atom_cache & a   = atom_[i];
        Atom_kit   & kit = atom_group_.atom (i).kit();

        {
        Vector_3D_impl f (a.force_x___, a.force_y___, a.force_z___);
        kit.set_potential_force (f);
        }
        {
        Vector_3D_impl f (a.F_bond_stretch_x___, a.F_bond_stretch_y___, a.F_bond_stretch_z___);
        kit.set_bond_stretch_force (f);
        }
        {
        Vector_3D_impl f (a.F_angle_x___, a.F_angle_y___, a.F_angle_z___);
        kit.set_angle_force (f);
        }
        {
        Vector_3D_impl f (a.F_torsion_x___, a.F_torsion_y___, a.F_torsion_z___);
        kit.set_torsion_force (f);
        }
        {
        Vector_3D_impl f (a.F_improper_x___, a.F_improper_y___, a.F_improper_z___);
        kit.set_improper_force (f);
        }
        {
        Vector_3D_impl f (a.F_nonbonded_x___, a.F_nonbonded_y___, a.F_nonbonded_z___);
        kit.set_nonbonded_force (f);
        }
        //{
        //Vector_3D_impl f (a.FS_nonbonded_x___, a.FS_nonbonded_y___, a.FS_nonbonded_z___);
        //atom_group_.atom (i).kit().set_short_nonbonded_force (f);
        //}
        //{
        //Vector_3D_impl f (a.FL_nonbonded_x___, a.FL_nonbonded_y___, a.FL_nonbonded_z___);
        //atom_group_.atom (i).kit().set_long_nonbonded_force (f);
        //}
    }
}

//void Atom_group_cache::
//flush_born ()
//{
//    //fix REQUIRE ("Cached", atom_.size() != 0);
//    if (atom_.size() == 0)
//        return;
//
//    int i, count = atom_group_.atom_count();
//    
//    for (i=0;  i<count;  ++i)
//    {
//        Atom_cache & atom = atom_[i];
//        atom_group_.atom (i).kit().set_born_radius (atom.born_radius___);
//        atom_group_.atom (i).kit().set_volume (atom.V___);
//        atom_group_.atom (i).kit().set_Gpol (atom.Gpol___);
//        atom_group_.atom (i).kit().set_Gpol13 (atom.Gpol13___);
//    }
//}

}//MM
