/**
 * \file utils/peptideevidence.h
 * \date 18/11/2017
 * \author Olivier Langella
 * \brief peptide evidence : a peptide sequence + spectrum + identification
 * engine evaluation (psm)
 */


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

#include <pappsomspp/types.h>
#include "peptidextp.h"
#include "identification_sources/identificationdatasource.h"
#include "automaticfilterparameters.h"
#include "msrun.h"

#include "../grouping/groupingexperiment.h"

class PeptideEvidence;

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

class PeptideEvidence
{
  public:
  PeptideEvidence(MsRun *msrunid_sp, std::size_t scan_index);
  PeptideEvidence(const PeptideEvidence &other);
  virtual ~PeptideEvidence();
  std::size_t getHashSampleScan() const;
  std::size_t getHashPeptideMassSample() const;

  PeptideEvidenceSp makePeptideEvidenceSp() const;

  void setRetentionTime(pappso::pappso_double rt);
  void setEvalue(pappso::pappso_double evalue);

  /** @brief get experimental mass of this peptide
   * @return the computed mass given the precursor measured mass and the deduced
   * peptide charge
   */
  pappso::pappso_double getExperimentalMass() const;

  /** @brief get experimental MH+ of this peptide
   * @return getExperimentalMass + MHPLUS
   */
  pappso::pappso_double getExperimentalMhplus() const;

  /** @brief get experimental mz of this peptide
   * @return the real mass measured (precuror mass) by the spectrometer
   */
  pappso::pappso_double getExperimentalMz() const;


  /** @brief set experimental mass of this peptide
   * @arg exp_mass the computed mass given the precursor measured mass and the
   * deduced peptide charge
   */
  void setExperimentalMass(pappso::pappso_double exp_mass);


  /** \brief set specific parameter value
   */
  virtual void setParam(PeptideEvidenceParam param, const QVariant &value);
  /** \brief get specific parameter value
   */
  virtual const QVariant getParam(PeptideEvidenceParam param) const;

  const std::map<PeptideEvidenceParam, QVariant> &getParamList() const;


  void setCharge(unsigned int charge);
  void setPeptideXtpSp(PeptideXtpSp peptide);
  void
  setIdentificationDataSource(IdentificationDataSource *identification_source);


  /** @brief sets the identification engine
   * by default, this is the identification engine of the datasource
   */
  void setIdentificationEngine(IdentificationEngine identification_engine);

  /** @brief get the identification engine
   * by default, this is the identification engine of the datasource
   */
  IdentificationEngine getIdentificationEngine() const;

  void setChecked(bool arg1);
  bool isChecked() const;
  bool isValid() const;
  bool isValidAndChecked() const;
  bool isGrouped() const;

  const MsRun *getMsRunP() const;
  MsRun *getMsRunPtr();
  IdentificationDataSource *getIdentificationDataSource() const;
  unsigned int getScanNumber() const;

  /** @brief get retention time of this PSM in seconds
   * the retention time must have been present when reading MS identification
   * results. If no retention time was set, this returns O
   * @return retention time in seconds or zero if data is missing
   */
  pappso::pappso_double getRetentionTime() const;

  /** @brief get retention time of this PSM in seconds by all means
   *
   * if retention time is missing, this tries to guess it by all means. It will
   * try to look at mz data file.
   * This could be time consuming.
   * @return retention time in seconds or zero if data is missing
   */
  pappso::pappso_double getHardenedRetentionTime() const;
  unsigned int getCharge() const;
  const PeptideXtpSp &getPeptideXtpSp() const;
  pappso::pappso_double getEvalue() const;

  void setGrpPeptideSp(const pappso::GrpPeptideSp &sp_grp_peptide);
  const pappso::GrpPeptideSp &getGrpPeptideSp() const;

  /** @brief validate or invalidate peptides and proteins based automatic
   * filters and manual checks
   * */
  void updateAutomaticFilters(
    const AutomaticFilterParameters &automatic_filter_parameters);

  /** @brief get delta between theoretical mhplus mass and mhplus experimental
   * mass mhplus experimental mass - theoretical mhplus mass
   */
  pappso::pappso_double getDeltaMass() const;

  /** @brief get delta in ppm between theoretical mhplus mass and mhplus
   * experimental mass
   * @return mhplus experimental mass - theoretical mhplus mass
   */
  pappso::pappso_double getPpmDeltaMass() const;

  /** @brief get theoretical (not observed) m/z based on peptide composition and
   * charge
   * @return theoretical mz mass
   */
  pappso::pappso_double getTheoreticalMz() const;

  ValidationState getValidationState() const;

  private:
  static std::hash<std::string> _hash_fn;
  MsRun *_msrunid_sp;
  unsigned int m_scan_number = 0;
  size_t _hash_sample_scan;
  pappso::GrpPeptideSp _sp_grp_peptide;
  PeptideXtpSp _peptide_sp;
  pappso::pappso_double _rt;
  pappso::pappso_double _evalue = 0;
  pappso::pappso_double _exp_mass;
  unsigned int _charge;
  IdentificationDataSource *_p_identification_source = nullptr;
  std::map<PeptideEvidenceParam, QVariant> _params;

  /** @brief manually checked by user (true by default)
   */
  bool _checked = true;

  /** @brief automatic filter result (false by default)
   */
  bool _proxy_valid = false;

  /** @brief the search/identification engine that found this evidence
   */
  IdentificationEngine _identification_engine;
};
