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


/////////////////////// Qt includes


/////////////////////// Local includes
#include <libmass/Ponderable.hpp>
#include <massxpert/nongui/PolChemDefEntity.hpp>
#include <libmass/IonizeRule.hpp>

namespace msXpSmassXpert
{


//! 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 msXpSlibmass::Ponderable
{
  protected:
  //! IonizeRule that is used to ionize \c this Ionizable.
  msXpSlibmass::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 msXpSlibmass::Ponderable & = msXpSlibmass::Ponderable(),
            const msXpSlibmass::IonizeRule & = msXpSlibmass::IonizeRule(),
            bool                             = false);

  Ionizable(const Ionizable &);

  virtual ~Ionizable();

  virtual Ionizable *clone() const;

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Woverloaded-virtual"
  virtual void clone(Ionizable *) const;
  virtual void mold(const Ionizable &);
#pragma clang diagnostic pop

  virtual Ionizable &operator=(const Ionizable &);

  const msXpSlibmass::IonizeRule &ionizeRule() const;
  msXpSlibmass::IonizeRule *ionizeRule();

  bool isIonized() const;
  int setCharge(int);
  virtual int charge() const;

  virtual int ionize();
  virtual int ionize(const msXpSlibmass::IonizeRule &);
  static int ionize(Ionizable *, const msXpSlibmass::IonizeRule &);

  virtual int deionize();
  static int deionize(Ionizable *);

  virtual double molecularMass(msXpS::MassType);

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Woverloaded-virtual"
  bool validate();
#pragma clang diagnostic pop

  virtual bool operator==(const Ionizable &) const;
  virtual bool operator!=(const Ionizable &) const;

  virtual bool calculateMasses();
};

} // namespace msXpSmassXpert


#endif // IONIZABLE_HPP
