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


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


/////////////////////// Local includes
#include <libmass/Formula.hpp>
#include <massxpert/nongui/Modif.hpp>
#include <massxpert/nongui/CrossLinker.hpp>
#include <massxpert/nongui/CleaveSpec.hpp>
#include <massxpert/nongui/FragSpec.hpp>
#include <libmass/IonizeRule.hpp>
#include <massxpert/nongui/Polymer.hpp>
#include <massxpert/nongui/MonomerSpec.hpp>
#include <massxpert/nongui/ModifSpec.hpp>
#include <massxpert/nongui/CrossLinkerSpec.hpp>
#include <massxpert/nongui/PolChemDefSpec.hpp>
#include <massxpert/nongui/ChemEntVignetteRenderer.hpp>


namespace msXpSmassXpert
{

//! The PolChemDef class provides a polymer chemistry definition.
/*! A polymer chemistry definition allows one to characterize in a
  fine manner the chemistry of a polymer. That means that it should
  contain:

  -  a list of atoms;

  - a list of monomers;

  - a list of modifications;

  - a list of cross-linkers;

  - a list of cleavage specifications;

  - a list of fragmentation specifications;

  and a number of chemical data, like the left and right cap formulas,
  the code length(that is the maximum number of characters that might
  be used to construct a monomer code).

  Because monomers have to be graphically rendered at some point, in
  the form of monomer vignettes in the sequence editor, the polymer
  chemistry definition also contains:

  - a list of monomer specifications, which tell the sequence editor
  what file is to be used to render any monomer in the polymer
  chemistry definition;

  - a list of modification specifications, which tell the sequence
  editor what file is to be used to render any chemical
  modification;

  - a hash of all the vignettes already rendered for use in any
  polymer sequence editor containing a polymer sequence of this
  polymer chemistry definition. This is so that no more than one
  vignette is rendered for the same chemical entity in this polymer
  chemistry definition..
*/
class PolChemDef
{
  private:
  //! Name.
  /*! Identifies the polymer definition, like "protein" or "dna", for
    example.
  */
  QString m_name;

  //! File path.
  /*! Fully qualifies the file which contains the polymer definition.
   */
  QString m_filePath;

  //! Left cap formula.
  /*! Describes how the polymer should be capped on its left end.
   */
  msXpSlibmass::Formula m_leftCap;

  //! Right cap formula.
  /*! Describes how the polymer should be capped on its right end.
   */
  msXpSlibmass::Formula m_rightCap;

  //! Code length.
  /*! Maximum number of characters allowed to construct a monomer
    code.
  */
  int m_codeLength;

  //! Delimited codes string.
  /*! String made with each code of each monomer separated using '@',
    like "@Ala@Tyr@Phe@".
  */
  QString m_delimitedCodes;

  //! Ionization rule.
  /*! The ionization rule indicates how the polymer sequence needs be
    ionized by default.
  */
  msXpSlibmass::IonizeRule m_ionizeRule;

  //! List of atoms.
  QList<msXpSlibmass::Atom *> m_atomList;

  //! List of monomers.
  QList<Monomer *> m_monomerList;

  //! List of modifications.
  QList<Modif *> m_modifList;

  //! List of cross-linkers.
  QList<CrossLinker *> m_crossLinkerList;

  //! List of cleavage specifications.
  QList<CleaveSpec *> m_cleaveSpecList;

  //! List of fragmentation specifications.
  QList<FragSpec *> m_fragSpecList;

  //! List of monomer specifications.
  /*! Each monomer in the polymer chemistry definition has an item in
    this list indicating where the graphics file is to be found for
    graphical rendering.
  */
  QList<MonomerSpec *> m_monomerSpecList;

  //! List of modification specifications.
  /*! Each modification in the polymer chemistry definition has an
    item in this list indicating where the graphics file is to be
    found for graphical rendering and the graphical mechanism to be
    used for rendering the modification graphically.
  */
  QList<ModifSpec *> m_modifSpecList;

  //! List of cross-link specifications.
  /*! Each cross-link in the polymer chemistry definition has an item
    in this list indicating where the graphics file is to be found for
    graphical rendering.
  */
  QList<CrossLinkerSpec *> m_crossLinkerSpecList;

  //! Hash of graphical vignettes.
  /*! The graphical vignettes pointed to by items in this hash are
    used to render graphically chemical entities in the polymer
    chemistry definition. Their address is stored so that they can be
    reused by accessing them using a string like "Ser" or
    Ser-Phosphorylation", for example.
  */
  QHash<QString, ChemEntVignetteRenderer *> m_chemEntVignetteRendererHash;

  //! Reference count.
  /*! The count of polymer sequences using this polymer chemistry
    definition.
  */
  int m_refCount;

  QList<PolChemDef *> *mp_repositoryList;

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

  ~PolChemDef();

  void setVersion(const QString &);
  QString version() const;

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

  void setFilePath(const QString &);
  QString filePath() const;

  QString dirPath() const;

  void setLeftCap(const msXpSlibmass::Formula &);
  const msXpSlibmass::Formula &leftCap() const;

  void setRightCap(const msXpSlibmass::Formula &);
  const msXpSlibmass::Formula &rightCap() const;

  void setCodeLength(int);
  int codeLength() const;

  void setRepositoryList(QList<PolChemDef *> *);

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

  void setIonizeRule(const msXpSlibmass::IonizeRule &);
  const msXpSlibmass::IonizeRule &ionizeRule() const;
  msXpSlibmass::IonizeRule *ionizeRulePtr();

  const QList<msXpSlibmass::Atom *> &atomList() const;
  QList<msXpSlibmass::Atom *> *atomListPtr();

  const QList<Monomer *> &monomerList() const;
  QList<Monomer *> *monomerListPtr();

  const QList<Modif *> &modifList() const;
  QList<Modif *> *modifListPtr();

  const QList<CrossLinker *> &crossLinkerList() const;
  QList<CrossLinker *> *crossLinkerListPtr();

  const QList<CleaveSpec *> &cleaveSpecList() const;
  QList<CleaveSpec *> *cleaveSpecListPtr();

  const QList<FragSpec *> &fragSpecList() const;
  QList<FragSpec *> *fragSpecListPtr();

  bool modif(const QString &, Modif * = 0) const;
  bool crossLinker(const QString &, CrossLinker * = 0) const;

  QHash<QString, ChemEntVignetteRenderer *> *chemEntVignetteRendererHash();
  ChemEntVignetteRenderer *chemEntVignetteRenderer(const QString &);
  ChemEntVignetteRenderer *newChemEntVignetteRenderer(const QString &,
                                                      QObject * = 0);
  ChemEntVignetteRenderer *newMonomerVignetteRenderer(const QString &,
                                                      QObject * = 0);
  ChemEntVignetteRenderer *newModifVignetteRenderer(const QString &,
                                                    QObject * = 0);
  ChemEntVignetteRenderer *newCrossLinkerVignetteRenderer(const QString &,
                                                          QObject * = 0);

  void setRefCount(int);
  int refCount();

  void incrementRefCount();
  void decrementRefCount();

  QList<MonomerSpec *> *monomerSpecList();
  QList<ModifSpec *> *modifSpecList();
  QList<CrossLinkerSpec *> *crossLinkerSpecList();

  bool renderXmlPolChemDefFile();

  QString *formatXmlDtd();

  bool writeXmlFile();

  QStringList *differenceBetweenMonomers(double, int);
};

} // namespace msXpSmassXpert


#endif // POL_CHEM_DEF_HPP
