/* 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
#include <map>

/////////////////////// Qt includes
#include <QString>
#include <QList>


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

#include "MsXpS/libXpertMassCore/PolChemDefSpec.hpp"
#include "MsXpS/libXpertMassCore/Ionizer.hpp"

namespace MsXpS
{
namespace libXpertMassCore
{


extern const int POL_CHEM_DEF_FILE_FORMAT_VERSION;


class PolChemDef;
typedef std::shared_ptr<PolChemDef> PolChemDefSPtr;
typedef std::shared_ptr<const PolChemDef> PolChemDefCstSPtr;


//////////////////// MODIFS //////////////////////
//////////////////// MODIFS //////////////////////
class Modif;
using ModifCstSPtr = std::shared_ptr<const Modif>;
using ModifSPtr    = std::shared_ptr<Modif>;
typedef std::vector<ModifSPtr>::iterator ModifsIterator;
typedef std::vector<ModifSPtr>::const_iterator ModifsCstIterator;


//////////////////// MONOMERS //////////////////////
//////////////////// MONOMERS //////////////////////
class Monomer;
using MonomerCstSPtr = std::shared_ptr<const Monomer>;
using MonomerSPtr    = std::shared_ptr<Monomer>;
typedef std::vector<MonomerSPtr>::iterator MonomersIterator;
typedef std::vector<MonomerSPtr>::const_iterator MonomersCstIterator;


//////////////////// CROSSLINKERS //////////////////////
//////////////////// CROSSLINKERS //////////////////////
class CrossLinker;
using CrossLinkerCstSPtr = std::shared_ptr<const CrossLinker>;
using CrossLinkerSPtr    = std::shared_ptr<CrossLinker>;
typedef std::vector<CrossLinkerSPtr>::iterator CrossLinkersIterator;
typedef std::vector<CrossLinkerSPtr>::const_iterator CrossLinkersCstIterator;


//////////////////// CLEAVAGE AGENTS //////////////////////
//////////////////// CLEAVAGE AGENTS //////////////////////
class CleavageAgent;
using CleavageAgentCstSPtr = std::shared_ptr<const CleavageAgent>;
using CleavageAgentSPtr    = std::shared_ptr<CleavageAgent>;
typedef std::vector<CleavageAgentSPtr>::iterator CleavageAgentsIterator;
typedef std::vector<CleavageAgentSPtr>::const_iterator
  CleavageAgentsCstIterator;


//////////////////// FRAGMENTATION PATHWAYS //////////////////////
//////////////////// FRAGMENTATION PATHWAYS //////////////////////
class FragmentationPathway;
using FragmentationPathwayCstSPtr = std::shared_ptr<const FragmentationPathway>;
using FragmentationPathwaySPtr    = std::shared_ptr<FragmentationPathway>;
typedef std::vector<FragmentationPathwaySPtr>::iterator
  FragmentationPathwaysIterator;
typedef std::vector<FragmentationPathwaySPtr>::const_iterator
  FragmentationPathwaysCstIterator;

class DECLSPEC PolChemDef
{

  public:
  PolChemDef();
  PolChemDef(const PolChemDefSpec &pol_chem_def_spec);

  virtual ~PolChemDef();

  void setName(const QString &name);
  QString getName() const;

  void setXmlDataFilePath(const QString &file_path);
  QString getXmlDataFilePath() const;
  QString getXmlDataDirPath() const;

  void setIsotopicDataFilePath(const QString &file_path);
  QString getIsotopicDataFilePath() const;
  QString deduceIsotopicDataFilePath() const;

  void setLeftCap(const Formula &formula);
  const Formula &getLeftCap() const;

  void setRightCap(const Formula &formula);
  const Formula &getRightCap() const;

  void setCodeLength(int code_length);
  int getCodeLength() const;

  void setIonizer(const Ionizer &ionizer);
  const Ionizer &getIonizerCstRef() const;
  Ionizer &getIonizerRef();

  void setIsotopicDataSPtr(IsotopicDataSPtr isotopic_data_sp);
  IsotopicDataCstSPtr getIsotopicDataCstSPtr() const;
  IsotopicDataSPtr getIsotopicDataSPtr();

  //////////////////// MODIFS //////////////////////
  //////////////////// MODIFS //////////////////////

  const std::vector<ModifSPtr> &getModifsCstRef() const;
  std::vector<ModifSPtr> &getModifsRef();

  ModifCstSPtr getModifCstSPtrByName(const QString &name) const;
  int getModifIndexByName(const QString &name) const;
  //////////////////// MODIFS //////////////////////


  //////////////////// MONOMERS //////////////////////
  //////////////////// MONOMERS //////////////////////

  const std::vector<MonomerSPtr> &getMonomersCstRef() const;
  std::vector<MonomerSPtr> &getMonomersRef();

  MonomerSPtr getMonomerCstSPtrByName(const QString &name) const;
  MonomerSPtr getMonomerCstSPtrByCode(const QString &code) const;
  int getMonomerIndexByName(const QString &name) const;
  int getMonomerIndexByCode(const QString &name) const;
  //////////////////// MONOMERS //////////////////////


  //////////////////// CROSSLINKERS //////////////////////
  //////////////////// CROSSLINKERS //////////////////////

  const std::vector<CrossLinkerSPtr> &getCrossLinkersCstRef() const;
  std::vector<CrossLinkerSPtr> &getCrossLinkersRef();

  CrossLinkerCstSPtr getCrossLinkerCstSPtrByName(const QString &name) const;
  //////////////////// CROSSLINKERS //////////////////////


  //////////////////// CLEAVAGE AGENTS //////////////////////
  //////////////////// CLEAVAGE AGENTS //////////////////////

  const std::vector<CleavageAgentSPtr> &getCleavageAgentsCstRef() const;
  std::vector<CleavageAgentSPtr> &getCleavageAgentsRef();

  CleavageAgentCstSPtr getCleavageAgentCstSPtrByName(const QString &name) const;
  int getCleavageAgentIndexByName(const QString &name) const;
  //////////////////// CLEAVAGE AGENTS //////////////////////


  //////////////////// FRAGMENTATION PATHWAYS //////////////////////
  //////////////////// FRAGMENTATION PATHWAYS //////////////////////

  const std::vector<FragmentationPathwaySPtr> &
  getFragmentationPathwaysCstRef() const;
  std::vector<FragmentationPathwaySPtr> &getFragmentationPathwaysRef();

  FragmentationPathwayCstSPtr
  getFragmentationPathwayCstSPtrByName(const QString &name) const;
  int getFragmentationPathwayIndexByName(const QString &name) const;
  //////////////////// FRAGMENTATION PATHWAYS //////////////////////

  bool calculateDelimitedCodes();
  const QString &getDelimitedCodes();

  QStringList differenceBetweenMonomers(double threshold,
                                        Enums::MassType mass_type);

  //////////////// OPERATORS /////////////////////
  bool isChemicallyEquivalent(const PolChemDef &other) const;
  bool operator==(const PolChemDef &other) const;
  bool operator!=(const PolChemDef &other) const;


  //////////////// ISOTOPIC DATA LOADING WRITING /////////////////////
  static std::size_t loadIsotopicData(PolChemDefSPtr pol_chem_def_sp,
                                      const QString &file_path = QString());

  static std::size_t writeIsotopicData(PolChemDefSPtr pol_chem_def_sp,
                                       const QString &file_path = QString());

  //////////////// XML DATA LOADING WRITING /////////////////////
  static bool renderXmlPolChemDefFile(PolChemDefSPtr pol_chem_def_sp);
  static bool renderXmlPolChemDefFileVersion1(PolChemDefSPtr pol_chem_def_sp);
  static bool renderXmlPolChemDefFileVersion2(PolChemDefSPtr pol_chem_def_sp);

  QString formatXmlDtd();

  bool writeXmlFile();

  //////////////// VALIDATIONS /////////////////////
  bool validate(ErrorList *error_list_p) const;
  bool isValid() const;

  //////////////// UTILS /////////////////////

  protected:
  QString m_name;

  QString m_xmlDataFilePath;

  QString m_isotopicDataFilePath;

  Formula m_leftCap;
  Formula m_rightCap;

  int m_codeLength = -1;

  QString m_delimitedCodes;

  Ionizer m_ionizer;

  IsotopicDataSPtr msp_isotopicData = nullptr;

  std::vector<ModifSPtr> m_modifs;
  std::vector<MonomerSPtr> m_monomers;
  std::vector<CrossLinkerSPtr> m_crossLinkers;
  std::vector<CleavageAgentSPtr> m_cleavageAgents;
  std::vector<FragmentationPathwaySPtr> m_fragmentationPathways;

  std::vector<PolChemDefCstSPtr> m_polChemDefs;

  mutable bool m_isValid = false;
};


} // namespace libXpertMassCore
} // namespace MsXpS

Q_DECLARE_METATYPE(MsXpS::libXpertMassCore::PolChemDefSPtr);
extern int polChemDefSPtrMetaTypeId;

Q_DECLARE_METATYPE(MsXpS::libXpertMassCore::PolChemDefCstSPtr);
extern int polChemDefCstSPtrMetaTypeId;
