/**
 * \file pappsomspp/masschroq/peptidemeasurements.cpp
 * \date 26/09/2024
 * \author Olivier Langella
 * \brief peptide extracted measures model in masschroqlite
 */

/*******************************************************************************
 * Copyright (c) 2024 Olivier Langella
 *<Olivier.Langella@universite-paris-saclay.fr>.
 *
 * This file is part of MassChroQ.
 *
 *     MassChroQ 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.
 *
 *     MassChroQ 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 MassChroQ.  If not, see <http://www.gnu.org/licenses/>.
 *
 ******************************************************************************/

#include "peptidemeasurements.h"
#include "peptideobservation.h"
#include "msrungroup.h"
#include "pappsomspp/core/processing/detection/tracepeaklist.h"
#include "pappsomspp/core/pappsoexception.h"

pappso::masschroq::PeptideMeasurements::PeptideMeasurements(
  const pappso::masschroq::PeptideObservationSp &peptide)
{
  msp_peptideObservation = peptide;
}

pappso::masschroq::PeptideMeasurements::PeptideMeasurements(const PeptideMeasurements &other)
  : PeptideMeasurementsBase(other)
{
  msp_peptideObservation = other.msp_peptideObservation;
}

pappso::masschroq::PeptideMeasurements::~PeptideMeasurements()
{
}

void
pappso::masschroq::PeptideMeasurements::prepareMeasurements(
  const pappso::MsRunId &targeted_msrun,
  const pappso::masschroq::MsRunGroup *msrun_group_p,
  const QuantificationMethodSp &quantification_method)
{
  // for one peptide
  pappso::masschroq::Peptide *the_peptide_p = msp_peptideObservation.get()->getPeptideSp().get();
  //  1) charge states
  //  2) isotope list
  std::vector<std::uint8_t> charge_states = the_peptide_p->getAllObservedChargeStateList();

  double best_rt = msp_peptideObservation.get()->getBestRtOverallChargeStates();


  pappso::XicCoordSPtr best_xic_coord = msp_peptideObservation.get()->getBestXicCoord();

  if(best_xic_coord.get() == nullptr)
    {
      throw pappso::PappsoException("best_xic_coord.get() == nullptr");
    }

  for(std::uint8_t charge : charge_states)
    {

      if(msrun_group_p->getIonMobilityGridSp().get() != nullptr)
        {
          // Ion mobility TimsTOF coordinates
          best_xic_coord = msp_peptideObservation.get()->getBestXicCoordSPtrForCharge(charge);

          if(best_xic_coord.get() == nullptr)
            {
              // now in this ms run, we do not have ion mobility index for
              // this charge we must chek out in other msrun for this charge
              best_xic_coord = the_peptide_p->getBestIonMobilityXicCoordToExtractOverallMsRunGroup(
                *msrun_group_p, targeted_msrun, charge);
            }
          if(best_xic_coord.get() == nullptr)
            continue;

          best_xic_coord.get()->rtTarget = best_rt;
        }

      prepareMeasurementsForPeptide(
        *the_peptide_p, quantification_method, best_xic_coord, charge, best_rt);
    }
}


void
pappso::masschroq::PeptideMeasurements::detectQuantifyPeaks(
  const QuantificationMethodSp &quantification_method)
{

  qDebug();
  pappso::TracePeakList peak_list;
  std::vector<double> observed_rt_list =
    msp_peptideObservation.get()->getObservedRetentionTimesOverallChargeStates();

  std::vector<std::uint8_t> observed_charge_states =
    msp_peptideObservation->getObservedChargeStates();

  for(auto &measure_one : m_measurementList)
    {
      qDebug();
      pappso::Xic *xic_p = measure_one.msp_xicCoord.get()->xicSptr.get();
      if(xic_p == nullptr)
        {
          throw pappso::PappsoException(QObject::tr("xic_p == nullptr"));
        }
      peak_list.clear();
      std::size_t nb_peaks = 0;
      quantification_method.get()->getTraceDetectionInterfaceCstSPtr().get()->detect(
        *xic_p, peak_list, false);

      qDebug();
      auto it_best_matched_peak = findBestTracePeakGivenRtList(
        peak_list.begin(), peak_list.end(), observed_rt_list, nb_peaks);

      qDebug();
      measure_one.m_peakQualityCategory       = PeakQualityCategory::missed;
      bool direct_charge_observation_in_msrun = true;
      if(observed_charge_states.end() ==
         find(observed_charge_states.begin(), observed_charge_states.end(), measure_one.m_charge))
        {
          direct_charge_observation_in_msrun = false;
        }
      if(it_best_matched_peak != peak_list.end())
        {
          measure_one.m_tracePeakSp = it_best_matched_peak->makeTracePeakCstSPtr();
          if(nb_peaks == 1)
            {

              measure_one.m_peakQualityCategory = PeakQualityCategory::za;
              if(direct_charge_observation_in_msrun)
                measure_one.m_peakQualityCategory = PeakQualityCategory::a;

              if(observed_rt_list.size() > 1)
                {
                  measure_one.m_peakQualityCategory = PeakQualityCategory::zaa;
                  if(direct_charge_observation_in_msrun)
                    measure_one.m_peakQualityCategory = PeakQualityCategory::aa;
                }
            }
          else if(nb_peaks > 1)
            {
              measure_one.m_peakQualityCategory = PeakQualityCategory::zab;
              if(direct_charge_observation_in_msrun)
                measure_one.m_peakQualityCategory = PeakQualityCategory::ab;
            }
        }
    }
}

const pappso::masschroq::PeptideObservationSp &
pappso::masschroq::PeptideMeasurements::getPeptideObservationSp() const
{
  return msp_peptideObservation;
}
