/* massXpert - the true massist's program.
   --------------------------------------
   Copyright(C) 2006,2007 Filippo Rusconi

   http://www.massxpert.org/massXpert

   This file is part of the massXpert project.

   The massxpert project is the successor to the "GNU polyxmass"
   project that is an official GNU project package(see
   www.gnu.org). The massXpert project is not endorsed by the GNU
   project, although it is released ---in its entirety--- under the
   GNU General Public License. A huge part of the code in massXpert
   is actually a C++ rewrite of code in GNU polyxmass. As such
   massXpert was started at the Centre National de la Recherche
   Scientifique(FRANCE), that granted me the formal authorization to
   publish it under this Free Software License.

   This software is free software; you can redistribute it and/or
   modify it under the terms of the GNU  General Public
   License version 3, as published by the Free Software Foundation.
   

   This software is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this software; if not, write to the

   Free Software Foundation, Inc.,

   51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/


#ifndef IONIZABLE_HPP
#define IONIZABLE_HPP


/////////////////////// Qt includes
#include <QLocale>


/////////////////////// Local includes
#include "ponderable.hpp"
#include "polChemDefEntity.hpp"
#include "ionizeRule.hpp"

namespace massXpert
{

  //! The Ionizable class provides an ionizable Ponderable.
  /*! An ionizable is a Ponderable that might undergo ionization,
      using either its own member IonizeRule or an IonizerRule passed
      as argument to one of its functions. An Ionizable \em is also a
      PolChemDefEntity, as it has to know at each instant what polymer
      chemistry definition it is based upon. The ionization status of
      the Ionizable can be checked at each moment and a call to an
      ionizing function will first trigger deionization if the
      Ionizable is already ionized. The main members of the Ionizable
      class are the following:
      
      \li a IonizeRule;
      
      \li a boolean member stating if the entity has actually been
      ionized;
      
      Upon creation of an Ionizable(without use of the copy
      constructor), all the data required for the full qualification
      of the new instance should be passed to the constructor. Default
      parameters ensure that the Ionizable is set to a consistent
      status(that is its IonizeRule member is \em invalid and that
      its \c m_isIonized flag is false). 

      The caller is responsible for seeding correct and consistent
      values into the constructor for proper operation of the class
      instances.
      
      For the ionization to be actually performed, and the masses to
      be effectively updated to account for that ionization, the
      Ionizable instance must be ionize()'d.
      
      It is possible to deionize() an Ionizable instance as it is
      possible to reionize the instance with another IonizeRule, which
      will replace the member IonizeRule if the reionization
      succeeds. The deionize() call effects the state of the Ionizable
      instance only if the \c m_isIonized boolean is true.
  */
  class Ionizable : public PolChemDefEntity, public Ponderable
  {
  protected:
    //! IonizeRule that is used to ionize \c this Ionizable.
    IonizeRule m_ionizeRule;

    //! Indicates if \c this Ionizable has been effectively ionized.
    bool m_isIonized;
        
  public:
    Ionizable(const PolChemDef *, const QString & = QString("NOT_SET"),
	       const Ponderable & = Ponderable(), 
	       const IonizeRule & = IonizeRule(),
	       bool = false);
    
    Ionizable(const Ionizable &);

    virtual ~Ionizable();
  
    virtual Ionizable *clone() const;
    virtual void clone(Ionizable *) const;
    virtual void mold(const Ionizable &);
    virtual Ionizable & operator =(const Ionizable &);
  
    const IonizeRule &ionizeRule() const;
    IonizeRule *ionizeRule();

    bool isIonized() const;
    int setCharge(int);
    virtual int charge() const;
        
    virtual int ionize();
    virtual int ionize(const IonizeRule &);
    static int ionize(Ionizable *, const IonizeRule &);
    
    virtual int deionize();
    static int deionize(Ionizable *);

    virtual double molecularMass(MassType);
        
    bool validate();
            
    virtual bool operator ==(const Ionizable &) const;
    virtual bool operator !=(const Ionizable &) const;
  
    virtual bool calculateMasses();
  };

} // namespace massXpert


#endif // IONIZABLE_HPP  
