/**
 * \file pappsomspp/psm/features/psmfeatures.h
 * \date 19/07/2022
 * \author Olivier Langella
 * \brief comutes various PSM (Peptide Spectrum Match) features
 */

/*******************************************************************************
 * Copyright (c) 2022 Olivier Langella <Olivier.Langella@u-psud.fr>.
 *
 * This file is part of PAPPSOms-tools.
 *
 *     PAPPSOms-tools 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.
 *
 *     PAPPSOms-tools 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 PAPPSOms-tools.  If not, see <http://www.gnu.org/licenses/>.
 *
 ******************************************************************************/

#pragma once

#include "../../massspectrum/massspectrum.h"
#include "../../mzrange.h"
#include "../../peptide/peptidefragmention.h"
#include "../../processing/filters/filterchargedeconvolution.h"
#include "../../processing/filters/filterexclusionmz.h"
#include "../../processing/filters/filterresample.h"
#include "../peptideisotopespectrummatch.h"
#include "../../trace/linearregression.h"


namespace pappso
{
/**
 * @todo write docs
 */
class PMSPP_LIB_DECL PsmFeatures
{
  public:
  /** @brief compute psm features
   * @param ms2precision precision of mass measurements for MS2 fragments
   * @param minimumMz ignore mz values under this threshold
   */
  PsmFeatures(PrecisionPtr ms2precision, double minimumMz);

  /**
   * Destructor
   */
  ~PsmFeatures();

  void setPeptideSpectrumCharge(const pappso::PeptideSp peptideSp,
                                const MassSpectrum *p_spectrum,
                                unsigned int parent_charge,
                                unsigned int max_isotope_number);

  /** @brief get the sum of intensity of a specific ion
   * @param ion_type ion species (y, b, ...)
   */
  double getIntensityOfMatchedIon(PeptideIon ion_type);

  /** @brief sum of all peak intensities (matched or not)
   */
  double getTotalIntensity() const;


  /** @brief sum of matched peak intensities
   */
  double getTotalIntensityOfMatchedIons() const;

  /** @brief number of matched ions (peaks)
   */
  std::size_t getNumberOfMatchedIons() const;

  /** @brief count the number of matched ion complement
   *
   * matched ion complement are ions with a sum compatible to the precursor mass
   *
   */
  std::size_t countMatchedIonComplementPairs() const;

  /** @brief intensity of matched ion complement
   */
  double getTotalIntensityOfMatchedIonComplementPairs() const;

  const std::vector<
    std::pair<pappso::PeakIonIsotopeMatch, pappso::PeakIonIsotopeMatch>> &
  getPeakIonPairs() const;


  /** @brief get mean deviation of matched peak mass delta
   */
  double getMatchedMzDiffMean() const;


  /** @brief get standard deviation of matched peak mass delta
   */
  double getMatchedMzDiffSd() const;


  /** @brief get the precursor mass delta of the maximum intensity pair of
   * complement ions
   */
  double getMaxIntensityMatchedIonComplementPairPrecursorMassDelta() const;


  /** @brief get the maximum consecutive fragments of one ion type
   * @param ion_type ion species (y, b, ...)
   */
  std::size_t getMaxConsecutiveIon(PeptideIon ion_type);

  /** @brief number of amino acid covered by matched ions
   */
  std::size_t getAaSequenceCoverage(PeptideIon ion_type);


  /** @brief number of amino acid covered by matched complement pairs of ions
   */
  std::size_t getComplementPairsAaSequenceCoverage();

  double getMaxIntensityPeakIonMatch(PeptideIon ion_type) const;


  double getIonPairPrecursorMassDelta(
    const std::pair<pappso::PeakIonIsotopeMatch, pappso::PeakIonIsotopeMatch>
      &ion_pair) const;

  /** experimental use with caution
   */
  LinearRegression getIonIsotopeLinearRegression() const;

  private:
  void findComplementIonPairs(const pappso::PeptideSp &peptideSp);

  private:
  std::shared_ptr<FilterChargeDeconvolution> msp_filterChargeDeconvolution;
  std::shared_ptr<FilterMzExclusion> msp_filterMzExclusion;
  std::shared_ptr<FilterResampleKeepGreater> msp_filterKeepGreater;

  std::shared_ptr<PeptideIsotopeSpectrumMatch> msp_peptideSpectrumMatch;
  pappso::PeptideSp msp_peptide;

  PrecisionPtr m_ms2precision;
  std::list<PeptideIon> m_ionList;

  double m_spectrumSumIntensity;

  double m_precursorTheoreticalMz;
  double m_precursorTheoreticalMass;
  unsigned int m_parentCharge = 1;

  std::vector<
    std::pair<pappso::PeakIonIsotopeMatch, pappso::PeakIonIsotopeMatch>>
    m_peakIonPairs;

  double m_matchedMzDiffMean   = 0;
  double m_matchedMzDiffMedian = 0;
  double m_matchedMzDiffSd     = 0;
};
} // namespace pappso
