#include "Selector.h"

#include "User.h"
#include "Atom_numerator.h"

#include "Atom.h"
#include "Atom_kit.h"
#include "Bond.h"
#include "Bond_kit.h"
#include "Model.h"
#include "Model_kit.h"

namespace MM
{
int                 Selector::max_picked_atoms_    = 1;
bool                Selector::numerate_atoms_flag_ = false;
Event_1 <Atom&>     Selector::atom_picked_;

void Selector::
when_atom_picked (Command_1 <Atom&> *adoptee, bool on)
{
    atom_picked_.subscribe (adoptee, on);
}

void Selector::
pick (Atom & atom)
{
//    if (atom.kit().is_picked())
    Own <Atom_numerator>    numerate;
    if (numerate_atoms_flag_)
        numerate.adopt (new Atom_numerator (model_));

    Atom_kit & kit = atom.kit();
    pick_queue_.push (&atom);
    pop ();
    kit.pick (true);

    //Atom_numerator numerate(model_);
    Text message;
    if (numerate_atoms_flag_)
    {
        message += "atom ";
        message += kit.number();
        message += "    ";
    }
    message += atom.element().c_str();
    message += "    ";
    message += atom.charge();
    message += " e";

    if (kit.has_mm_type())
    {
        message += "    ";
        message += kit.mm_type_c_str();
    }

    if (kit.has_fine_type())
    {
        message += "    ";
        message += kit.fine_type_name();
    }

    atom_picked_.publish (atom);
    to_user ().status (message);
}

void Selector::
pick (Bond & bond)
{
    //Bond_kit & kit = bond.kit();

    clear_picking ();

    for (int i=0;  i<bond.atom_count();  ++i)
    {
        bond.atom(i).kit().pick (true);
        pick_queue_.push (&bond.atom(i));
    }

    Text message;
    message += bond.order().c_str();
    message += "    ";

    to_user ().status (message);
}

void Selector::
clear_picking ()
{
    while (pick_queue_.size() > 0)
    {
        Atom * atom = pick_queue_.front();
        atom->kit().pick (false);
        pick_queue_.pop ();
    }
}

int Selector::
set_max_picked_atoms (int max)
{
    int old = max_picked_atoms_;
    max_picked_atoms_ = max;
    return old; 
}

void Selector::
pop ()
{
    while ((int)pick_queue_.size() > max_picked_atoms_)
    {
        pick_queue_.front()->kit().pick (false);
        pick_queue_.pop ();
    }
}

void Selector::
select (Atom & atom, bool on)
{
    Atom_kit & kit = atom.kit();
    kit.select (on);
    ++version_;
}

void Selector::
select (Bond & bond, bool on)
{
    Bond_kit & kit = bond.kit();
    kit.select (on);
    ++version_;
}

void Selector::
clear ()
{
    int count = model().atom_count();

    for (int i=0;  i<count;  ++i)
    {
        model().atom(i).kit().select (false);
        //model().atom(i).kit().pick   (false);
    }

    clear_picking ();
    ++version_;
}

void Selector::
invert_all ()
{
    int count = model().atom_count();

    for (int i=0;  i<count;  ++i)
    {
        Atom_kit & kit = model().atom(i).kit();
        kit.select (!kit.is_selected());
    }
    ++version_;
}

}//MM

