#include "Molecular_sequence_impl.h"

#include "Atom.h"
#include "Atom_kit.h"
#include "Model.h"
#include "Molecule.h"

namespace MM
{
Molecular_sequence_impl::
Molecular_sequence_impl (Model & model)
:
    model_(model)
{
    reset (Model_event::Structure_changed);
}

void Molecular_sequence_impl::
reset (Model_event::Hint)
{
    type_.clear ();

    for (int i=0;  i<model_.molecule_count();  ++i)
    {
        bool flag = false;

        // Add to appropriate type
        for (int j=0;  j<type_.size();  ++j)
        {
            if (has_the_same_type (model_.molecule(i),type_[j].molecule(0)))
            {
                type_[j].add (model_.molecule(i));
                flag = true;
                break;
            }
        }

        if (flag)
            continue;

        //if not found
        type_.push_back  (Molecular_type());
        type_.back().add (model_.molecule(i));
    }
}

bool Molecular_sequence_impl::
has_the_same_type (Molecule const & first_mol, Molecule const & second_mol)
{
    if (first_mol.atom_count () != second_mol.atom_count () )
        return false;

    int i;

    for (i=0;  i<first_mol.atom_count();  ++i)
    {
        first_mol. atom (i).kit().set_number (i);
        second_mol.atom (i).kit().set_number (i);
    }

    for (i=0;  i<first_mol.atom_count();  ++i)
    {
        const Atom & atom_1 = first_mol. atom (i);
        const Atom & atom_2 = second_mol.atom (i);

        if (atom_1.element()     != atom_2.element() ||
            atom_1.bound_count() != atom_2.bound_count())
            return false;

        for (int j=0;  j<atom_1.bound_count();  ++j)
            if (atom_1.bound(j).kit().number() != 
                atom_2.bound(j).kit().number())
            return false;
    }

    #ifndef NDEBUG                                  
    for (i=0;  i<first_mol.atom_count();  ++i)
    {
        first_mol. atom (i).kit().set_number (-1);
        second_mol.atom (i).kit().set_number (-1);
    }
    #endif

    return true;
}

}//MM
