/* BEGIN software license
 *
 * MsXpertSuite - mass spectrometry software suite
 * -----------------------------------------------
 * Copyright 2009--2026 by 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
 */

#pragma once


/////////////////////// Stdlib includes


/////////////////////// Qt includes
#include <QtQml>


/////////////////////// pappsomspp includes


/////////////////////// Local includes
#include "MsXpS/export-import-config.h"

#include "MsXpS/libXpertMassCore/jsclassregistrar.h"
#include "MsXpS/libXpertMassCore/Utils.hpp"
#include "MsXpS/libXpertMassCore/Formula.hpp"

namespace MsXpS
{
namespace libXpertMassCore
{

/*  BEGIN CLASS JS REFERENCE
 *  namespace: MsXpS::libXpertMassCore
 *  class name: Ionizer
 */

class DECLSPEC Ionizer: public QObject
{
  Q_OBJECT

  // Q_PROPERTY(
  //   Formula formula READ getFormulaCstRef WRITE setFormula MEMBER m_formula)
  Q_PROPERTY(int nominalCharge READ getNominalCharge WRITE setNominalCharge
               MEMBER m_nominalCharge)
  Q_PROPERTY(int level READ getLevel WRITE setLevel MEMBER m_level)
  Q_PROPERTY(bool isValid READ isValid MEMBER m_isValid)
  // Q_PROPERTY(Formula currentStateFormula READ getCurrentStateFormulaCstRef
  //              MEMBER m_currentStateFormula)
  Q_PROPERTY(int currentStateNominalCharge READ getCurrentStateNominalCharge
               MEMBER m_currentStateNominalCharge)
  Q_PROPERTY(
    int currentStateLevel READ getCurrentStateLevel MEMBER m_currentStateLevel)
  Q_PROPERTY(bool isCurrentStateValid READ isCurrentStateValid MEMBER
               m_isCurrentStateValid)

  // friend class Polymer;

  public:
  Q_INVOKABLE Ionizer(QObject *parent = nullptr);
  Ionizer(IsotopicDataCstSPtr isotopic_data_csp, QObject *parent = nullptr);
  Ionizer(IsotopicDataCstSPtr isotopic_data_csp,
          const Formula &formula,
          int charge,
          int level,
          QObject *parent = nullptr);
  Ionizer(IsotopicDataCstSPtr isotopic_data_csp,
          const QString &formula_string,
          int charge,
          int level,
          QObject *parent = nullptr);

  // Pseudo copy constructor
  Ionizer(const Ionizer &other, QObject *parent = nullptr);
  void initialize(const Ionizer &other);

  void setIsotopicDataCstSPtr(IsotopicDataCstSPtr isotopic_data_csp);
  IsotopicDataCstSPtr getIsotopicDataCstSPtr() const;

  void setFormula(const Formula &formula);
  void setFormula(const QString &formula_string);
  const Formula &getFormulaCstRef() const;
  Formula &getFormulaRef();
  const Formula &getCurrentStateFormulaCstRef() const;

  void setNominalCharge(int nominal_charge);
  int getNominalCharge() const;
  int getCurrentStateNominalCharge() const;

  Q_INVOKABLE int charge() const;
  Q_INVOKABLE int currentStateCharge() const;

  Q_INVOKABLE void
  forceCurrentState(const Formula &formula, int nominal_charge, int level);
  Q_INVOKABLE void forceCurrentStateLevel(int level);

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

  Q_INVOKABLE Ionizer makeIonizerWithCurrentStateData();

  bool isIonized() const;

  Enums::IonizationOutcome ionize(double &mono, double &avg) const;
  Enums::IonizationOutcome deionize(double &mono, double &avg) const;
  Enums::IonizationOutcome molecularMasses(double &mono, double &avg) const;

  Ionizer &operator=(const Ionizer &other);
  bool operator==(const Ionizer &other) const;
  bool operator!=(const Ionizer &other) const;

  bool renderXmlIonizeRuleElement(const QDomElement &element);
  QString formatXmlIonizeRuleElement(
    int, const QString &indent = Utils::xmlIndentationToken);

  Q_INVOKABLE bool validate(ErrorList *error_list_p) const;
  bool isValid() const;

  Q_INVOKABLE bool validateCurrentState(ErrorList *error_list_p) const;
  bool isCurrentStateValid() const;

  //////////////// UTILS /////////////////////
  QString toString(bool with_title = true) const;
  void clear();

  static void registerJsConstructor(QJSEngine *engine);

  protected:
  IsotopicDataCstSPtr mcsp_isotopicData = nullptr;
  Formula m_formula;
  int m_nominalCharge    = 0;
  int m_level            = 0;
  mutable bool m_isValid = false;

  mutable Formula m_currentStateFormula;
  mutable int m_currentStateNominalCharge = 0;
  mutable int m_currentStateLevel         = 0;
  mutable bool m_isCurrentStateValid      = false;
};

typedef std::shared_ptr<Ionizer> IonizerSPtr;
typedef std::shared_ptr<const Ionizer> IonizerCstSPtr;


/*  END CLASS JS REFERENCE
 *  namespace: MsXpS::libXpertMassCore
 *  class name: Ionizer
 */

} // namespace libXpertMassCore
MSXPS_REGISTER_JS_CLASS(MsXpS::libXpertMassCore, Ionizer)
} // namespace MsXpS

Q_DECLARE_METATYPE(MsXpS::libXpertMassCore::Ionizer);
extern int ionizerMetaTypeId;

Q_DECLARE_METATYPE(MsXpS::libXpertMassCore::Ionizer *);
extern int ionizerPtrMetaTypeId;
