#ifndef MOLECULE_IMPL_H
#define MOLECULE_IMPL_H

#ifndef MOLECULE_H
#include "Molecule.h"
#endif

#ifndef RESIDUE_H
#include "Residue.h"
#endif

#ifndef ARRAY_OF_REF_H
#include "Array_of_ref.h"
#endif

//#ifndef ARRAY_OF_OWN_H
//#include "Array_of_own.h"
//#endif

#ifndef ATOM_H
#include "Atom.h"
#endif

namespace MM
{

class Molecule_impl : public Molecule
{
    mutable Text            local_id_;
    int                     mm_type_;
    Array_of_ref <Atom>     atoms_;
    Array_of_ref <Residue>  residues_;
    //Array_of_ref <Bond>     bonds_;
    Text                    name_;

public:
    Molecule_impl ();
    Molecule *              clone () const {return new Molecule_impl;}

    Text const&             local_id () const               {return local_id_;}
    void                    set_local_id (Text const& id) const;

    Text const &            name () const   {return name_;}

    // from class Atom_group
    virtual int             atom_count () const {return atoms_.size();}
    virtual Atom &          atom (int i)        {return atoms_[i];}
    virtual const Atom &    atom (int i) const  {return atoms_[i];}

    // from class Bond_group
    //int                     bond_count () const {return bonds_.size();}
    //Bond &                  bond (int i)        {return bonds_[i];}
    //const Bond &            bond (int i) const  {return bonds_[i];}

    // from class Molecule
    void                    add_atom (Atom & ref);
    void                    remove_atom (Atom & ref);
    void                    remove_dead_atoms ()    {atoms_.stable_remove_deads();}
    //void                    add_bond    (Bond & ref);
    //void                    remove_bond (Bond & ref);

    int                     mm_type () const        {return mm_type_;}
    void                    set_mm_type (int type)  {mm_type_ = type;}

    double                  mass () const;
    Text                    molecular_formula (Format format) const;
    double                  charge () const;

    int                     residue_count () const  {return residues_.size();}
    Residue &               residue (int n)         {return residues_[n];}
    Residue const &         residue (int n) const   {return residues_[n];}
    void                    remove_dead_residues () {residues_.stable_remove_deads();}
    void                    reset_residues();

    void                    clear_local_ids ();

    void                    move   (Vector_3D const & movement);
    void                    rotate (Vector_3D const & around, double teta);
};

}//MM

#endif //MOLECULE_IMPL_H
