/* 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 IONIZE_RULE_HPP
#define IONIZE_RULE_HPP


/////////////////////// Local includes
#include "formula.hpp"


namespace massXpert
{

  //! The IonizeRule class provides an ionization rule.
  /*! Ionizations are chemical reactions that bring a charge(or more
    charges) to an analyte. The chemical reaction is described by the
    inherited Formula class. The electric charge that is brought by
    this reaction is described by a member of the class, charge. It
    might happen that for polymers, ionization reactions might occur
    more than once. This is described by one member of the class,
    level.

    For example, in protein chemistry, the ionization reaction is
    mainly a protonation reaction, which brings ---per reaction--- a
    single charge. Thus, the Formula would be "+H" and the charge
    1. In MALDI, we would have a single protonation, thus level would
    be 1 by default. In electrospray ionization, more than one
    ionization reaction occurs, and we could have a level value of 25,
    for example. 

    Note that both charge and level should be positive values, since
    the real nature of the ionization is beared by the Formula(with
    "+H" for protonation in protein chemistry and "-H" for
    deprotonation in nucleic acids chemistry, for example).

    Thus, an IonizeRule is valid if it generates a m/z ratio after
    ionization of the analyte that is different than the previous(M)
    and if its Formula validates.  This means that the following
    should be true:

    \li The Formula should be valid(that is should contain at least
    one atom(use a 0-weighing atom if necessary, like Nul from the
    polymer chemistry definitions shipped with the software);

    \li The charge is > 0(the ionization event should bring one
    charge, otherwise there is no ionization. To reset the ionization
    to 0(that is to deionize the analyte, set the level to 0);
    
    \li The level is >= 0(if the level is 0, then the analyte is
    considered not ionized);

    Note that we do not consider compulsory that the Formula brings
    atoms whatsoever, because some ionizations might not involve heavy
    mass transfers, like electron gain or electron loss.
  */
  class IonizeRule : public Formula
  {
  private:
    //! Charge brought by one ionization reaction.
    int m_charge;

    //! Level at which the ionization reaction should occur, that is
    //the number of times the ionization should occur(can be 0, in
    //which case the analyte is deionized).
    int m_level;

    //! Indicates if \c this IonizeRule is valid. Set only after a
    //! call to validate().
    bool m_isValid;
    
  public:
    IonizeRule();
    IonizeRule(const IonizeRule &);

    IonizeRule *clone() const;
    void clone(IonizeRule *) const;
    void mold(const IonizeRule &);
    IonizeRule & operator =(const IonizeRule &);
  
    void setCharge(int);
    int charge() const;

    void setLevel(int);
    int level() const;

    QString formula() const;
    
    bool operator ==(const IonizeRule &) const;
    bool operator !=(const IonizeRule &) const;

    bool validate(const QList<Atom *> &);
    bool isValid() const;
  
    bool renderXmlIonizeRuleElement(const QDomElement &);
  
    QString *formatXmlIonizeRuleElement(int , 
					 const QString & = QString("  "));

    void debugPutStdErr();
  };

} // namespace massXpert


#endif // IONIZE_RULE_HPP
