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

#include <QFileInfo>
#include "proteinmatch.h"
#include "msrun.h"

#include "grouping/groupingexperiment.h"
#include "grouping/ptm/ptmgroupingexperiment.h"
#include "../utils/types.h"
#include "../utils/workmonitor.h"

#pragma once


class Project;

/** @brief an identification group contains one or more sample to consider for
 * grouping
 */
class IdentificationGroup
{

  public:
  IdentificationGroup(Project *project);
  virtual ~IdentificationGroup();

  ProteinMatch *getProteinMatchInstance(const QString accession);
  const GroupStore &getGroupStore() const;
  void addProteinMatch(ProteinMatch *protein_match);
  std::vector<ProteinMatch *> &getProteinMatchList();
  const std::vector<ProteinMatch *> &getProteinMatchList() const;
  void addIdentificationDataSourceP(
    IdentificationDataSource *p_identification_source);

  const PtmGroupingExperiment *getPtmGroupingExperiment() const;

  /** @brief compute proto NSAF sum within msrun
   * Warning: this is not NSAF, just a part
   * @param p_msrun_id pointer on the msrun to get NSAF.
   * */
  pappso::pappso_double
  computeProtoNsafSumFirstInSg(const MsRun *p_msrun_id,
                               const Label *p_label = nullptr) const;

  /** @brief count groups
   * */
  std::size_t countGroup() const;

  /** @brief count subgroups
   * */
  std::size_t countSubGroup() const;

  /** @brief count proteins
   * */
  std::size_t countProteinMatch(ValidationState state) const;

  /** @brief count decoy proteins
   * */
  std::size_t countDecoyProteinMatch(ValidationState state) const;

  /** @brief count peptide evidences (peptide spectrum match + identification
   * engine)
   * */
  std::size_t countPeptideEvidence(ValidationState state) const;

  /** @brief count peptide evidences (peptide spectrum match + identification
   * engine)
   * */
  std::size_t countDecoyPeptideEvidence(ValidationState state) const;

  /** @brief count peptide match (peptide spectrum match + protein match)
   * */
  std::size_t countPeptideMatch(ValidationState state) const;

  /** @brief count decoy peptide match
   * */
  std::size_t countDecoyPeptideMatch(ValidationState state) const;

  /** @brief count distinct peptides overall samples(peptide+mass) including
   * peptides from decoy proteins
   * */
  std::size_t countPeptideMass(ValidationState state) const;

  /** @brief count peptide (peptide+mass+sample) including peptides from decoy
   * proteins
   * */
  std::size_t countPeptideMassSample(ValidationState state) const;

  /** @brief count peptide (peptide+mass+sample) only on decoy proteins
   * */
  std::size_t countDecoyPeptideMassSample(ValidationState state) const;

  /** @brief get False Discovery Rate of proteins
   */
  pappso::pappso_double
  getProteinFdr(ValidationState state = ValidationState::valid) const;

  /** @brief get False Discovery Rate of peptide/mass (unique
   * sequence+modifications)
   */
  pappso::pappso_double
  getPeptideMassFdr(ValidationState state = ValidationState::valid) const;

  /** @brief get False Discovery Rate of psm, peptide spectrum match (unique
   * PeptideEvidence object)
   */
  pappso::pappso_double
  getPsmFdr(ValidationState state = ValidationState::valid) const;


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

  void startGrouping(ContaminantRemovalMode contaminantRemovalMode,
                     const GroupingType &grouping_type,
                     WorkMonitorInterface *p_work_monitor);
  /** @brief creates a new PTM grouping experiment
   * @param ptm_mode choose available PTM mode in enumeration
   * */
  void startPtmGrouping(PtmMode ptm_mode);

  const std::vector<MsRunSp> &getMsRunSpList() const;
  const std::vector<IdentificationDataSource *> &
  getIdentificationDataSourceList() const;

  /** @brief get tab name for qtabwidget
   * */
  const QString getTabName() const;

  bool contains(const MsRun *p_msrun) const;
  bool containSample(const QString &sample) const;


  /** @brief collect mass delta between theoretical mass and observed mass for
   * target sequences
   *
   * each peptide evidence is only counted once it counts only
   * peptide evidence for target Sequences
   * @param delta_list list of mass delta
   * @param unit precision unit, ppm or dalton
   * @param state validation state of the peptides to collect
   */
  void collectMhDelta(std::vector<pappso::pappso_double> &delta_list,
                      pappso::Enums::PrecisionUnit unit,
                      ValidationState state) const;


  /** @brief collect mass delta between theoretical mass and observed mass
   *
   * each peptide evidence is only counted once it counts target or decoy
   * peptide evidence
   * @param delta_list list of mass delta
   * @param unit precision unit, ppm or dalton
   * @param state validation state of the peptides to collect
   */
  void collectTargetDecoyMhDelta(std::vector<pappso::pappso_double> &delta_list,
                                 pappso::Enums::PrecisionUnit unit,
                                 ValidationState state) const;


  /** @brief look for a peptide in the same XIC
   * @param peptide_evidence_list the peptide evidence list to build
   * @param p_msrun MSrun to look for
   * @param p_peptide peptide to look for
   * @param charge charge to look for
   */
  void getSameXicPeptideEvidenceList(
    std::vector<const PeptideEvidence *> &peptide_evidence_list,
    const MsRun *p_msrun,
    const PeptideXtp *p_peptide,
    unsigned int charge) const;

  private:
  void addMsRunSp(MsRunSp ms_run_sp);

  private:
  GroupingExperiment *_p_grp_experiment        = nullptr;
  PtmGroupingExperiment *_p_grp_ptm_experiment = nullptr;

  Project *_p_project;

  GroupStore _group_store;

  std::vector<ProteinMatch *> _protein_match_list;

  std::vector<MsRunSp> _ms_run_list;
  std::vector<IdentificationDataSource *> _id_source_list;

  std::map<QString, ProteinMatch *> _cache_accession_protein_match;
};
