/* massXpert - the true massist's program.
   --------------------------------------
   Copyright(C) 2006,2007 Filippo Rusconi

   http://www.massxpert.org/massXpert

   This file is part of the massXpert project.

   The massxpert project is the successor to the "GNU polyxmass"
   project that is an official GNU project package(see
   www.gnu.org). The massXpert project is not endorsed by the GNU
   project, although it is released ---in its entirety--- under the
   GNU General Public License. A huge part of the code in massXpert
   is actually a C++ rewrite of code in GNU polyxmass. As such
   massXpert was started at the Centre National de la Recherche
   Scientifique(FRANCE), that granted me the formal authorization to
   publish it under this Free Software License.

   This software is free software; you can redistribute it and/or
   modify it under the terms of the GNU  General Public
   License version 3, as published by the Free Software Foundation.
   

   This software 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 software; if not, write to the

   Free Software Foundation, Inc.,

   51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/


#ifndef POL_CHEM_DEF_HPP
#define POL_CHEM_DEF_HPP


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


/////////////////////// Local includes
#include "formula.hpp"
#include "modif.hpp"
#include "crossLinker.hpp"
#include "cleaveSpec.hpp"
#include "fragSpec.hpp"
#include "ionizeRule.hpp"
#include "polymer.hpp"
#include "monomerSpec.hpp"
#include "modifSpec.hpp"
#include "crossLinkerSpec.hpp"
#include "polChemDefSpec.hpp"
#include "chemEntVignetteRenderer.hpp"


namespace massXpert
{

  //! 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.
     */
    Formula m_leftCap;

    //! Right cap formula.
    /*! Describes how the polymer should be capped on its right end.
     */
    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.
    */
    IonizeRule m_ionizeRule;
  
    //! List of atoms.
    QList<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 Formula &);
    const Formula &leftCap() const;

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

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

    void setRepositoryList(QList<PolChemDef *> *);

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

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

    const QList<Atom *> &atomList() const;
    QList<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 massXpert


#endif // POL_CHEM_DEF_HPP
