/* BEGIN software license
 *
 * msXpertSuite - mass spectrometry software suite
 * -----------------------------------------------
 * Copyright(C) 2009,...,2018 Filippo Rusconi
 *
 * http://www.msxpertsuite.org
 *
 * This file is part of the msXpertSuite project.
 *
 * The msXpertSuite project is the successor of the massXpert project. This
 * project now includes various independent modules:
 *
 * - massXpert, model polymer chemistries and simulate mass spectrometric data;
 * - mineXpert, a powerful TIC chromatogram/mass spectrum viewer/miner;
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 program. If not, see <http://www.gnu.org/licenses/>.
 *
 * END software license
 */


#ifndef IONIZE_RULE_HPP
#define IONIZE_RULE_HPP


/////////////////////// Local includes
#include <libmass/Formula.hpp>


namespace msXpSlibmass
{

//! 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;
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Woverloaded-virtual"

  void clone(IonizeRule *) const;
  void mold(const IonizeRule &);
#pragma clang diagnostic pop

  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;

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Woverloaded-virtual"
  bool validate(const QList<Atom *> &);
#pragma clang diagnostic pop

  bool isValid() const;

  bool renderXmlIonizeRuleElement(const QDomElement &);

  QString *formatXmlIonizeRuleElement(int, const QString & = QString("  "));

  void debugPutStdErr();
};

} // namespace msXpSlibmass


#endif // IONIZE_RULE_HPP
