/* 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
 */


/////////////////////// Local includes
#include "ChemicalGroupRule.hpp"


namespace MsXpS
{

namespace libXpertMass
{


/*!
\class MsXpS::libXpertMass::ChemicalGroupRule
\inmodule libXpertMass
\ingroup PolChemDefBuildingdBlocks
\inheaderfile ChemicalGroupRule.hpp

\brief The ChemicalGroupRule class provides a model for refining the
acido-basic behaviour of a chemical group of either a \l Monomer object or of a
\l Modif object.

In an pkaphpidata definition file, the following xml structure
is encountered:

\code
<pkaphpidata>
  <monomers>
    <monomer>
      <code>A</code>
      <mnmchemgroup>
        <name>N-term NH2</name>
        <pka>9.6</pka>
        <acidcharged>TRUE</acidcharged>
        <polrule>left_trapped</polrule>
        <chemgrouprule>
          <entity>LE_PLM_MODIF</entity>
          <name>Acetylation</name>
          <outcome>LOST</outcome>
        </chemgrouprule>
      </mnmchemgroup>
      <mnmchemgroup>
        <name>C-term COOH</name>
        <pka>2.35</pka>
        <acidcharged>FALSE</acidcharged>
        <polrule>right_trapped</polrule>
      </mnmchemgroup>
    </monomer>
    <monomer>
      <code>C</code>
      <mnmchemgroup>
        <name>N-term NH2</name>
        <pka>9.6</pka>
        <acidcharged>TRUE</acidcharged>
        <polrule>left_trapped</polrule>
        <chemgrouprule>
          <entity>LE_PLM_MODIF</entity>
          <name>Acetylation</name>
          <outcome>LOST</outcome>
        </chemgrouprule>
      </mnmchemgroup>
      <mnmchemgroup>
        <name>C-term COOH</name>
        <pka>2.35</pka>
        <acidcharged>FALSE</acidcharged>
        <polrule>right_trapped</polrule>
      </mnmchemgroup>
      <mnmchemgroup>
        <name>Lateral SH2</name>
        <pka>8.3</pka>
        <acidcharged>FALSE</acidcharged>
        <polrule>never_trapped</polrule>
      </mnmchemgroup>
    </monomer>
    .....
  <modifs>
    <modif>
      <name>Phosphorylation</name>
      <mdfchemgroup>
        <name>none_set</name>
        <pka>1.2</pka>
        <acidcharged>FALSE</acidcharged>
      </mdfchemgroup>
      <mdfchemgroup>
        <name>none_set</name>
        <pka>6.5</pka>
        <acidcharged>FALSE</acidcharged>
      </mdfchemgroup>
    </modif>
  </modifs>
</pkaphpidata>
\endcode

\sa ChemicalGroup,
*/


/*!
\enum MsXpS::libXpertMass::ChemicalGroupRuleFate

This enum specifies how the chemical group behaves when the chemical entity
that it holds polymerizes into a \l Polymer.

This example clarifies the concept:

\code
    <monomer>
      <code>C</code>
      <mnmchemgroup>
        <name>N-term NH2</name>
        <pka>9.6</pka>
        <acidcharged>TRUE</acidcharged>
        <polrule>left_trapped</polrule>
        <chemgrouprule>
          <entity>LE_PLM_MODIF</entity>
          <name>Acetylation</name>
          <outcome>LOST</outcome>
        </chemgrouprule>
      </mnmchemgroup>
\endcode

When the Cysteine's amino group is modified because the Cys residue
on on the N-terminal end of the polymer, if it gets acetylated, then the amino
group is lost because it is trapped in the amide bond. It is thus not accounted
for when computing the pI of the protein.

\value LOST
        The chemical group is lost upon modification of the \l Monomer.
\value PRESERVED
        The chemical group is preserved upon modification of the \l Monomer.
*/

/*!
\variable MsXpS::libXpertMass::ChemicalGroupRule::m_name

\brief The name of the ChemicalGroupRule instance.
*/

/*!
\variable MsXpS::libXpertMass::ChemicalGroupRule::m_entity

\brief The entity of the ChemicalGroupRule instance, like LE_PLM_MODIF for
\e{left end polymer modification}.
*/

/*!
\variable MsXpS::libXpertMass::ChemicalGroupRule::m_chemicalGroupFate

\brief The fate of the ChemicalGroupRule instance.

\sa MsXpS::libXpertMass::ChemicalGroupRuleFate
*/

/*!
\brief Constructs a ChemicalGroupRule instance.

\list
\li \a name: The name of this ChemicalGroupRule instance.
\li \a entity: The entity of this ChemicalGroupRule instance.
\li \a fate: The fate of this ChemicalGroupRule instance.
\endlist
*/
ChemicalGroupRule::ChemicalGroupRule(QString name,
                                     QString entity,
                                     ChemicalGroupRuleFate fate)
  : m_name(name), m_entity(entity), m_chemicalGroupFate(fate)
{
  Q_ASSERT(m_chemicalGroupFate == ChemicalGroupRuleFate::LOST ||
           m_chemicalGroupFate == ChemicalGroupRuleFate::PRESERVED);
}

/*!
\brief Sets the \a name.
*/
void
ChemicalGroupRule::setName(QString name)
{
  m_name = name;
}


/*!
\brief Returns the name.
*/
QString
ChemicalGroupRule::name()
{
  return m_name;
}


/*!
\brief Sets the \a entity.
*/
void
ChemicalGroupRule::setEntity(QString entity)
{
  m_entity = entity;
}

/*!
\brief Returns the entity.
*/
QString
ChemicalGroupRule::entity()
{
  return m_entity;
}

/*!
\brief Sets the \a fate.
*/
void
ChemicalGroupRule::setFate(ChemicalGroupRuleFate fate)
{
  m_chemicalGroupFate = fate;
}

/*!
\brief Returns the fate.
*/
ChemicalGroupRuleFate
ChemicalGroupRule::fate()
{
  return m_chemicalGroupFate;
}


/*!
\brief Parses the ChemicalGroupRule XML \a element.

Upon parsing of the \a element, its data are validated and set to this
ChemicalGroupRule instance, thus essentially initializing it.

Returns true if parsing and validation were successful, false otherwise.
*/
bool
ChemicalGroupRule::renderXmlElement(const QDomElement &element)
{
  QDomElement child;

  // In an acidobasic definition file, the following xml structure
  // is encountered:

    // <monomer>
    //   <code>C</code>
    //   <mnmchemgroup>
    //     <name>N-term NH2</name>
    //     <pka>9.6</pka>
    //     <acidcharged>TRUE</acidcharged>
    //     <polrule>left_trapped</polrule>
    //     <chemgrouprule>
    //       <entity>LE_PLM_MODIF</entity>
    //       <name>Acetylation</name>
    //       <outcome>LOST</outcome>
    //     </chemgrouprule>
    //   </mnmchemgroup>

  // The relevant DTD line is:
  // <!ELEMENT chemgrouprule(entity,name,outcome)>

  // And the element the parameter points to is:

  //  <chemgrouprule>

  // Which means that element.tagName() == "chemgrouprule" and that we'll
  // have to go one step down to the first child of the current node
  // in order to get to the <entity> element.

  if(element.tagName() != "chemgrouprule")
    return false;

  child = element.firstChildElement("entity");

  if(child.isNull())
    return false;

  m_entity = child.text();

  child = child.nextSiblingElement();

  if(child.isNull() || child.tagName() != "name")
    return false;

  m_name = child.text();

  child = child.nextSiblingElement();

  if(child.isNull() || child.tagName() != "outcome")
    return false;

  if(child.text() == "LOST")
    m_chemicalGroupFate = ChemicalGroupRuleFate::LOST;
  else if(child.text() == "PRESERVED")
    m_chemicalGroupFate = ChemicalGroupRuleFate::PRESERVED;
  else
    return false;

  return true;
}

} // namespace libXpertMass

} // namespace MsXpS
