/**
 * \file core/label.cpp
 * \date 20/5/2017
 * \author Olivier Langella
 * \brief description of a label
 */

/*******************************************************************************
 * Copyright (c) 2017 Olivier Langella <olivier.langella@u-psud.fr>.
 *
 * This file is part of i2MassChroQ.
 *
 *     i2MassChroQ 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.
 *
 *     i2MassChroQ 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 i2MassChroQ.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Contributors:
 *     Olivier Langella <olivier.langella@u-psud.fr> - initial API and
 *implementation
 ******************************************************************************/

#include "label.h"
#include "../../utils/utils.h"
#include <pappsomspp/core/amino_acid/aamodification.h>
#include <pappsomspp/core/pappsoexception.h>
#include <QDebug>

LabelModification::LabelModification(const QString &inat,
                                     pappso::AaModificationP inmodification)
{
  at           = inat;
  modification = inmodification;
}


Label::Label(QDomNode &label_node)
{
  //<isotope_label id="light">
  _xml_id = label_node.toElement().attribute("id");
  qDebug() << "Label::Label begin " << _xml_id;
  try
    {
      //<mod at="Nter" value="28.0" acc="MOD:00429"/>
      //<mod at="K" value="28.0" acc="MOD:00429"/>
      QDomNode child = label_node.firstChild();
      while(!child.isNull())
        {
          if(child.toElement().tagName() == "mod")
            {
              if(child.toElement().attribute("acc").isEmpty())
                {
                  throw pappso::PappsoException(QObject::tr(
                    "acc attribute is empty : PSIMOD accession required"));
                }
              qDebug() << "Label::Label mod at="
                       << child.toElement().attribute("at")
                       << " mod=" << child.toElement().attribute("acc");
              LabelModification label_modification = {
                child.toElement().attribute("at"),
                pappso::AaModification::getInstance(
                  child.toElement().attribute("acc"))};
              _modification_list.push_back(label_modification);
            }
          child = child.nextSibling();
        }
    }
  catch(pappso::PappsoException &error)
    {
      throw pappso::PappsoException(
        QObject::tr("error creating Label : %1").arg(error.qwhat()));
    }
}


Label::Label(const Label &other)
{
  _xml_id            = other._xml_id;
  _modification_list = other._modification_list;
}

Label::~Label()
{
}

bool
Label::containsAaModificationP(
  const std::list<pappso::AaModificationP> &modification_set) const
{
  for(LabelModification label_modification : _modification_list)
    {
      if(std::find(modification_set.begin(),
                   modification_set.end(),
                   label_modification.modification) != modification_set.end())
        {
          return true;
        }
    }
  return false;
}

pappso::PeptideSp
Label::getUnlabeledPeptideSp(const pappso::Peptide *p_peptide) const
{
  pappso::Peptide peptide(*p_peptide);
  for(LabelModification label_modification : _modification_list)
    {
      qDebug() << "remove " << peptide.toString() << " "
               << label_modification.modification->getAccession();
      peptide.removeAaModification(label_modification.modification);
    }
  return (peptide.makePeptideSp());
}


pappso::PeptideSp
Label::getLLabeledPeptideSp(const pappso::Peptide *p_peptide) const
{
  pappso::Peptide peptide(*p_peptide);

  for(LabelModification label_modification : _modification_list)
    {
      if(label_modification.at == "Nter")
        {
          peptide.addAaModification(label_modification.modification, 0);
        }
      else if(label_modification.at == "Cter")
        {
          peptide.addAaModification(label_modification.modification,
                                    peptide.size() - 1);
        }
      else
        {
          pappso::Enums::AminoAcidChar aa_char =
            (pappso::Enums::AminoAcidChar)label_modification.at[0].toLatin1();
          peptide.addAaModificationOnAllAminoAcid(
            label_modification.modification, aa_char);
        }
    }

  return (peptide.makePeptideSp());
}

const QString &
Label::getXmlId() const
{
  return _xml_id;
}

const std::vector<LabelModification> &
Label::getLabelModifictionList() const
{
  return _modification_list;
}

void
Label::writeMassChroqMl(QXmlStreamWriter *output_stream) const
{


  //<isotope_label id="iso1">
  output_stream->writeStartElement("isotope_label");
  output_stream->writeAttribute("id", _xml_id);
  //		<mod at="Nter" value="28.0" acc="MOD:00429"/>
  //		<mod at="K" value="28.0" acc="MOD:00429"/>
  for(const LabelModification &label_modification : _modification_list)
    {
      output_stream->writeStartElement("mod");
      output_stream->writeAttribute("at", label_modification.at);
      output_stream->writeAttribute(
        "value",
        Utils::getXmlDouble(label_modification.modification->getMass()));
      output_stream->writeAttribute(
        "acc", label_modification.modification->getAccession());
      output_stream->writeEndElement();
      output_stream->writeComment(label_modification.modification->getName());
    }
  //	</isotope_label>
  output_stream->writeEndElement();
}

bool
Label::isEmpty() const
{
  if(_modification_list.size() == 0)
    return true;
  return false;
}
