#include "Atom_cartesian_coordinates.h"

#include "Atom_group.h"
#include "Flaw.h"
#include "Atom.h"

namespace MM
{

Atom_cartesian_coordinates::
Atom_cartesian_coordinates (Atom_group & atoms)
: 
    atoms_(atoms), coord_(0)
{
}

/*double Atom_cartesian_coordinates::
parameters_current () const
{
    switch( coord_ )
    {
        case 0:
            //return atoms_.current().x();
            return atoms_.current().x();
        case 1:
            return atoms_.current().y();
        case 2:
            return atoms_.current().z();

        default:
            FLAW( "coord_ is out of range" );
    }
}

bool Atom_cartesian_coordinates::
parameters_is_valid() const
{
    return atoms_.is_valid();
}

void Atom_cartesian_coordinates::
parameters_next() const
{
    REQUIRE( "Atom has 3 coordinates", coord_ >= 0 && coord_ < 3 );

    if( coord_ == 2 )
    {
        atoms_.next();
        coord_ = 0;
    }
    else
    {
        ++coord_;
    }

    ENSURE( "Atom has 3 coordinates", coord_ >= 0 && coord_ < 3 );
}

void Atom_cartesian_coordinates::
parameters_first() const
{
    atoms_.first();
}

int Atom_cartesian_coordinates::
parameters_size() const
{
    return 3 * atoms_.size();
}

void Atom_cartesian_coordinates::
parameters_add_to_current( double value )
{
    switch( coord_ )
    {
        case 0:
            atoms_.current().set_x( atoms_.current().x() + value );
            break;

        case 1:
            atoms_.current().set_y( atoms_.current().y() + value );
            break;

        case 2:
            atoms_.current().set_z( atoms_.current().z() + value );
            break;

        default:
            FLAW( "coord_ is out of range" );
    }
}

void Atom_cartesian_coordinates::
parameters_set_to_current( double value )
{
    switch( coord_ )
    {
        case 0:
            atoms_.current().set_x( value );
            break;

        case 1:
            atoms_.current().set_y( value );
            break;

        case 2:
            atoms_.current().set_z( value );
            break;

        default:
            FLAW( "coord_ is out of range" );
    }
}
//*/
double Atom_cartesian_coordinates::
value (int i) const
{
    switch (i%3)
    {
        case 0: return atoms_.atom(i/3).x();
        case 1: return atoms_.atom(i/3).y();
        case 2: return atoms_.atom(i/3).z();

        default: FLAW ("coord_ is out of range");
    }
}

void Atom_cartesian_coordinates::
set (double value, int i)
{
    switch (i%3)
    {
        case 0:
            atoms_.atom(i/3).set_x (value);
            break;
        case 1:
            atoms_.atom(i/3).set_y (value);
            break;
        case 2:
            atoms_.atom(i/3).set_z (value);
            break;

        default:
            FLAW ("coord_ is out of range");
    }
}

void Atom_cartesian_coordinates::
add (double value, int i)
{
    switch (i%3)
    {
        case 0:
            atoms_.atom(i/3).set_x (value + atoms_.atom(i/3).x()); //fix add atom.add_x ...
            break;                                        //atom.add( vector );
        case 1:
            atoms_.atom(i/3).set_y (value + atoms_.atom(i/3).y());
            break;
        case 2:
            atoms_.atom(i/3).set_z (value + atoms_.atom(i/3).z());
            break;

        default:
            FLAW ("coord_ is out of range");
    }
}

int Atom_cartesian_coordinates::
size () const 
{
    return 3*atoms_.atom_count();
}

}//MM
