//
// File: test_hyperscore.cpp
// Created by: Olivier Langella
// Created on: 13/3/2015
//
/*******************************************************************************
 * Copyright (c) 2015 Olivier Langella <Olivier.Langella@moulon.inra.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 warrantyo f
 *     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/>.
 *
 * Contributors:
 *     Olivier Langella <Olivier.Langella@moulon.inra.fr> - initial API and
 *implementation
 ******************************************************************************/

// ./tests/catch2-only-tests [hyperscore] -s

#include <catch2/catch_test_macros.hpp>

#include <pappsomspp/core/mzrange.h>
#include <pappsomspp/core/peptide/peptidenaturalisotopelist.h>
#include <pappsomspp/core/peptide/peptidefragmentionlistbase.h>
#include <pappsomspp/core/massspectrum/massspectrum.h>
#include <pappsomspp/core/psm/xtandem/xtandemhyperscore.h>
#include <pappsomspp/core/psm/xtandem/xtandemhyperscorebis.h>
#include <pappsomspp/core/psm/xtandem/xtandemspectrumprocess.h>
#include <pappsomspp/core/processing/filters/filterpass.h>
#include <pappsomspp/core/processing/filters/filterresample.h>
#include <iostream>
#include <iomanip>
#include <set>
#include <QDebug>
#include <QString>
#include <cmath>
#include "common.h"
#include "tests/tests-config.h"

using namespace pappso;
using namespace std;
// using namespace pwiz::msdata;


