#ifndef BOX_IMPL_H
#define BOX_IMPL_H

#ifndef BOX_H
#include "Box.h"
#endif

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

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

#ifndef EVENT_H
#include "Event.h"
#endif

#ifndef DBC_H
#include "DbC.h"
#endif


namespace MM
{

class Box_impl : public Box, protected DbC
{
    Point_3D_impl       o_;
    Vector_3D_impl      a_, b_, c_;
    Event               was_changed_;

    static const double default_L_;

public:
    Box_impl();

    bool                is_default () const;
    bool                is_rectangular () const;
    double              volume () const;

    Point_3D  const &   o () const              {return o_;}
    Vector_3D const &   a () const              {return a_;}
    Vector_3D const &   b () const              {return b_;}
    Vector_3D const &   c () const              {return c_;}

    double              a_mod () const          {return a_.length();}
    double              b_mod () const          {return b_.length();}
    double              c_mod () const          {return c_.length();}

    double              a_mod_rectangle () const {return a_.length();}
    double              b_mod_rectangle () const;
    double              c_mod_rectangle () const;

    double              alpha () const;
    double              beta  () const;
    double              gamma () const;

    void                set_o (Point_3D const & new_o);

    void                set (Vector_3D const & new_a,
                             Vector_3D const & new_b,
                             Vector_3D const & new_c);

    void                set (double new_a,
                             double new_b,    
                             double new_c,
                             double new_alpha, 
                             double new_beta, 
                             double new_gamma);

    void                set (double new_a,
                             double new_b,    
                             double new_c);

    void                scale_a (double k)      {a_*=k; was_changed_.publish();}
    void                scale_b (double k)      {b_*=k; was_changed_.publish();}
    void                scale_c (double k)      {c_*=k; was_changed_.publish();}

    void                fit (Atom_group const &, Shape, double margin);

    //Command *           when_changed (Command * to_do, bool on) {}//fix on all lavels
    //void                cancel_when_changed_reaction (){}

protected:
    bool                invariant () const;
};

}//MM

#endif //BOX_IMPL_H
