#ifndef MODEL_AS_MD_SUBJECT_H
#define MODEL_AS_MD_SUBJECT_H

#ifndef MD_SUBJECT_H
#include "MD_subject.h"
#endif

#ifndef MASS_H
#include "Mass.h"
#endif

#ifndef OWN_H
#include "Own.h"
#endif

#ifndef ATOM_CHUNK_H
#include "Atom_chunk.h"
#endif

#ifndef COLLECT_ENERGY_H
#include "Collect_energy.h"
#endif

#ifndef COLLECT_KINETIC_ENERGY_H
#include "Collect_kinetic_energy.h"
#endif

#ifndef COLLECT_POTENTIAL_H
#include "Collect_potential.h"
#endif

#ifndef POINT_3D_IMPL_H
#include "Point_3D_impl.h"
#endif

//#ifndef ATOM_GROUP_AS_MD_SUBJECT_H
//#include "Atom_group_as_md_subject.h"
//#endif

//#ifndef VECTOR_3D_IMPL_H
//#include "Vector_3D_impl.h"
//#endif

//#include <deque>

namespace MM
{
class Model;
//class Interaction;

class Model_as_md_subject : public MD_subject
{
    Model &                     model_;
    Own <Mass>                  masses_;
    //Interaction &               interaction_;
    //Atom_group_as_md_subject    atom_group_as_md_subject_;

    bool                        first_bad_iteration_;
    double                      lIforce_limit_;

    Array <double>              f_short_x_, f_short_y_, f_short_z_;
    Array <double>              f_long_x_,  f_long_y_,  f_long_z_;
    Array <double>              f_long2_x_, f_long2_y_, f_long2_z_;
    Array <double>              f_long3_x_, f_long3_y_, f_long3_z_;

    Array <double>              sum1_x_, sum1_y_, sum1_z_;
    Array <double>              sum2_x_, sum2_y_, sum2_z_;

    Array <Atom_chunk_small>    chunk1_, chunk2_;
    std::deque<Atom_chunk_big>  chunk3_;
    //std::deque <Point_3D_impl>       configuration_;
    //Array <Atom_chunk>          chunk1_, chunk2_, chunk3_;
    Array <Point_3D_impl>       configuration_;
    Collect_energy              H_monitor_;
    Collect_kinetic_energy      K_monitor_;
    Collect_potential           U_monitor_;

public:
    explicit Model_as_md_subject (Model & model);

    virtual void        start   ();
    virtual void        finish  ();

    virtual void        zero_virial ();
    virtual void        list   (Hint hint, double skin);
    virtual void        list   (Hint hint, double R, double skin);
    virtual double      degrees_of_freedom ();
    virtual double      H ();
    virtual double      K ();
    virtual double      U ();
    virtual void        F      (Hint hint = Whole);
    virtual void        F      (Hint hint, double R, double Switching);
    virtual void        clear_moment (Hint hint);
    virtual void        kick   (double dT, Hint hint);
    virtual void        kick   (int substeps, double dT, Hint hint);
    virtual void        drift  (double dT);
    virtual void        keep_configuration ();
    virtual void        restore_configuration ();
    virtual void        update (bool force = false);
    virtual bool        locked () const;
    virtual void        set_lock (bool on);
    virtual void        setup_velocities (Temperature_unit const& t);

    int                 list_1_size () const {return chunk1_.size();}
    int                 list_2_size () const {return chunk2_.size();}
    int                 list_3_size () const {return chunk3_.size();}

private:
    //void                update_interactions (Hint hint);
    void                cut_large_forces ();
    void                extract_long (Hint hint);
};

}//MM

#endif //MODEL_AS_MD_SUBJECT_H
