/**
 * \file tests/test_sgposttreatment.cpp
 * \date 15/11/2023
 * \author Olivier Langella
 * \brief tests for peptide model post treatment
 */


/*
 * SpecGlobTool, Spectra to peptide alignment tool
 * Copyright (C) 2023  Olivier Langella
 * <olivier.langella@universite-paris-saclay.fr>
 *
 * This program 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.
 *
 * This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */
// ./tests/catch2-only-tests [post] -s


#include <QDebug>
#include <QString>
#include <catch2/catch_test_macros.hpp>
#include <catch2/catch_approx.hpp>
#include "config.h"
#include "common.h"
#include <pappsomspp/core/massspectrum/massspectrum.h>
#include <pappsomspp/core/processing/filters/filterresample.h>
#include <pappsomspp/core/processing/filters/filterpass.h>
#include <pappsomspp/core/processing/specglob/spectralalignment.h>
#include <pappsomspp/core/processing/specglob/posttreatment.h>
#include <pappsomspp/core/utils.h>

TEST_CASE("specglob test post treatment of peptide model", "[post]")
{
  // Set the debugging message formatting pattern.scores to apply in comparisons
  qSetMessagePattern(QString("%{file}@%{line}, %{function}(): %{message}"));


  SECTION("..:: test with good sequence AIADGSLLDLLR ::..", "[post]")
  {

    pappso::PeptideSp sampler(
      std::make_shared<pappso::Peptide>("AIADGSLLDLLR"));

    pappso::specglob::PeptideSpectraCsp peptide_spectra =
      std::make_shared<pappso::specglob::PeptideSpectrum>(sampler);

    QualifiedMassSpectrum spectrum_simple =
      readMgf(QString(CMAKE_SOURCE_DIR)
                .append("/tests/data/peaklists/peaklist_15046.mgf"));
    pappso::FilterGreatestY(60).filter(
      *(spectrum_simple.getMassSpectrumSPtr().get()));

    PrecisionPtr precision_ptr =
      pappso::PrecisionFactory::getDaltonInstance(0.02);

    pappso::specglob::ExperimentalSpectrumCsp experimental_spectrum =
      std::make_shared<pappso::specglob::ExperimentalSpectrum>(spectrum_simple,
                                                               precision_ptr);
    pappso::specglob::SpectralAlignment spectral_alignment(
      pappso::specglob::ScoreValues(), precision_ptr);

    spectral_alignment.align(peptide_spectra, experimental_spectrum);

    pappso::specglob::PostTreatment treatment(
      precision_ptr, spectral_alignment.buildPeptideModel());

    REQUIRE(treatment.getBetterPeptideModel().toString().toStdString() ==
            "AIADGSLLDLLR");
  }

  SECTION("..:: test with wrong sequence AIADGSLLDLLR ::..", "[post]")
  {

    pappso::PeptideSp sampler(
      std::make_shared<pappso::Peptide>("AIADGSSAMLLDLLR"));

    pappso::specglob::PeptideSpectraCsp peptide_spectra =
      std::make_shared<pappso::specglob::PeptideSpectrum>(sampler);

    QualifiedMassSpectrum spectrum_simple =
      readMgf(QString(CMAKE_SOURCE_DIR)
                .append("/tests/data/peaklists/peaklist_15046.mgf"));
    pappso::FilterGreatestY(60).filter(
      *(spectrum_simple.getMassSpectrumSPtr().get()));

    PrecisionPtr precision_ptr =
      pappso::PrecisionFactory::getDaltonInstance(0.02);

    pappso::specglob::ExperimentalSpectrumCsp experimental_spectrum =
      std::make_shared<pappso::specglob::ExperimentalSpectrum>(spectrum_simple,
                                                               precision_ptr);

    REQUIRE(experimental_spectrum.get()->getTargetMzSum() ==
            Catch::Approx(1257.72828));
    pappso::specglob::SpectralAlignment spectral_alignment(
      pappso::specglob::ScoreValues(), precision_ptr);

    spectral_alignment.align(peptide_spectra, experimental_spectrum);

    pappso::specglob::PostTreatment treatment(
      precision_ptr, spectral_alignment.buildPeptideModel());

    qDebug() << treatment.getBetterPeptideModel().toString();
    REQUIRE(treatment.getBetterPeptideModel().toString().toStdString() ==
            "[A]IADGS-([S][A][M][-289.11])LLDLLR");
  }

  pappso::PeptideSp sampler(
    std::make_shared<pappso::Peptide>("DATNVGDEGGFAPNIIENK"));

  pappso::specglob::PeptideSpectraCsp peptide_spectra =
    std::make_shared<pappso::specglob::PeptideSpectrum>(sampler);

  SECTION("..:: test with SpecGlobX test file ::..",
          "[DATNVGDEGGFAPNIIENK 55451]")
  {

    QualifiedMassSpectrum spectrum_simple =
      readMgf(QString(CMAKE_SOURCE_DIR)
                .append("/tests/data/publi/DATNVGDEGGFAPNIIENK.mgf"),
              55451);
    REQUIRE(spectrum_simple.getMassSpectrumId().getSpectrumIndex() == 62);
    pappso::FilterGreatestY(100).filter(
      *(spectrum_simple.getMassSpectrumSPtr().get()));

    PrecisionPtr precision_ptr =
      pappso::PrecisionFactory::getDaltonInstance(0.02);

    pappso::specglob::ExperimentalSpectrumCsp experimental_spectrum =
      std::make_shared<pappso::specglob::ExperimentalSpectrum>(spectrum_simple,
                                                               precision_ptr);

    REQUIRE(experimental_spectrum.get()->getTargetMzSum() ==
            Catch::Approx(1961.9336));
    pappso::specglob::SpectralAlignment spectral_alignment(
      pappso::specglob::ScoreValues(), precision_ptr);

    spectral_alignment.align(peptide_spectra, experimental_spectrum);


    REQUIRE(spectral_alignment.getMaxScore() == 13);
    pappso::specglob::PostTreatment treatment(
      precision_ptr, spectral_alignment.buildPeptideModel());

    qDebug() << treatment.getBetterPeptideModel().toString();

    // Title;SharedPeaksBeforeAlign;SharedPeaksAfterAlign;AlignedPeptide;ScoreAlign;IntensityExplained
    // b1922_293T_proteinID_02A_QE3_122212.raw.55451;14;14;[D]ATNVG[D]EG[G]FAP[N][I]IENK;13;0.394183708
    REQUIRE(treatment.getBetterPeptideModel().toString().toStdString() ==
            "[D]ATNVG[D]EG[G]FAP[N][I]IENK");
    // same as java

    REQUIRE(treatment.getBetterPeptideModel().getCountSharedPeaks() == 14);
    REQUIRE(
      treatment.getBetterPeptideModel().getIntensitySharedPeaks() /
        treatment.getBetterPeptideModel().getIntensityExperimentalPeaks() ==
      Catch::Approx(0.394183708));
  }


  SECTION("..:: test with SpecGlobX test file ::..",
          "[DATNVGDEGGFAPNIIENK 54219]")
  {

    QualifiedMassSpectrum spectrum_simple =
      readMgf(QString(CMAKE_SOURCE_DIR)
                .append("/tests/data/publi/DATNVGDEGGFAPNIIENK.mgf"),
              54219);
    REQUIRE(spectrum_simple.getMassSpectrumId().getSpectrumIndex() == 36);
    pappso::FilterGreatestY(60).filter(
      *(spectrum_simple.getMassSpectrumSPtr().get()));

    PrecisionPtr precision_ptr =
      pappso::PrecisionFactory::getDaltonInstance(0.02);

    pappso::specglob::ExperimentalSpectrumCsp experimental_spectrum =
      std::make_shared<pappso::specglob::ExperimentalSpectrum>(spectrum_simple,
                                                               precision_ptr);
    pappso::specglob::SpectralAlignment spectral_alignment(
      pappso::specglob::ScoreValues(), precision_ptr);
    spectral_alignment.align(peptide_spectra, experimental_spectrum);

    pappso::specglob::PostTreatment treatment(
      precision_ptr, spectral_alignment.buildPeptideModel());

    // Title;SharedPeaksBeforeAlign;SharedPeaksAfterAlign;AlignedPeptide;ScoreAlign;IntensityExplained
    // b1922_293T_proteinID_02A_QE3_122212.raw.54219;15;16;[D]ATNV[G][D][-514,20]EGG[514,20]FAPNIIENK;56;0.429572293


    REQUIRE(spectral_alignment.getMaxScore() == 56);
    REQUIRE(treatment.getBetterPeptideModel().toString().toStdString() ==
            "[D]ATNV[G][D]EGGFAPNIIENK");

    REQUIRE(treatment.getBetterPeptideModel().getCountSharedPeaks() == 15);
    REQUIRE(
      treatment.getBetterPeptideModel().getIntensitySharedPeaks() /
        treatment.getBetterPeptideModel().getIntensityExperimentalPeaks() ==
      Catch::Approx(0.4107375786));
    // OK
  }


  SECTION("..:: test with SpecGlobX test file ::..",
          "[DATNVGDEGGFAPNIIENK 53962]")
  {

    QualifiedMassSpectrum spectrum_simple =
      readMgf(QString(CMAKE_SOURCE_DIR)
                .append("/tests/data/publi/DATNVGDEGGFAPNIIENK.mgf"),
              53962);
    REQUIRE(spectrum_simple.getMassSpectrumId().getSpectrumIndex() == 20);
    pappso::FilterGreatestY(60).filter(
      *(spectrum_simple.getMassSpectrumSPtr().get()));

    PrecisionPtr precision_ptr =
      pappso::PrecisionFactory::getDaltonInstance(0.02);

    pappso::specglob::ExperimentalSpectrumCsp experimental_spectrum =
      std::make_shared<pappso::specglob::ExperimentalSpectrum>(spectrum_simple,
                                                               precision_ptr);
    pappso::specglob::SpectralAlignment spectral_alignment(
      pappso::specglob::ScoreValues(), precision_ptr);
    spectral_alignment.align(peptide_spectra, experimental_spectrum);

    pappso::specglob::PostTreatment treatment(
      precision_ptr, spectral_alignment.buildPeptideModel());

    // Title;SharedPeaksBeforeAlign;SharedPeaksAfterAlign;AlignedPeptide;ScoreAlign;IntensityExplained
    // b1922_293T_proteinID_02A_QE3_122212.raw.53962;15;15;[D]ATNV[G][D][-514,20]EGGFAPNIIENK_[515,20];54;0.393881648

    REQUIRE(
      treatment.getBetterPeptideModel()
        .getTheoreticalPeakDataPointListToString()
        .toStdString() ==
      "{116.034,0,0,D}{147.113,1.19549e+06,18,K}{159.075,3.41728e+06,6,D}{187."
      "071,4.20531e+06,1,A}{261.156,5.40787e+06,17,N}{288.118,1.63189e+06,7,E}{"
      "288.119,0,2,T}{345.139,784367,8,G}{390.198,3.02316e+06,16,E}{402.161,2."
      "22344e+06,9,G}{402.162,0,3,N}{501.23,4.3566e+06,4,V}{503.282,6.4255e+06,"
      "15,I}{549.229,0,10,F}{558.252,0,5,G}{616.366,3.06085e+06,14,I}{620.266,"
      "0,11,A}{717.319,0,12,P}{730.409,3.54028e+06,13,N}{827.462,2.08459e+07,"
      "12,P}{831.362,0,13,N}{889.477,0,6,D}{898.499,4.47063e+06,11,A}{944.446,"
      "0,14,I}{946.498,0,5,G}{1045.57,0,4,V}{1045.57,0,10,F}{1057.53,0,15,I}{"
      "1102.59,0,9,G}{1159.61,978459,3,N}{1159.61,0,8,G}{1186.57,0,16,E}{1260."
      "66,0,2,T}{1288.65,0,7,E}{1300.62,0,17,N}{1331.69,0,1,A}");

    REQUIRE(spectral_alignment.getMaxScore() == 54);
    REQUIRE(treatment.getBetterPeptideModel().toString().toStdString() ==
            "[D]A[T]NV[G]D[-514.20]EGGFAPNIIENK_[515.21]");

    REQUIRE(treatment.getBetterPeptideModel().getCountSharedPeaks() == 15);
    REQUIRE(
      treatment.getBetterPeptideModel().getIntensitySharedPeaks() /
        treatment.getBetterPeptideModel().getIntensityExperimentalPeaks() ==
      Catch::Approx(0.3938816483));
  }


  SECTION("..:: test with SpecGlobX test file ::..",
          "[DATNVGDEGGFAPNIIENK 59385]")
  {

    QualifiedMassSpectrum spectrum_simple =
      readMgf(QString(CMAKE_SOURCE_DIR)
                .append("/tests/data/publi/DATNVGDEGGFAPNIIENK.mgf"),
              59385);
    REQUIRE(spectrum_simple.getMassSpectrumId().getSpectrumIndex() == 72);
    pappso::FilterGreatestY(60).filter(
      *(spectrum_simple.getMassSpectrumSPtr().get()));

    PrecisionPtr precision_ptr =
      pappso::PrecisionFactory::getDaltonInstance(0.02);

    pappso::specglob::ExperimentalSpectrumCsp experimental_spectrum =
      std::make_shared<pappso::specglob::ExperimentalSpectrum>(spectrum_simple,
                                                               precision_ptr);
    pappso::specglob::SpectralAlignment spectral_alignment(
      pappso::specglob::ScoreValues(), precision_ptr);
    spectral_alignment.align(peptide_spectra, experimental_spectrum);

    pappso::specglob::PostTreatment treatment(
      precision_ptr, spectral_alignment.buildPeptideModel());

    // Title;SharedPeaksBeforeAlign;SharedPeaksAfterAlign;AlignedPeptide;ScoreAlign;IntensityExplained
    // b1922_293T_proteinID_02A_QE3_122212.raw.59385;12;12;[D][A][T][N]VG[D][E]GG[F]APN[I]IENK_[1228,74];13;0.196788788

    REQUIRE(
      treatment.getBetterPeptideModel()
        .getTheoreticalPeakDataPointListToString()
        .toStdString() ==
      "{116.034,0,0,D}{147.113,5219.7,18,K}{187.071,0,1,A}{261.156,13862.1,17,"
      "N}{288.119,0,2,T}{390.198,13645.2,16,E}{402.162,0,3,N}{501.23,4312.9,4,"
      "V}{503.282,23963,15,I}{558.252,0,5,G}{616.366,0,14,I}{673.279,0,6,D}{"
      "730.409,5423.8,13,N}{802.321,0,7,E}{827.462,63043.5,12,P}{859.343,0,8,G}"
      "{898.499,31619.2,11,A}{916.364,0,9,G}{1045.57,0,10,F}{1063.43,0,10,F}{"
      "1102.59,5659.4,9,G}{1134.47,0,11,A}{1159.61,17522.7,8,G}{1231.52,0,12,P}"
      "{1288.65,0,7,E}{1345.57,0,13,N}{1403.68,0,6,D}{1458.65,0,14,I}{1460.7,"
      "25679.3,5,G}{1559.77,0,4,V}{1571.73,0,15,I}{1673.81,0,3,N}{1700.78,0,16,"
      "E}{1774.86,0,2,T}{1814.82,0,17,N}{1845.9,0,1,A}");

    REQUIRE(spectral_alignment.getMaxScore() == 13);
    REQUIRE(treatment.getBetterPeptideModel().toString().toStdString() ==
            "[D][A][T][N]VG[D][E]GG[F]APN[I]IENK_[1228.74]");
    // same as Java

    REQUIRE(treatment.getBetterPeptideModel().getCountSharedPeaks() == 11);
    REQUIRE(
      treatment.getBetterPeptideModel().getIntensitySharedPeaks() /
        treatment.getBetterPeptideModel().getIntensityExperimentalPeaks() ==
      Catch::Approx(0.1924142781));
  }


  SECTION("..:: test with SpecGlobX test file ::..",
          "[DATNVGDEGGFAPNIIENK 59357]")
  {

    QualifiedMassSpectrum spectrum_simple =
      readMgf(QString(CMAKE_SOURCE_DIR)
                .append("/tests/data/publi/DATNVGDEGGFAPNIIENK.mgf"),
              59357);
    REQUIRE(spectrum_simple.getMassSpectrumId().getSpectrumIndex() == 71);
    pappso::FilterGreatestY(60).filter(
      *(spectrum_simple.getMassSpectrumSPtr().get()));

    PrecisionPtr precision_ptr =
      pappso::PrecisionFactory::getDaltonInstance(0.02);

    pappso::specglob::ExperimentalSpectrumCsp experimental_spectrum =
      std::make_shared<pappso::specglob::ExperimentalSpectrum>(spectrum_simple,
                                                               precision_ptr);
    pappso::specglob::SpectralAlignment spectral_alignment(
      pappso::specglob::ScoreValues(), precision_ptr);
    spectral_alignment.align(peptide_spectra, experimental_spectrum);

    pappso::specglob::PostTreatment treatment(
      precision_ptr, spectral_alignment.buildPeptideModel());

    // Title;SharedPeaksBeforeAlign;SharedPeaksAfterAlign;AlignedPeptide;ScoreAlign;IntensityExplained
    // b1922_293T_proteinID_02A_QE3_122212.raw.59357;15;15;[D][A][T][N]VGDEGGFAP[N]IIENK_[61,04];64;0.354033613

    REQUIRE(spectral_alignment.getMaxScore() == 53);
    REQUIRE(treatment.getBetterPeptideModel().toString().toStdString() ==
            "[D][A][T][N]VGDEGGFAP[N]IIENK_[61.04]");
    // same as Java

    REQUIRE(treatment.getBetterPeptideModel().getCountSharedPeaks() == 15);
    REQUIRE(
      treatment.getBetterPeptideModel().getIntensitySharedPeaks() /
        treatment.getBetterPeptideModel().getIntensityExperimentalPeaks() ==
      Catch::Approx(0.3540336131));
  }


  SECTION("..:: test with SpecGlobX test file ::..",
          "[DATNVGDEGGFAPNIIENK 46761]")
  {

    QualifiedMassSpectrum spectrum_simple =
      readMgf(QString(CMAKE_SOURCE_DIR)
                .append("/tests/data/publi/DATNVGDEGGFAPNIIENK.mgf"),
              46761);
    REQUIRE(spectrum_simple.getMassSpectrumId().getSpectrumIndex() == 0);
    pappso::FilterGreatestY(60).filter(
      *(spectrum_simple.getMassSpectrumSPtr().get()));

    PrecisionPtr precision_ptr =
      pappso::PrecisionFactory::getDaltonInstance(0.02);

    pappso::specglob::ExperimentalSpectrumCsp experimental_spectrum =
      std::make_shared<pappso::specglob::ExperimentalSpectrum>(spectrum_simple,
                                                               precision_ptr);
    pappso::specglob::SpectralAlignment spectral_alignment(
      pappso::specglob::ScoreValues(), precision_ptr);
    spectral_alignment.align(peptide_spectra, experimental_spectrum);

    pappso::specglob::PostTreatment treatment(
      precision_ptr, spectral_alignment.buildPeptideModel());

    // Title;SharedPeaksBeforeAlign;SharedPeaksAfterAlign;AlignedPeptide;ScoreAlign;IntensityExplained
    // b1922_293T_proteinID_02A_QE3_122212.raw.46761;13;13;[D]ATNV[G][D][E][G]G[F]APNIIENK_[30,03];41;0.314416833

    REQUIRE(spectral_alignment.getMaxScore() == 41);
    REQUIRE(treatment.getBetterPeptideModel().toString().toStdString() ==
            "[D]ATNV[G][D][E][G]G[F]APNIIENK_[30.03]");
    // same as Java

    REQUIRE(treatment.getBetterPeptideModel().getCountSharedPeaks() == 13);
    REQUIRE(
      treatment.getBetterPeptideModel().getIntensitySharedPeaks() /
        treatment.getBetterPeptideModel().getIntensityExperimentalPeaks() ==
      Catch::Approx(0.3144168332));
  }
}
