//
// File: test_peptide.cpp
// Created by: Olivier Langella
// Created on: 7/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 6,6"

#include <pappsomspp/mzrange.h>
#include <pappsomspp/amino_acid/aa.h>
#include <pappsomspp/peptide/peptide.h>
#include <pappsomspp/peptide/peptidestrparser.h>
#include <iostream>
#include <QDebug>
#include <QString>

using namespace pappso;
using namespace std;

int
main()
{

  cout << std::endl << "..:: peptide init ::.." << std::endl;
  Peptide peptide("LA");
  cout << std::endl << "..:: peptide LI ::.." << std::endl;
  cout << peptide.getSequence().toStdString() << " "
       << peptide.getSequenceLi().toStdString() << std::endl;
  MzRange mz_range(peptide.getMass(), PrecisionFactory::getPpmInstance(10));
  if(!mz_range.contains(Aa('L').getMass() + Aa('A').getMass() + MASSH2O))
    {
      cerr << "!mz_range.contains(Aa('L').getMass()+Aa('A').getMass()"
           << std::endl;
      return 1;
    }
  // 202.13179
  // http://db.systemsbiology.net:8080/proteomicsToolkit/FragIonServlet?sequence=LA&massType=monoRB&charge=1&bCB=1&yCB=1&nterm=0.0&cterm=0.0&addModifType=&addModifVal=
  MzRange mz_range_very_precise(peptide.getMass(),
                                PrecisionFactory::getPpmInstance(0.5));
  if(!mz_range_very_precise.contains(202.13179))
    {
      cerr << QString::number(peptide.getMass(), 'g', 10).toStdString()
           << " LA mass != 202.13179" << std::endl;
      return 1;
    }

  Peptide peptide2("CCAADDKEACFAVEGPK");
  // 1756.73395
  MzRange mz_range_very_preciseb(peptide2.getMz(1),
                                 PrecisionFactory::getPpmInstance(0.5));
  if(!mz_range_very_preciseb.contains(1756.73395))
    {
      cerr << QString::number(peptide2.getMz(1), 'g', 10).toStdString()
           << " CCAADDKEACFAVEGPK mass != 1756.73395" << std::endl;
      return 1;
    }
  /*
  <psimod position="1"  accession="MOD:00397"/>
    <psimod position="2"  accession="MOD:00397"/>
    <psimod position="10"  accession="MOD:00397"/>
    <psimod position="1"  accession="MOD:01160"/>
    */

  pappso::AaModificationP aaModcarba = AaModification::getInstance("MOD:00397");
  /*
  pappso::AaModificationP aaModcarbab =
    AaModification::getInstance("MOD:00397");
  AaModificationP met_oxy = AaModification::getInstance("MOD:00719");*/
  peptide2.addAaModification(aaModcarba, 0);
  peptide2.addAaModification(aaModcarba, 1);
  peptide2.addAaModification(aaModcarba, 9);
  peptide2.addAaModification(AaModification::getInstance("MOD:01160"), 0);

  cerr << peptide2.getFormula(1).toStdString().c_str() << std::endl;

  MzRange mz_range2(peptide2.getMz(1), PrecisionFactory::getPpmInstance(10));
  if(!mz_range2.contains(1910.7722))
    {
      cerr << peptide2.getMz(1) << "!="
           << "1910.7722" << std::endl;
      return 1;
    }


  PeptideSp peptide_from_str = PeptideStrParser::parseString(
    "C(MOD:00397+MOD:01160)C(MOD:00397)AADDKEAC(MOD:00397)FAVEGPK");
  if(peptide_from_str.get()->getMass() != peptide2.getMass())
    {
      cerr << "peptide_from_str.get()->getMass() != peptide2.getMass()"
           << peptide_from_str.get()->getMass() << "!=" << peptide2.getMass()
           << std::endl;
      return 1;
    }
  PeptideSp peptide_from_str2 = PeptideStrParser::parseString(
    "C(Carbamidomethyl+MOD:01160)C(MOD:00397)AADDKEAC(57.021464)FAVEGPK");
  PeptideSp peptide_from_str3 = PeptideStrParser::parseString(
    "C(Carbamidomethyl+MOD:01160)C(397)AADDKEAC(57.021464)FAVEGPK");

  if(peptide_from_str2.get()->getMass() != peptide_from_str3.get()->getMass())
    {
      cerr << "peptide_from_str2.get()->getMass() != "
              "peptide_from_str3.get()->getMass()"
           << peptide_from_str2.get()->getMass()
           << "!=" << peptide_from_str3.get()->getMass() << std::endl;
      return 1;
    }
  // SUCCESS
  Peptide copy_str2(*peptide_from_str2.get());
  copy_str2.rotate();
  cerr << copy_str2.toAbsoluteString().toStdString() << std::endl;
  if(peptide_from_str2.get()->getMass() != copy_str2.getMass())
    {
      cerr << "peptide_from_str2.get()->getMass() != copy_str2.getMass()"
           << peptide_from_str2.get()->getMass() << "!=" << copy_str2.getMass()
           << std::endl;
      return 1;
    }


  // testing isotope labels
  //[Term]
  // id: MOD:00582
  // name: 6x(13)C,2x(15)N labeled L-lysine
  cout << std::endl << "..:: Test peptide isotope labels::.." << std::endl;
  PeptideSp peptide_normal =
    PeptideStrParser::parseString("CCAALDDKEACFAVEGPK");
  PeptideSp peptide_lys_label =
    PeptideStrParser::parseString("CCAAL(MOD:00582)DDKEACFAVEGPK");
  if(peptide_normal.get()->getNumberOfAtom(AtomIsotopeSurvey::C) !=
     peptide_lys_label.get()->getNumberOfAtom(AtomIsotopeSurvey::C))
    {
      cerr << "peptide_normal.get()->getNumberOfAtom(AtomIsotopeSurvey::C) "
           << peptide_normal.get()->getNumberOfAtom(AtomIsotopeSurvey::C)
           << "!= "
           << peptide_lys_label.get()->getNumberOfAtom(AtomIsotopeSurvey::C)
           << " peptide_lys_label.get()->getNumberOfAtom(AtomIsotopeSurvey::C)"
           << std::endl;
      return 1;
    }
  if(peptide_normal.get()->getNumberOfIsotope(Isotope::C13) != 0)
    {
      cerr << "peptide_normal.get()->getNumberOfIsotope(Isotope::C13) != 0 "
           << std::endl;
      return 1;
    }
  if(peptide_lys_label.get()->getNumberOfIsotope(Isotope::C13) != 6)
    {
      cerr << "peptide_lys_label.get()->getNumberOfIsotope(Isotope::C13) != 6 "
           << std::endl;
      return 1;
    }
  // xref: DiffMono: "8.014199"
  MzRange mz_range_lys(8.014199, PrecisionFactory::getPpmInstance(10));
  if(!mz_range_lys.contains(peptide_lys_label.get()->getMz(1) -
                            peptide_normal.get()->getMz(1)))
    {
      cerr << "mz_range_lys -  peptide_normal != 8.014199" << std::endl;
      return 1;
    }

  if(*peptide_normal.get() == *peptide_lys_label.get())
    {
      cerr << "(*peptide_normal.get() == *peptide_lys_label.get()) ERROR"
           << std::endl;
      return 1;
    }
  if(!(*peptide_normal.get() < *peptide_lys_label.get()))
    {
      cerr << "!(*peptide_normal.get() < *peptide_lys_label.get()) ERROR"
           << std::endl;
      return 1;
    }

  PeptideSp peptide_lys_label_bis =
    PeptideStrParser::parseString("CCAAL(MOD:00582)DDKEACFAVEGPK");

  if(!(*peptide_lys_label_bis.get() == *peptide_lys_label.get()))
    {
      cerr
        << "!(*peptide_lys_label_bis.get() == *peptide_lys_label.get()) ERROR"
        << std::endl;
      return 1;
    }


  cout << std::endl << "..:: peptide palindrome ::.." << std::endl;
  Peptide peptide_pal_a("ALA");

  if(!peptide_pal_a.isPalindrome())
    {
      cerr << "!peptide_pal_a.isPalindrome() ERROR" << std::endl;
      return 1;
    }

  if(peptide_normal.get()->isPalindrome())
    {
      cerr << "peptide_normal.isPalindrome() ERROR "
           << peptide_normal.get()->getSequence().toStdString() << " "
           << peptide_normal.get()->isPalindrome() << std::endl;
      return 1;
    }


  cout << std::endl << "..:: peptide dimethyl ::.." << std::endl;
  //"Q(internal:Nter_hydrolytic_cleavage_H,MOD:00429)SLPSLSS(MOD:00696)FLNR(internal:Cter_hydrolytic_cleavage_HO)"
  Peptide peptide_dimethyl("QSLPSLSSFLNR");
  pappso::AaModificationP aaModDimethyl =
    AaModification::getInstance("MOD:00429");
  pappso::AaModificationP aaModDimethyl2 =
    AaModification::getInstance("MOD:00696");
  peptide_dimethyl.addAaModification(aaModDimethyl, 0);
  peptide_dimethyl.addAaModification(aaModDimethyl2, 7);
  cout << "Before " << peptide_dimethyl.toAbsoluteString().toStdString();
  cout << std::endl << "remove AaModif" << std::endl;
  peptide_dimethyl.removeAaModification(aaModDimethyl);
  if(peptide_dimethyl.toAbsoluteString() !=
     "Q(internal:Nter_hydrolytic_cleavage_H)SLPSLSS(MOD:00696)FLNR(internal:"
     "Cter_hydrolytic_cleavage_HO)")
    {
      cerr << "peptide_dimethyl.removeAaModification(aaModDimethyl) ERROR "
           << peptide_dimethyl.toAbsoluteString().toStdString() << " "
           << aaModDimethyl->getName().toStdString();
      return 1;
    }
  cout << "Finish " << peptide_dimethyl.toAbsoluteString().toStdString();

  return 0;
}