TEST_CASE("Hyperscore test suite.", "[hyperscore]")
{
  // Set the debugging message formatting pattern.
  qSetMessagePattern(QString("%{file}@%{line}, %{function}(): %{message}"));

  SECTION("..:: readMgf ::..", "[hyperscore]")
  {
    std::cout << std::endl << "..:: readMgf ::.." << std::endl;
    bool refine_spectrum_synthesis = false;

    MassSpectrum spectrum_simple =
      readMgf(QString(CMAKE_SOURCE_DIR)
                .append("/tests/data/peaklist_15046_simple_xt.mgf"));
    Peptide peptide("AIADGSLLDLLR");
    PeptideSp peptide_sp(peptide.makePeptideSp());
    // peptide_sp.get()->addAaModification(AaModification::getInstance("MOD:00397"),
    // 0);

    qDebug() << __FILE__ << "@" << __LINE__ << __FUNCTION__ << "()";
    PrecisionPtr precision = PrecisionFactory::getDaltonInstance(0.02);
    std::list<Enums::PeptideIon> ion_list;
    ion_list.push_back(Enums::PeptideIon::y);
    ion_list.push_back(Enums::PeptideIon::b);
    std::cout << "spectrum_simple size  " << spectrum_simple.size()
              << std::endl;

    qDebug() << __FILE__ << "@" << __LINE__ << __FUNCTION__ << "()";
    XtandemHyperscore hyperscore_withxtspectrum(spectrum_simple,
                                                peptide_sp,
                                                2,
                                                precision,
                                                ion_list,
                                                refine_spectrum_synthesis);

    qDebug() << __FILE__ << "@" << __LINE__ << __FUNCTION__ << "()";
    std::cout << "spectrum_simple " << peptide.getSequence().toStdString()
              << " hyperscore=" << hyperscore_withxtspectrum.getHyperscore()
              << std::endl;
    float test_tandem =
      std::round(10 * hyperscore_withxtspectrum.getHyperscore()) / 10;
    REQUIRE(test_tandem == (float)33.5);
    // hyperscore="33.5"


    qDebug() << __FILE__ << "@" << __LINE__ << __FUNCTION__ << "()";
    refine_spectrum_synthesis = true;
    XtandemHyperscore hyperscore_model(spectrum_simple,
                                       peptide_sp,
                                       2,
                                       precision,
                                       ion_list,
                                       refine_spectrum_synthesis);
    std::cout << "spectrum_simple with spectrum model "
              << peptide.getSequence().toStdString()
              << " hyperscore=" << hyperscore_model.getHyperscore()
              << std::endl;
    // hyperscore="35.4"
    test_tandem = round(10 * hyperscore_model.getHyperscore()) / 10;
    REQUIRE(test_tandem == (float)35.4);

    qDebug() << __FILE__ << "@" << __LINE__ << __FUNCTION__ << "()";
    XtandemSpectrumProcess spectrum_process;
    spectrum_process.setMinimumMz(150);
    spectrum_process.setNmostIntense(100);
    spectrum_process.setDynamicRange(100);
    // 	20120906_balliau_extract_1_A01_urnb-1
    // http://pappso.inra.fr/protic/proticprod/angular/#/peptide_hits/947252
    // 35.400
    // pwiz::msdata::MSDataFile
    // dataFile("/home/langella/developpement/git/pappsomspp/test/data/peaklist_15046.mgf");
    qDebug() << __FILE__ << "@" << __LINE__ << __FUNCTION__ << "()";
    MassSpectrum spectrum = spectrum_process.process(
      readMgf(
        QString(CMAKE_SOURCE_DIR).append("/tests/data/peaklist_15046.mgf")),
      628.86414,
      2);
    qDebug() << __FILE__ << "@" << __LINE__ << __FUNCTION__ << "()";
    //.applyCutOff(150).takeNmostIntense(100).applyDynamicRange(100);

    /*
     * <domain id="15046.1.1" start="430" end="441" expect="2.9e-05"
     * mh="1256.7213" delta="-0.0010" hyperscore="35.4" nextscore="32.3"
     * y_score="11.1" y_ions="9" b_score="10.3" b_ions="2" pre="CGDK"
     * post="QVFT" seq="AIADGSLLDLLR" missed_cleavages="0">
     * */

    // spectrum.applyCutOff(150);
    // spectrum_temp.takeNmostIntense(50,spectrum);
    std::cout << "spectrum size  " << spectrum.size() << std::endl;

    refine_spectrum_synthesis = false;

    XtandemHyperscore hyperscore(spectrum,
                                 peptide.makePeptideSp(),
                                 2,
                                 precision,
                                 ion_list,
                                 refine_spectrum_synthesis);

    qDebug() << __FILE__ << "@" << __LINE__ << __FUNCTION__ << "()";
    std::cout << "peptide " << peptide.getSequence().toStdString()
              << " hyperscore=" << hyperscore.getHyperscore() << std::endl;
    // SUCCESS

    qDebug() << __FILE__ << "@" << __LINE__ << __FUNCTION__ << "()";

    //    msconvert
    //    /gorgone/pappso/formation/Janvier2014/TD/mzXML/20120906_balliau_extract_1_A01_urnb-1.mzXML
    //    --filter "scanNumber 2016" --mgf


    MassSpectrum mgf =
      readMgf(QString(CMAKE_SOURCE_DIR).append("/tests/data/scan_2016.mgf"));
    qDebug() << __FILE__ << "@" << __LINE__ << __FUNCTION__ << "()";
    spectrum = spectrum_process.process(mgf, 679.467, 3);

    qDebug() << __FILE__ << "@" << __LINE__ << __FUNCTION__ << "()";

    //.applyCutOff(150).takeNmostIntense(100).applyDynamicRange(100);

    refine_spectrum_synthesis = true;

    Peptide pep("EDKPQPPPEGR");
    PrecisionPtr precisionb = PrecisionFactory::getDaltonInstance(0.02);
    XtandemHyperscore hyperscoreb(spectrum,
                                  pep.makePeptideSp(),
                                  2,
                                  precisionb,
                                  ion_list,
                                  refine_spectrum_synthesis);

    qDebug() << __FILE__ << "@" << __LINE__ << __FUNCTION__ << "()";
    std::cout << "peptide " << pep.getSequence().toStdString()
              << " hyperscore=" << hyperscoreb.getHyperscore() << std::endl;

    qDebug() << __FILE__ << "@" << __LINE__ << __FUNCTION__ << "()";
    // match ion ED b 245.077, pi=15 for X!Tandem
    //"ED" 245.077   1  intensity: 20.155  Pi= 15  sum= 448.197
    // Spectrum::getHyperscore peak match !  245.046   -0.031235


    // 15968
    //    msconvert
    //    /gorgone/pappso/formation/Janvier2014/TD/mzXML/20120906_balliau_extract_1_A01_urnb-1.mzXML
    //    --filter "scanNumber 15968" --mgf
    spectrum =
      readMgf(QString(CMAKE_SOURCE_DIR).append("/tests/data/scan_15968.mgf"));

    FilterResampleKeepGreater(150).filter(spectrum);

    refine_spectrum_synthesis = true;
    // spectrum.debugPrintValues();
    Peptide pep15968("EITLGFVDLLR");

    XtandemSpectrumProcess xt_spectrum_process;
    xt_spectrum_process.setExcludeParent(true);
    xt_spectrum_process.setDynamicRange(100);
    xt_spectrum_process.setNmostIntense(100);
    // spectrum = spectrum.removeParent(pep15968.makePeptideSp(), 2, 2,
    // 2).takeNmostIntense(100).applyDynamicRange(100);
    spectrum = xt_spectrum_process.process(spectrum, 638.36934732588, 2);
    XtandemHyperscore hyperscore15968(spectrum,
                                      pep15968.makePeptideSp(),
                                      2,
                                      precisionb,
                                      ion_list,
                                      refine_spectrum_synthesis);
    std::cout << "peptide " << pep15968.getSequence().toStdString()
              << " hyperscore15968=" << hyperscore15968.getHyperscore()
              << std::endl;
    std::cout << "peptide " << pep15968.getSequence().toStdString()
              << " mz1=" << pep15968.getMz(1) << " mz2=" << pep15968.getMz(2)
              << std::endl;

    std::vector<Enums::PeptideIon> ion_vec;
    ion_vec.push_back(Enums::PeptideIon::y);
    ion_vec.push_back(Enums::PeptideIon::b);
    XtandemHyperscoreBis hyperscore15968bis(
      refine_spectrum_synthesis, precisionb, ion_vec);
    if(hyperscore15968bis.computeXtandemHyperscore(spectrum, pep15968, 2))
      {
        std::cout << "XtandemHyperscoreBis peptide "
                  << pep15968.getSequence().toStdString()
                  << " hyperscore15968bis="
                  << hyperscore15968bis.getHyperscore() << std::endl;
        std::cout << "XtandemHyperscoreBis peptide "
                  << pep15968.getSequence().toStdString()
                  << " mz1=" << pep15968.getMz(1)
                  << " mz2=" << pep15968.getMz(2) << std::endl;
      }

    // FISLQLGQPPAMGSHM(MOD:00719)TDSNSR

    // Spectrum::getHyperscore  "b"  itmap->second  3   6
    //  Spectrum::getHyperscore  "y"  itmap->second  10   3628800
  }
}
