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


// ./tests/proteincode/catch2-only-proteincode [specglob] -s


#include <catch2/catch_test_macros.hpp>
#include <catch2/catch_approx.hpp>

#include <QString>
#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/filters/filterchargedeconvolution.h>
#include <pappsomspp/core/utils.h>
#include "proteincode_lib.h"
#include "../common.h"
#include "tests/tests-config.h"


TEST_CASE("trim peptide on localized protein region.", "[specglob]")
{
  // Set the debugging message formatting pattern.
  qSetMessagePattern(QString("%{file}@%{line}, %{function}(): %{message}"));

  SECTION(
    "..:: scan_15780 spectrum easy met on fasta file AIADGSIIDIIR "
    "::..",
    "[specglob]")
  {

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

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

    pappso::QualifiedMassSpectrum spectrum_simple = readQualifiedMassSpectrumMgf(
      QString(CMAKE_SOURCE_DIR)
        .append("/tests/data/scans/20120906_balliau_extract_1_A01_urnb-1_15780.mgf"));


    PrecisionPtr precision_ptr = pappso::PrecisionFactory::getDaltonInstance(0.02);
    pappso::FilterChargeDeconvolution(precision_ptr)
      .filter(*(spectrum_simple.getMassSpectrumSPtr().get()));
    pappso::FilterResampleKeepGreater(150).filter(*(spectrum_simple.getMassSpectrumSPtr().get()));
    pappso::FilterGreatestY(120).filter(*(spectrum_simple.getMassSpectrumSPtr().get()));

    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);


    REQUIRE(spectral_alignment.getMaxScore() == 24);
    // INFOS:
    // ;AIADGSSAMLLDLLR++++-289,11;7;11;[A][I][A][D][G][S][S][A][M][-289,11]LLDLLR_[-0,00];[A]IADGSSAM[-289,11]LLDLLR;1;0,00;27;0.3224648627994288
    REQUIRE(spectral_alignment.backTrack().toStdString() ==
            "[A][I]ADGSIID[I][I][R]_[-0.00452147]");

    pappso::specglob::PeptideModel peptide_model = spectral_alignment.buildPeptideModel();

    REQUIRE(peptide_model.toProForma().toStdString() ==
            "[-0.0045]?AIADGSIIDIIR");

    peptide_model.eliminateComplementaryDelta(precision_ptr);

    REQUIRE(peptide_model.toProForma().toStdString() == "[-0.0045]?AIADGSIIDIIR");
    peptide_model.matchExperimentalPeaks(precision_ptr);
    REQUIRE(peptide_model.getCountSharedPeaks() == 11);
  }


  SECTION(
    "..:: scan_3302 spectrum easy met on fasta file GKQQVM[MOD:00719]VGYSDSGK "
    "::..",
    "[specglob]")
  {

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

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

    pappso::QualifiedMassSpectrum spectrum_simple = readQualifiedMassSpectrumMgf(
      QString(CMAKE_SOURCE_DIR)
        .append("/tests/data/scans/"
                "20120906_balliau_extract_1_A08_teal-2_scan_3302.mgf"));


    pappso::FilterGreatestY(80).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);

    // INFOS:
    // ;AIADGSSAMLLDLLR++++-289,11;7;11;[A][I][A][D][G][S][S][A][M][-289,11]LLDLLR_[-0,00];[A]IADGSSAM[-289,11]LLDLLR;1;0,00;27;0.3224648627994288
    REQUIRE(spectral_alignment.backTrack().toStdString() ==
            "[128.095]G[K][-128.095]QQV[M][15.9994]VGYSDSGK_[-0.0038543]");

    REQUIRE(spectral_alignment.getMaxScore() == 52);
    pappso::specglob::PeptideModel peptide_model = spectral_alignment.buildPeptideModel();

    REQUIRE(peptide_model.toProForma().toStdString() ==
            "[-0.0039]?G[+128.0946]K[-128.0953]QQVM[+15.9994]VGYSDSGK");

    peptide_model.eliminateComplementaryDelta(precision_ptr);

    REQUIRE(peptide_model.toProForma().toStdString() == "[-0.0045]?GKQQVM[+15.9994]VGYSDSGK");
    peptide_model.matchExperimentalPeaks(precision_ptr);
    REQUIRE(peptide_model.getCountSharedPeaks() == 14);
    writeSpectralAlignmentMatrix("alignment_matrix_3302_good_seq.ods", spectral_alignment);
  }


  SECTION(
    "..:: trim peptide GKQQVM[MOD:00719]VGYSDSGK "
    "::..",
    "[specglob]")
  {


    pappso::QualifiedMassSpectrum spectrum_simple = readQualifiedMassSpectrumMgf(
      QString(CMAKE_SOURCE_DIR)
        .append("/tests/data/scans/"
                "20120906_balliau_extract_1_A08_teal-2_scan_3302.mgf"));


    pappso::FilterGreatestY(80).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);


    pappso::PeptideSp sampler(
      std::make_shared<pappso::Peptide>("FSVDWYMDRIKGKQQVMVGYSDSGKDAGRLSAAWQLYRAQEEM"));
    pappso::specglob::PeptideSpectraCsp peptide_spectra =
      std::make_shared<pappso::specglob::PeptideSpectrum>(sampler);
    spectral_alignment.align(peptide_spectra, experimental_spectrum);

    REQUIRE(spectral_alignment.getMaxScore() == 0);
    // INFOS:
    // ;AIADGSSAMLLDLLR++++-289,11;7;11;[A][I][A][D][G][S][S][A][M][-289,11]LLDLLR_[-0,00];[A]IADGSSAM[-289,11]LLDLLR;1;0,00;27;0.3224648627994288
    // REQUIRE(spectral_alignment.backTrack().toStdString() ==
    //        "[128.095]G[K][-128.095]QQV[M][15.9994]VGYSDSGK_[-0.0038543]");


    REQUIRE_THROWS_AS(spectral_alignment.buildPeptideModel(), pappso::PappsoException);

    // REQUIRE(peptide_model.toProForma().toStdString() ==
    //       "G[+128.0946]K[-128.0953]QQVM[+15.9994]VGYSDSGK");

    writeSpectralAlignmentMatrix("alignment_matrix_3302.ods", spectral_alignment);


    spectral_alignment.align(peptide_spectra, experimental_spectrum);

    REQUIRE(spectral_alignment.getMaxScore() == 0);

    pappso::specglob::PeptideModel peptide_model = spectral_alignment.rtrim(precision_ptr);

    REQUIRE(spectral_alignment.getMaxScore() == 59);
    REQUIRE(spectral_alignment.backTrack().toStdString() ==
            "KG[K][-128.095]QQV[M][15.9994]VGYSDSGK_[-0.0041749]");
    // GKQQVM[MOD:00719]VGYSDSGK
    REQUIRE(peptide_model.toProForma().toStdString() == "[-0.0045]?GKQQVM[+15.9994]VGYSDSGK");

    peptide_model.matchExperimentalPeaks(precision_ptr);
    peptide_model.removeBracketsForAlignedAA();
    REQUIRE(peptide_model.toProForma().toStdString() == "[-0.0045]?GKQQVM[+15.9994]VGYSDSGK");
    peptide_model.matchExperimentalPeaks(precision_ptr);
    REQUIRE(peptide_model.getCountSharedPeaks() == 14);

    REQUIRE(peptide_model.getMass() ==
            Catch::Approx(experimental_spectrum.get()->getPrecursorMass()).margin(0.01));

    pappso::Aa metox(Enums::AminoAcidChar::methionine);
    metox.addAaModification(pappso::AaModification::getInstance("MOD:00719"));
    peptide_model.checkForAaModification(metox, precision_ptr);

    REQUIRE(peptide_model.toProForma().toStdString() == "GKQQVM[MOD:00719]VGYSDSGK");

    REQUIRE(peptide_model.getMass() ==
            Catch::Approx(experimental_spectrum.get()->getPrecursorMass()).margin(0.01));
  }
}
