#include "Atom_group_as_md_subject.h"

#include "Atom.h"
#include "Atom_kit.h"
#include "Atom_group.h"
#include "Interaction.h"
#include "Mass.h"
#include "Vector_3D_impl.h"
#include "Profiler.h"

namespace MM
{

Atom_group_as_md_subject::
Atom_group_as_md_subject (Atom_group  & model,
                          Interaction & interaction,
                          Mass        * adoptee)
:   model_      (model),
    interaction_(interaction),
    masses_     (adoptee)
{
}

void Atom_group_as_md_subject::
drift (double dT)
{
    int size = model_.atom_count();

    for (int i=0;  i<size;  ++i)
    {
        // x = x0 + dT * v0
        Atom &          atom = model_.atom(i);

        if (atom.kit().was_frozen())
            continue;

        Vector_3D_impl  movement (atom.kit().velocity());
        movement *= dT;
        atom.move (movement);
    }
    //update_interactions ();
}

void Atom_group_as_md_subject::
F (Hint hint)
{
    update_interactions (hint);
}

void Atom_group_as_md_subject::
kick (double dT, Hint)
{
    //update_interactions (MD_subject::Whole);

    int size = model_.atom_count();

    for (int i=0;  i<size;  ++i)
    {
        // v = v0 + dT * F / m
        Atom &          atom = model_.atom(i);

        if (atom.kit().was_frozen())
            continue;

        Vector_3D_impl  dV (atom.kit().potential_force());
        dV *= dT * masses_().inverse(i);
        atom.kit().add_velocity (dV);
    }
}

void Atom_group_as_md_subject::
update (bool)
{
    profile().interactions___add_force___others ();

    int size = model_.atom_count();

    for (int i=0;  i<size;  ++i)
    {
        Atom & atom = model_.atom(i);
        atom.update ();
    }

    profile().update ();
}

void Atom_group_as_md_subject::
update_interactions (Hint/* hint*/)
{
    //fix describe
    //fix dynamic check or DbC
    int size = model_.atom_count();

    for (int i=0;  i<size;  ++i)
        model_.atom(i).kit().set_potential_force (Vector_3D_impl (0,0,0));

    interaction_.add_force ();
}

}//MM
