//
// File: test_peptidenaturalisotopelist.cpp
// Created by: Olivier Langella
// Created on: 9/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 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/>.
 *
 * Contributors:
 *     Olivier Langella <Olivier.Langella@moulon.inra.fr> - initial API and
 *implementation
 ******************************************************************************/
// make test ARGS="-V -I 7,7"


#include <pappsomspp/precision.h>
#include <pappsomspp/peptide/peptidenaturalisotopelist.h>
#include <pappsomspp/peptide/peptidenaturalisotopeaverage.h>
#include <pappsomspp/peptide/peptidefragmention.h>
#include <pappsomspp/peptide/peptidefragmentionlistbase.h>
#include <pappsomspp/peptide/peptidestrparser.h>
#include <iostream>
#include <QDebug>
#include <QString>

using namespace pappso;
using namespace std;

int
main()
{

  cout << std::endl << "..:: peptide natural isotope list init ::.." << std::endl;
  Peptide peptide("LA");

  PeptideNaturalIsotopeList isotopeList(peptide.makePeptideSp());
  cout << std::endl << "isotope list OK" << isotopeList.size() << std::endl;

  PeptideNaturalIsotopeList::const_iterator it(isotopeList.begin());

  while(it != isotopeList.end())
    {
      // qDebug() <<  it->getIntensityRatio();
      cout << std::endl << it->get()->getSequence().toStdString();
      cout.flush();
      cout << "..:: " << it->get()->getFormula(1).toStdString();
      cout.flush();
      cout << " C13=" << it->get()->getNumberOfIsotope(Isotope::C13);
      cout.flush();
      cout << " mass=" << it->get()->getMz(1);
      cout.flush();
      cout << " mz(2)=" << it->get()->getMz(2);
      cout.flush();

      cout << " ratio=" << it->get()->getIntensityRatio(1) << " ::.." << std::endl;
      it++;
    }
  cout << std::endl << "print isotope list OK" << std::endl;
  // MassRange mz_range(peptide.getMass(), ppm_precision(10));
  // if (!mz_range.contains(Aa('L').getMass()+Aa('A').getMass()))
  //    return 1;
  //    Peptide peptideb ("TAPSDVLAVELLQR");
  //   PeptideNaturalIsotopeList isotopeListb(peptideb.getPeptideSp());
  // http://pappso.inra.fr/protic/proticprod/angular/#/peptide_hits/947229
  // http://pappso.inra.fr/protic/proticprod/angular/#/peptide_hits/947252

  // AIADGSLLDLLR
  // http://prospector.ucsf.edu/prospector/cgi-bin/mssearch.cgi

  Peptide peptideb("AIADGSLLDLLR");
  peptideb.addAaModification(AaModification::getInstance("MOD:00397"), 0);
  pappso::pappso_double mass_before = peptideb.getMass();

  PeptideSp peptideSp = peptideb.makePeptideSp();
  PeptideNaturalIsotopeList isotopeListb(peptideSp);


  it = isotopeListb.begin();

  while(it != isotopeListb.end())
    {
      if(it->get()->getIsotopeNumber() == 0)
        {
          if(it->get()->getMass() != mass_before)
            {
              cerr << "it->get()->getMass() != mass_before FAILED" << std::endl;
              return 1;
            }
        }
      if(it->get()->size() != peptideb.size())
        return 1;
      // C55 H98 N15 O18 + C2 H3 N1 O1
      if(it->get()->getNumberOfAtom(AtomIsotopeSurvey::C) != 57)
        {
          cerr << "it->getNumberOfAtom(AtomIsotopeSurvey::C) != 57 FAILED"
               << std::endl;
          return 1;
        }
      if(it->get()->getNumberOfAtom(AtomIsotopeSurvey::H) != 100)
        {
          cerr << "it->getNumberOfAtom(AtomIsotopeSurvey::H) != 100 FAILED"
               << std::endl;
          return 1;
        }
      if(it->get()->getNumberOfAtom(AtomIsotopeSurvey::N) != 16)
        {
          cerr << "it->getNumberOfAtom(AtomIsotopeSurvey::N) != 16 FAILED"
               << std::endl;
          return 1;
        }
      if(it->get()->getNumberOfAtom(AtomIsotopeSurvey::O) != 19)
        {
          cerr << "it->getNumberOfAtom(AtomIsotopeSurvey::O) != 19 FAILED"
               << std::endl;
          return 1;
        }
      // qDebug() <<  it->getIntensityRatio();
      cout << std::endl
           << it->get()->getSequence().toStdString()
           << "..:: " << it->get()->getFormula(1).toStdString()
           << " C13=" << it->get()->getNumberOfIsotope(Isotope::C13)
           << " mass=" << it->get()->getMz(1)
           << " mz(2)=" << it->get()->getMz(2)
           << " ratio=" << it->get()->getIntensityRatio(1) << " ::.." << std::endl;
      it++;
    }

  std::map<unsigned int, pappso_double> map_isotope_number =
    isotopeListb.getIntensityRatioPerIsotopeNumber();

  cout << "isotope levels" << std::endl;
  for(unsigned int i = 0; i < map_isotope_number.size(); i++)
    {
      cout << "isotope " << i << " " << map_isotope_number[i] << std::endl;
    }

  cout << std::endl
       << "..:: peptide natural isotope list init test on fragment ::.."
       << std::endl;

  list<PeptideIon> cid_ion = PeptideFragmentIonListBase::getCIDionList();
  PeptideFragmentIonListBase fragmentation_cid(peptideSp, cid_ion);
  PeptideFragmentIonSp pepfrag_sp =
    fragmentation_cid.getPeptideFragmentIonSp(PeptideIon::y, 3);
  PeptideNaturalIsotopeList isotopeListFrag(pepfrag_sp);
  map_isotope_number = isotopeListFrag.getIntensityRatioPerIsotopeNumber();

  cout << "isotope levels" << std::endl;
  for(unsigned int i = 0; i < map_isotope_number.size(); i++)
    {
      cout << "frag isotope " << i << " " << map_isotope_number[i] << std::endl;
    }

  std::vector<PeptideNaturalIsotopeAverageSp> naturalIsotopeAverageList =
    isotopeListFrag.getByIntensityRatio(
      1, PrecisionFactory::getPpmInstance(2), 0.99);

  for(PeptideNaturalIsotopeAverageSp isotopeAverageSp :
      naturalIsotopeAverageList)
    {
      cout << "average isotope " << isotopeAverageSp.get()->getIntensityRatio()
           << " number=" << isotopeAverageSp.get()->getIsotopeNumber()
           << " rank=" << isotopeAverageSp.get()->getIsotopeRank() << std::endl;
    }
  // SUCCESS


  cout << "test with a big peptide at 10ppm" << std::endl;
  PeptideSp peptide_from_str = PeptideStrParser::parseString(
    "M(internal:Nter_hydrolytic_cleavage_H,0.00163028)"
    "GGTTQYTVNNQMVNATLMNIADNPTNVQLPGMYNK(internal:Cter_hydrolytic_cleavage_"
    "HO)");
  PeptideNaturalIsotopeList isotopeListBig(peptide_from_str);
  std::vector<pappso::PeptideNaturalIsotopeAverageSp>
    natural_isotope_average_list = isotopeListBig.getByIntensityRatio(
      3, PrecisionFactory::getPpmInstance(10), 0.6);
  for(PeptideNaturalIsotopeAverageSp isotopeAverageSp :
      natural_isotope_average_list)
    {
      cout << "average isotope " << isotopeAverageSp.get()->getIntensityRatio()
           << " number=" << isotopeAverageSp.get()->getIsotopeNumber()
           << " rank=" << isotopeAverageSp.get()->getIsotopeRank() << std::endl;
    }


  cout << "test with a big peptide at 5ppm" << std::endl;
  for(PeptideNaturalIsotopeAverageSp isotopeAverageSp :
      isotopeListBig.getByIntensityRatio(
        3, PrecisionFactory::getPpmInstance(5), 0.6))
    {
      cout << "average isotope " << isotopeAverageSp.get()->getIntensityRatio()
           << " number=" << isotopeAverageSp.get()->getIsotopeNumber()
           << " rank=" << isotopeAverageSp.get()->getIsotopeRank() << std::endl;
    }


  cout << "test with a big peptide at 3ppm" << std::endl;
  for(PeptideNaturalIsotopeAverageSp isotopeAverageSp :
      isotopeListBig.getByIntensityRatio(
        3, PrecisionFactory::getPpmInstance(3), 0.6))
    {
      cout << "average isotope " << isotopeAverageSp.get()->getIntensityRatio()
           << " number=" << isotopeAverageSp.get()->getIsotopeNumber()
           << " rank=" << isotopeAverageSp.get()->getIsotopeRank() << std::endl;
    }


  cout << "test with a big peptide at 2ppm" << std::endl;
  for(PeptideNaturalIsotopeAverageSp isotopeAverageSp :
      isotopeListBig.getByIntensityRatio(
        3, PrecisionFactory::getPpmInstance(2), 0.6))
    {
      cout << "average isotope " << isotopeAverageSp.get()->getIntensityRatio()
           << " number=" << isotopeAverageSp.get()->getIsotopeNumber()
           << " rank=" << isotopeAverageSp.get()->getIsotopeRank() << std::endl;
    }


  cout << "test with a big peptide at 1ppm" << std::endl;
  for(PeptideNaturalIsotopeAverageSp isotopeAverageSp :
      isotopeListBig.getByIntensityRatio(
        3, PrecisionFactory::getPpmInstance(1), 0.6))
    {
      cout << "average isotope " << isotopeAverageSp.get()->getIntensityRatio()
           << " number=" << isotopeAverageSp.get()->getIsotopeNumber()
           << " rank=" << isotopeAverageSp.get()->getIsotopeRank() << std::endl;
    }


  cout << std::endl
       << "..:: peptide natural isotope list from labeled peptide ::.." << std::endl;
  PeptideSp peptide_lys_label =
    PeptideStrParser::parseString("CCAAL(MOD:00582)DDKEACFAVEGPK");

  PeptideNaturalIsotopeList isotopeList_lys(peptide_lys_label);
  cout << std::endl << "isotope list OK" << isotopeList_lys.size() << std::endl;

  map_isotope_number = isotopeList_lys.getIntensityRatioPerIsotopeNumber();

  cout << "isotope levels" << std::endl;
  for(unsigned int i = 0; i < map_isotope_number.size(); i++)
    {
      cout << "frag isotope " << i << " " << map_isotope_number[i] << std::endl;
    }

  cout << std::endl
       << "..:: get 80 % intensity of natural isotope average PPM = 2 ::.."
       << std::endl;
  naturalIsotopeAverageList = isotopeList_lys.getByIntensityRatio(
    1, PrecisionFactory::getPpmInstance(2), 0.8);

  for(PeptideNaturalIsotopeAverageSp isotopeAverageSp :
      naturalIsotopeAverageList)
    {
      cout << "average isotope " << isotopeAverageSp.get()->getIntensityRatio()
           << " number=" << isotopeAverageSp.get()->getIsotopeNumber()
           << " rank=" << isotopeAverageSp.get()->getIsotopeRank() << std::endl;
    }

  cout << std::endl << "print lys isotope list OK" << std::endl;

  cout << std::endl
       << "..:: get 10 % intensity of small peptide natural isotope average "
          "dalton = 0.2 ::.."
       << std::endl;
  naturalIsotopeAverageList = isotopeList_lys.getByIntensityRatio(
    1, PrecisionFactory::getDaltonInstance(0.2), 0.1);

  for(PeptideNaturalIsotopeAverageSp isotopeAverageSp :
      naturalIsotopeAverageList)
    {
      cout << "average isotope " << isotopeAverageSp.get()->getIntensityRatio()
           << " number=" << isotopeAverageSp.get()->getIsotopeNumber()
           << " rank=" << isotopeAverageSp.get()->getIsotopeRank() << std::endl;
    }
  if(naturalIsotopeAverageList.size() != 1)
    {
      cerr << "naturalIsotopeAverageList.size() "
           << naturalIsotopeAverageList.size() << " != 1 ERROR" << std::endl;
      return 1;
    }
  if(naturalIsotopeAverageList.at(0).get()->getIsotopeNumber() != 0)
    {
      cerr
        << "naturalIsotopeAverageList.at(0).get()->getIsotopeNumber() !=0 ERROR"
        << std::endl;
      return 1;
    }

  cout << std::endl
       << "..:: get 10 % intensity of big peptide natural isotope average "
          "dalton = 0.2 ::.."
       << std::endl;
  naturalIsotopeAverageList = isotopeListBig.getByIntensityRatio(
    1, PrecisionFactory::getDaltonInstance(0.2), 0.1);

  for(PeptideNaturalIsotopeAverageSp isotopeAverageSp :
      naturalIsotopeAverageList)
    {
      cout << "average isotope " << isotopeAverageSp.get()->getIntensityRatio()
           << " number=" << isotopeAverageSp.get()->getIsotopeNumber()
           << " rank=" << isotopeAverageSp.get()->getIsotopeRank() << std::endl;
    }
  if(naturalIsotopeAverageList.size() != 1)
    {
      cerr << "naturalIsotopeAverageList.size() != 1 ERROR" << std::endl;
      return 1;
    }
  if(naturalIsotopeAverageList.at(0).get()->getIsotopeNumber() != 2)
    {
      cerr
        << "naturalIsotopeAverageList.at(0).get()->getIsotopeNumber() !=2 ERROR"
        << std::endl;
      return 1;
    }


  cout << std::endl << "..:: peptide rank test ::.." << std::endl;

  PeptideSp peptide_ratio_test = PeptideStrParser::parseString("DPTLAVVAYR");
  PeptideNaturalIsotopeList isotopeListRatioTest(peptide_ratio_test, 0.001);
  std::vector<pappso::PeptideNaturalIsotopeAverageSp>
    natural_isotope_average_list_ratio_test =
      isotopeListRatioTest.getByIntensityRatio(
        4, PrecisionFactory::getPpmInstance(10), 0.999);
  for(PeptideNaturalIsotopeAverageSp isotopeAverageSp :
      natural_isotope_average_list_ratio_test)
    {
      cout << "average isotope " << isotopeAverageSp.get()->getIntensityRatio()
           << " average mz=" << isotopeAverageSp.get()->getMz()
           << " number=" << isotopeAverageSp.get()->getIsotopeNumber()
           << " rank=" << isotopeAverageSp.get()->getIsotopeRank() << std::endl;
      /*
            if(isotopeAverageSp.get()->getIsotopeRank() == 3)
              {
                cerr << "isotopeAverageSp.get()->getIsotopeRank()== 3 ERROR, not
         " "possible with 10ppm"
                     << std::endl;
                return 1;
              }
              */
    }

  return 0;
}
