
/*******************************************************************************
 * 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 "peptidextp.h"
#include <QStringList>
#include <set>

PeptideXtp::PeptideXtp(const QString &pepstr) : pappso::Peptide(pepstr)
{
}

PeptideXtp::PeptideXtp(const pappso::Peptide &peptide)
  : pappso::Peptide(peptide)
{
}


PeptideXtp::PeptideXtp(const PeptideXtp &other) : pappso::Peptide(other)
{
}

PeptideXtp::~PeptideXtp()
{
}

const QString
PeptideXtp::getModifString(bool without_label [[maybe_unused]]) const
{
  QStringList modif_list;
  unsigned int i = 1;
  for(const pappso::Aa &amino_acid : m_aaVec)
    {
      std::vector<pappso::AaModificationP> aa_modif_list =
        amino_acid.getModificationList();
      QStringList aamodif;
      for(auto &&aa_modif : aa_modif_list)
        {
          if(aa_modif->getAccession().startsWith("MUTATION:"))
            { // pm@5:N=>T
              aamodif << QString(aa_modif->getAccession())
                           .replace("MUTATION:", QString("pm").arg(i));
            }
          else
            {
              if(!aa_modif->isInternal())
                {
                  aamodif << QString::number(aa_modif->getMass(), 'f', 2);
                }
            }
        }
      aamodif.sort();
      QString mod_str(aamodif.join("|"));
      if(!mod_str.isEmpty())
        {
          modif_list << QString("%1%2:%3")
                          .arg(i)
                          .arg(amino_acid.getLetter())
                          .arg(mod_str);
        }
      i++;
    }
  // return QString ("%1 %2").arg(modif_list.join("
  // ")).arg(this->toAbsoluteString());
  return modif_list.join(" ");
}

PeptideXtpSp
PeptideXtp::makePeptideXtpSp() const
{
  return std::make_shared<PeptideXtp>(*this);
}


pappso::pappso_double
PeptideXtp::getGroupingMass() const
{
  return getNativePeptideP()->getMass();
}
void
PeptideXtp::clearLabel()
{
  _sp_native_peptide = nullptr;
  _p_label           = nullptr;
}

const pappso::Peptide *
PeptideXtp::getNativePeptideP() const
{
  if(_sp_native_peptide.get() == nullptr)
    {
      return this;
    }
  return _sp_native_peptide.get();
}

bool
PeptideXtp::replaceModification(pappso::AaModificationP oldmod,
                                pappso::AaModificationP newmod)
{

  pappso::Peptide::replaceAaModification(oldmod, newmod);
  if(_sp_native_peptide.get() != nullptr)
    {
      //_sp_native_peptide.get()->replaceAaModification(oldmod, newmod);
      return false;
    }
  return true;
}

bool
PeptideXtp::replaceAaModificationOnAminoAcid(pappso::Enums::AminoAcidChar aa,
                                             pappso::AaModificationP oldmod,
                                             pappso::AaModificationP newmod)
{

  pappso::Peptide::replaceAaModificationOnAminoAcid(aa, oldmod, newmod);
  if(_sp_native_peptide.get() != nullptr)
    {
      //_sp_native_peptide.get()->replaceAaModification(oldmod, newmod);
      return false;
    }
  return true;
}


void
PeptideXtp::applyLabelingMethod(LabelingMethodSp labeling_method_sp)
{
  std::list<pappso::AaModificationP> modification_set;
  for(const pappso::Aa &amino_acid : m_aaVec)
    {
      std::vector<pappso::AaModificationP> aa_modif_list =
        amino_acid.getModificationList();
      modification_set.insert(
        modification_set.begin(), aa_modif_list.begin(), aa_modif_list.end());
    }
  modification_set.unique();
  _p_label             = nullptr;
  const Label *p_label = labeling_method_sp.get()->getLabel(modification_set);
  if(p_label != nullptr)
    {
      _p_label           = p_label;
      _sp_native_peptide = _p_label->getUnlabeledPeptideSp(this);
    }
}

const Label *
PeptideXtp::getLabel() const
{
  return _p_label;
}

void
PeptideXtp::observedInMsRun(const MsRun *p_msrun)
{
  if(find(m_observedMsrunList.begin(), m_observedMsrunList.end(), p_msrun) ==
     m_observedMsrunList.end())
    {
      m_observedMsrunList.push_back(p_msrun);
    }
}

const std::vector<const MsRun *> &
PeptideXtp::getObservedMsrunList() const
{
  return m_observedMsrunList;
}

const PeptideXtp &
PeptideXtp::residueModifications(
  const std::map<pappso::Enums::AminoAcidChar, pappso::AaModificationP>
    &residue_modifications)
{
  for(pappso::Aa &amino_acid : m_aaVec)
    {
      auto it = residue_modifications.find(amino_acid.getAminoAcidChar());

      if(it != residue_modifications.end())
        {
          amino_acid.addAaModification(it->second);
        }
    }
  this->m_proxyMass = -1;
  getMass();
  return *this;
}
