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

#pragma once

#include <pappsomspp/core/peptide/peptide.h>
#include "labeling/labelingmethod.h"
#include "msrun.h"

class PeptideXtp;

/** \brief shared pointer on a Peptide object
 */
typedef std::shared_ptr<PeptideXtp> PeptideXtpSp;

class PeptideXtp : public pappso::Peptide
{
  public:
  PeptideXtp(const QString &pepstr);
  PeptideXtp(const pappso::Peptide &peptide);
  PeptideXtp(const PeptideXtp &other);
  ~PeptideXtp();

  PeptideXtpSp makePeptideXtpSp() const;

  /** \brief get the theoretical mass to use for grouping
   * This mass might be different than the true peptide mass to recognize that a
   * tagged peptide with taget modification is a light, inter or heavy version
   * of the same peptide
   */
  pappso::pappso_double getGroupingMass() const;

  /** @brief get the native version of this peptide (not labeled)
   * if the peptide is not labeled, returns this
   */
  const pappso::Peptide *getNativePeptideP() const;

  /** @brief human readable string that contains modifications
   * @param without_label get modifications without existing labels
   * */
  const QString getModifString(bool without_label = false) const;

  /** @brief replace modification in peptide
   */
  bool replaceModification(pappso::AaModificationP oldmod,
                           pappso::AaModificationP newmod);


  /** @brief replaces all occurences of a modification by a new one
   * on a specific amino acid
   * @param aa the amino acid to modify
   * @param oldmod modification to change
   * @param newmod new modification
   */
  bool replaceAaModificationOnAminoAcid(pappso::Enums::AminoAcidChar aa,
                                        pappso::AaModificationP oldmod,
                                        pappso::AaModificationP newmod);

  /** @brief reset label
   * */
  void clearLabel();
  /** @brief try to apply any label from this labeling method
   * */
  void applyLabelingMethod(LabelingMethodSp labeling_method_sp);

  /** @brief get label
   * */
  const Label *getLabel() const;

  /** @brief inform that this peptide has been observed in this MS run
   * usefull to be able to use the peprepro parameter to validate peptides
   */
  void observedInMsRun(const MsRun *p_msrun);

  /** @brief get the non redundant list of MS runs in which this peptide has
   * been observed
   */
  const std::vector<const MsRun *> &getObservedMsrunList() const;

  /** @brief modify each residue according to the map
   */
  const PeptideXtp &residueModifications(
    const std::map<pappso::Enums::AminoAcidChar, pappso::AaModificationP>
      &residue_modifications);

  private:
  /** \brief if the peptide is tagged, this is the native peptide without tags
   */
  pappso::PeptideSp _sp_native_peptide = nullptr;

  const Label *_p_label = nullptr;

  std::vector<const MsRun *> m_observedMsrunList;
};
