/**
 * \file input/xtpxpipsaxhandler.cpp
 * \date 17/11/2017
 * \author Olivier Langella
 * \brief parse new xpip files from xtpcpp
 */


/*******************************************************************************
 * Copyright (c) 2017 Olivier Langella <Olivier.Langella@u-psud.fr>.
 *
 * This file is part of XTPcpp.
 *
 *     XTPcpp 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.
 *
 *     XTPcpp 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 XTPcpp.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Contributors:
 *     Olivier Langella <Olivier.Langella@u-psud.fr> - initial API and
 *implementation
 ******************************************************************************/

#include "xtpxpipsaxhandler.h"

#include <pappsomspp/exception/exceptionnotfound.h>
#include <cmath>
#include "../core/peptideevidence.h"
#include "../utils/peptidestore.h"
#include "../utils/proteinstore.h"

XtpXpipSaxHandler::XtpXpipSaxHandler(WorkMonitorInterface *p_monitor,
                                     Project *p_project)
  : _p_project(p_project)
{
  qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  _p_monitor = p_monitor;
  qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
}

XtpXpipSaxHandler::~XtpXpipSaxHandler()
{
}


bool
XtpXpipSaxHandler::isXtpXpip() const
{
  return _is_xtpcpp_xpip;
}
bool
XtpXpipSaxHandler::startElement(const QString &namespaceURI [[maybe_unused]],
                                const QString &localName [[maybe_unused]],
                                const QString &qName,
                                const QXmlAttributes &attributes)
{
  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__ << " " <<
  // namespaceURI << " "
  //       << localName << " " << qName;
  _tag_stack.push_back(qName);
  bool is_ok = true;

  try
    {
      // startElement_group
      if(_tag_stack.size() == 1)
        {
          _is_xtpcpp_xpip = true;
          if(qName != "xpip")
            {
              _is_xtpcpp_xpip = false;
              throw pappso::ExceptionNotFound(
                QObject::tr("ERROR this file is not an xpip file %1")
                  .arg(qName));
            }
        }
      else if(qName == "protein_match")
        {
          if(_count_total % 100 == 0)
            {
              _p_monitor->message(QString("reading protein matches %1 on %2")
                                    .arg(_count_protein_matches)
                                    .arg(_total_protein_matches),
                                  _count_total);
            }
          is_ok = startElement_protein_match(attributes);
        }
      else if(qName == "peptide_match")
        {
          is_ok = startElement_peptide_match(attributes);
        }
      else if(qName == "protein")
        {
          if(_count_total % 100 == 0)
            {
              _p_monitor->message(QString("reading proteins %1 on %2")
                                    .arg(_count_proteins)
                                    .arg(_total_proteins),
                                  _count_total);
            }
          is_ok = startElement_protein(attributes);
        }
      else if(qName == "identification_source")
        {
          is_ok = startElement_identification_source(attributes);
        }
      else if(qName == "param")
        {
          is_ok = startElement_param(attributes);
        }
      else if(qName == "stat")
        {
          is_ok = startElement_stat(attributes);
        }
      else if(qName == "identification_group")
        {
          is_ok = startElement_identification_group(attributes);
        }
      else if(qName == "peptide_evidence_list")
        {
          is_ok = startElement_peptide_evidence_list(attributes);
        }
      else if(qName == "counts")
        {
          is_ok = startElement_counts(attributes);
        }
      else if(qName == "label_method")
        {
          is_ok = startElement_label_method(attributes);
        }
      //<sample value="P6_08_10"/>
      else if(qName == "msrun")
        {
          is_ok = startElement_msrun(attributes);
        }
      else if(qName == "msrun_group")
        {
          is_ok = startElement_alignmentGroup(attributes);
        }
      else if(qName == "grouped_msrun")
        {
          is_ok = startElement_msrunInAlignmentGroup(attributes);
        }
      else if(qName == "peptide")
        {
          if(_count_total % 100 == 0)
            {
              _p_monitor->message(QObject::tr("reading peptide %1 on %2")
                                    .arg(_count_peptides)
                                    .arg(_total_peptides),
                                  _count_total);
            }
          is_ok = startElement_peptide(attributes);
        }
      else if(qName == "peptide_evidence")
        {
          if(_count_total % 100 == 0)
            {
              _p_monitor->message(
                QObject::tr("reading peptide evidence %1 on %2")
                  .arg(_count_peptide_evidences)
                  .arg(_total_peptide_evidences),
                _count_total);
            }
          is_ok = startElement_peptide_evidence(attributes);
        }
      else if(qName == "modification")
        {
          is_ok = startElement_modification(attributes);
        }
      else if(qName == "mod")
        {
          is_ok = startElement_mod(attributes);
        }
      else if(qName == "filter_params")
        {
          is_ok = startElement_filter_params(attributes);
        }
      else if(qName == "description")
        {
          is_ok = startElement_description(attributes);
        }
      else if(qName == "fasta_file")
        {
          is_ok = startElement_fasta_file(attributes);
        }
      else if(qName == "contaminants")
        {
          is_ok = startElement_contaminants(attributes);
        }
      else if(qName == "decoys")
        {
          is_ok = startElement_decoys(attributes);
        }

      _current_text.clear();
    }
  catch(pappso::PappsoException &exception_pappso)
    {
      _errorStr = QObject::tr(
                    "ERROR in XtpXpipSaxHandler::startElement tag "
                    "%1, PAPPSO exception:\n%2")
                    .arg(qName)
                    .arg(exception_pappso.qwhat());
      return false;
    }
  catch(std::exception &exception_std)
    {
      _errorStr =
        QObject::tr(
          "ERROR in XtpXpipSaxHandler::startElement tag %1, std exception:\n%2")
          .arg(qName)
          .arg(exception_std.what());
      return false;
    }
  return is_ok;
}

bool
XtpXpipSaxHandler::endElement(const QString &namespaceURI [[maybe_unused]],
                              const QString &localName [[maybe_unused]],
                              const QString &qName)
{

  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__ << " " <<
  // namespaceURI << " "
  //        << localName << " " << qName;
  bool is_ok = true;
  // endElement_peptide_list
  try
    {
      if(qName == "protein")
        {
          is_ok = endElement_protein();
        }
      else if(qName == "peptide")
        {
          is_ok = endElement_peptide();
        }
      else if(qName == "msrun")
        {
          is_ok = endElement_msrun();
        }
      else if(qName == "msrun_group")
        {
          is_ok = endElement_alignmentGroup();
        }
      else if(qName == "sequence")
        {
          is_ok = endElement_sequence();
        }
      else if(qName == "protein_match")
        {
          is_ok = endElement_protein_match();
        }
      else if(qName == "peptide_evidence")
        {
          is_ok = endElement_peptide_evidence();
        }
      else if(qName == "peptide_evidence_list")
        {
          is_ok = endElement_peptide_evidence_list();
        }
      else if(qName == "identification_group")
        {
          is_ok = endElement_identification_group();
        }
      else if(qName == "identification_source")
        {
          is_ok = endElement_identification_source();
        }

      // end of detection_moulon
      // else if ((_tag_stack.size() > 1) &&
      //         (_tag_stack[_tag_stack.size() - 2] == "detection_moulon"))
    }
  catch(pappso::PappsoException &exception_pappso)
    {
      _errorStr = QObject::tr(
                    "ERROR in XtpXpipSaxHandler::endElement tag %1, "
                    "PAPPSO exception:\n%2")
                    .arg(qName)
                    .arg(exception_pappso.qwhat());
      return false;
    }
  catch(std::exception &exception_std)
    {
      _errorStr =
        QObject::tr(
          "ERROR in XtpXpipSaxHandler::endElement tag %1, std exception:\n%2")
          .arg(qName)
          .arg(exception_std.what());
      return false;
    }

  _current_text.clear();
  _tag_stack.pop_back();

  return is_ok;
}

bool
XtpXpipSaxHandler::startElement_contaminants(QXmlAttributes attributes)
{
  //    <contaminants regexp="^contatruc\|" fasta_id=""/>

  qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  if(!attributes.value("mode").isEmpty())
    {
      _p_project->setContaminantRemovalMode(
        (ContaminantRemovalMode)attributes.value("mode").toUInt());
      qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__ << " "
               << (std::uint8_t)_p_project->getContaminantRemovalMode();
    }

  QString regexp(attributes.value("regexp"));
  QString fasta_id_list(attributes.value("fasta_id"));
  if(!regexp.isEmpty())
    {
      _p_project->getProteinStore().setRegexpContaminantPattern(regexp);
    }
  if(!fasta_id_list.isEmpty())
    {
      for(QString fasta_id : fasta_id_list.split(" "))
        {
          _p_project->getProteinStore().addContaminantFastaFile(
            _map_fasta_files.at(fasta_id).get());
        }
    }
  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  return true;
}

bool
XtpXpipSaxHandler::startElement_decoys(QXmlAttributes attributes)
{
  //    <decoys regexp=".*reversedi" fasta_id=""/>
  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  QString regexp(attributes.value("regexp"));
  QString fasta_id_list(attributes.value("fasta_id"));
  if(!regexp.isEmpty())
    {
      _p_project->getProteinStore().setRegexpDecoyPattern(regexp);
    }
  if(!fasta_id_list.isEmpty())
    {
      for(QString fasta_id : fasta_id_list.split(" "))
        {
          _p_project->getProteinStore().addDecoyFastaFile(
            _map_fasta_files.at(fasta_id).get());
        }
    }
  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  return true;
}

bool
XtpXpipSaxHandler::startElement_label_method(QXmlAttributes attributes)
{
  //    <label_method id="dimethyl">
  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  LabelingMethod method(attributes.value("id").simplified());
  _sp_labeling_method = method.makeLabelingMethodSp();
  _p_project->setLabelingMethodSp(_sp_labeling_method);
  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  return true;
}

bool
XtpXpipSaxHandler::startElement_counts(QXmlAttributes attributes)
{
  //    <counts proteins="6019" peptides="6194" peptide_evidences="7123"
  //    protein_matches="6019"/>
  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  _total_proteins = (std::size_t)attributes.value("proteins").toLong();
  _total_peptides = (std::size_t)attributes.value("peptides").toLong();
  _total_peptide_evidences =
    (std::size_t)attributes.value("peptide_evidences").toLong();
  _total_protein_matches =
    (std::size_t)attributes.value("protein_matches").toLong();
  _count_proteins          = 0;
  _count_peptides          = 0;
  _count_peptide_evidences = 0;
  _count_protein_matches   = 0;

  _total = _total_proteins + _total_peptides + _total_peptide_evidences +
           _total_protein_matches;

  _p_monitor->setProgressMaximumValue((std::size_t)_total);
  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  return true;
}

bool
XtpXpipSaxHandler::startElement_filter_params(QXmlAttributes attributes)
{

  //    <filter_params pep_evalue="0.01" prot_evalue="0.01" pep_number="1"
  //    cross_sample="false"/>
  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  _automatic_filter_parameters.setFilterPeptideEvalue(
    attributes.value("pep_evalue").simplified().toDouble());
  _automatic_filter_parameters.setFilterProteinEvalue(
    attributes.value("prot_evalue").simplified().toDouble());
  _automatic_filter_parameters.setFilterMinimumPeptidePerMatch(
    attributes.value("pep_number").simplified().toUInt());
  _automatic_filter_parameters.setFilterCrossSamplePeptideNumber(false);
  if(attributes.value("cross_sample").simplified() == "true")
    {
      _automatic_filter_parameters.setFilterCrossSamplePeptideNumber(true);
    }

  _automatic_filter_parameters.setFilterPeptideObservedInLessSamplesThan(
    attributes.value("peprepro").simplified().toUInt());
  //_p_project->getFastaFileStore().getInstance(FastaFile(attributes.value("database_filter")));
  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  return true;
}

bool
XtpXpipSaxHandler::startElement_description(QXmlAttributes attributes)
{

  //    <description version="0.1.23" grouping="peptidemass" combine="true"
  //    date="2017-11-17T16:02:47"/>

  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  _p_project->setProjectMode(ProjectMode::individual);
  if(attributes.value("combine") == "true")
    {
      _p_project->setProjectMode(ProjectMode::combined);
    }

  if(attributes.value("ptm").isEmpty())
    {
      _p_project->setPtmMode(PtmMode::none);
    }
  else
    {
      _p_project->setPtmMode(
        static_cast<PtmMode>(attributes.value("ptm").toInt()));
    }

  if(attributes.value("mode").isEmpty())
    {
    }
  else
    {
      _p_project->setProjectMode(
        static_cast<ProjectMode>(attributes.value("mode").toInt()));
    }
  //_total_protein_match = attributes.value("match_number").toUInt();
  //_total_protein_match = attributes.value("match_number").toUInt();

  //_p_monitor->setProgressMaximumValue(_total_protein_match);
  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  return true;
}

bool
XtpXpipSaxHandler::startElement_stat(QXmlAttributes attributes)
{

  /*
  <stat key="0" value="48.5"/>
  */
  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;

  if(_sp_msrun.get() != nullptr)
    {
      MsRunStatistics type =
        static_cast<MsRunStatistics>(attributes.value("key").toUInt());
      _sp_msrun.get()->setMsRunStatistics(type, attributes.value("value"));
    }
  else if(_sp_current_identification_source.get() != nullptr)
    {
      IdentificationEngineStatistics type =
        static_cast<IdentificationEngineStatistics>(
          attributes.value("key").toUInt());
      _sp_current_identification_source.get()
        ->setIdentificationEngineStatistics(type, attributes.value("value"));
    }
  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  return true;
}

bool
XtpXpipSaxHandler::startElement_param(QXmlAttributes attributes)
{

  /*
  <param key="0" value="48.5"/>
  */
  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;

  if(_sp_current_peptide_evidence.get() != nullptr)
    {
      PeptideEvidenceParam type =
        static_cast<PeptideEvidenceParam>(attributes.value("key").toUInt());
      _sp_current_peptide_evidence.get()->setParam(
        type, QVariant(attributes.value("value")));
    }
  else if(_sp_current_identification_source.get() != nullptr)
    {
      IdentificationEngineParam type = static_cast<IdentificationEngineParam>(
        attributes.value("key").toUInt());
      _sp_current_identification_source.get()->setIdentificationEngineParam(
        type, attributes.value("value"));
    }

  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  return true;
}

bool
XtpXpipSaxHandler::startElement_modification(QXmlAttributes attributes)
{

  /*
  <modification id="moda1" mod="MOD:00719"/>
  */
  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;

  pappso::AaModificationP mod =
    pappso::AaModification::getInstance(attributes.value("mod").simplified());
  _map_modifs.insert(std::pair<QString, pappso::AaModificationP>(
    attributes.value("id").simplified(), mod));

  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  return true;
}

bool
XtpXpipSaxHandler::startElement_identification_group(QXmlAttributes attributes
                                                     [[maybe_unused]])
{

  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  _current_identification_group_p = _p_project->newIdentificationGroup();

  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  return true;
}

bool
XtpXpipSaxHandler::startElement_identification_source(QXmlAttributes attributes)
{
  //<identification_source id="identa0" msrun_id="sampa0"
  // path="/espace/bio/tandem/20120906_balliau_extract_1_A01_urnb-1.xml"
  // engine="1" version="2017.2.1.4" fasta_ids="fastaa0">

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

  IdentificationEngine engine =
    static_cast<IdentificationEngine>(attributes.value("engine").toUInt());
  _sp_current_identification_source =
    _p_project->getIdentificationDataSourceStore().getInstance(
      attributes.value("path").simplified(), engine);
  _sp_current_identification_source.get()->setXmlId(
    attributes.value("id").simplified());
  _map_ident_sources.insert(std::pair<QString, IdentificationDataSourceSp>(
    _sp_current_identification_source.get()->getXmlId(),
    _sp_current_identification_source));

  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  _sp_current_identification_source->setMsRunSp(
    _map_msruns.at(attributes.value("msrun_id").simplified()));
  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  _sp_current_identification_source->setIdentificationEngineVersion(
    attributes.value("version"));

  for(const QString &fasta_id : attributes.value("fasta_ids").split(" "))
    {
      _sp_current_identification_source.get()->addFastaFile(
        _map_fasta_files.at(fasta_id));
    }

  //_current_identification_group_p->addMsRunSp(ms_run);
  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  return true;
}
bool
XtpXpipSaxHandler::startElement_msrun(QXmlAttributes attributes)
{
  //<msrun id="sampa0" name="20120906_balliau_extract_1_A01_urnb-1" format="0"
  // path="20120906_balliau_extract_1_A01_urnb-1"/>

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

  _sp_msrun = _p_project->getMsRunStore().getInstance(
    attributes.value("path").simplified());
  _sp_msrun.get()->setFileName(attributes.value("path").simplified());
  _sp_msrun.get()->setSampleName(attributes.value("name").simplified());
  _sp_msrun.get()->setXmlId(attributes.value("id").simplified());
  _map_msruns.insert(
    std::pair<QString, MsRunSp>(_sp_msrun.get()->getXmlId(), _sp_msrun));
  //_current_identification_group_p->addMsRunSp(ms_run);
  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  return true;
}

bool
XtpXpipSaxHandler::startElement_alignmentGroup(QXmlAttributes attributes)
{
  msp_alignment_group = std::make_shared<MsRunAlignmentGroup>(
    _p_project, attributes.value("name").simplified());
  _p_project->addMsRunAlignmentGroupToList(msp_alignment_group);
  QString reference_id = attributes.value("reference").simplified();
  if(reference_id != "")
    {
      msp_alignment_group->setMsRunReference(_map_msruns.at(reference_id));
    }
  return true;
}

bool
XtpXpipSaxHandler::startElement_msrunInAlignmentGroup(QXmlAttributes attributes)
{
  MsRunSp ms_run = _map_msruns.at(attributes.value("id").simplified());
  msp_alignment_group->addMsRunToMsRunAlignmentGroupList(ms_run);
  ms_run->setAlignmentGroup(msp_alignment_group);
  return true;
}

bool
XtpXpipSaxHandler::startElement_peptide_evidence_list(QXmlAttributes attributes)
{
  //<peptide_evidence_list ident_source_id="identa0">

  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  _sp_current_identification_source =
    _map_ident_sources.at(attributes.value("ident_source_id").simplified());
  _current_identification_group_p->addIdentificationDataSourceP(
    _sp_current_identification_source.get());

  //_current_identification_group_p->addMsRunSp(ms_run);
  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  return true;
}
bool
XtpXpipSaxHandler::startElement_peptide_evidence(QXmlAttributes attributes)
{

  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  /*
   * <peptide_evidence id="peb76" source_id="identa0" peptide_id="pd7688"
   scan="11743" rt="2170" evalue="8.1e-10" exp_mass="1655.755648" charge="2"
   checked="true"> <param key="0" value="48.5"/>
              </peptide_evidence>

            */

  unsigned int scan   = attributes.value("scan").toUInt();
  _p_peptide_evidence = new PeptideEvidence(
    _sp_current_identification_source.get()->getMsRunSp().get(), scan);
  _p_peptide_evidence->setIdentificationDataSource(
    _sp_current_identification_source.get());

  _p_peptide_evidence->setChecked(false);
  if(attributes.value("checked").simplified().toLower() == "true")
    {
      _p_peptide_evidence->setChecked(true);
    }
  _p_peptide_evidence->setCharge(attributes.value("charge").toUInt());
  if(!attributes.value("eng").isEmpty())
    {
      _p_peptide_evidence->setIdentificationEngine(
        static_cast<IdentificationEngine>(attributes.value("eng").toUInt()));
    }
  _p_peptide_evidence->setRetentionTime(attributes.value("rt").toDouble());
  _p_peptide_evidence->setEvalue(attributes.value("evalue").toDouble());
  _p_peptide_evidence->setExperimentalMass(
    attributes.value("exp_mass").toDouble());
  _p_peptide_evidence->setPeptideXtpSp(
    _map_peptides.at(attributes.value("peptide_id").simplified()));

  _sp_current_peptide_evidence = _sp_current_identification_source.get()
                                   ->getPeptideEvidenceStore()
                                   .recordInstance(_p_peptide_evidence);
  _map_peptide_evidences.insert(std::pair<QString, PeptideEvidenceSp>(
    attributes.value("id").simplified(), _sp_current_peptide_evidence));
  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  return true;
}

bool
XtpXpipSaxHandler::startElement_peptide_match(QXmlAttributes attributes)
{

  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  /*
   *<peptide_match peptide_evidence_id="pea1" start="619"/>
   */
  PeptideMatch peptide_match;
  peptide_match.setPeptideEvidenceSp(_map_peptide_evidences.at(
    attributes.value("peptide_evidence_id").simplified()));
  peptide_match.setStart(attributes.value("start").toUInt());
  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  _p_protein_match->addPeptideMatch(peptide_match);
  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__    <<
  // _p_protein_match->getPeptideMatchList().size();
  return true;
}

bool
XtpXpipSaxHandler::startElement_protein_match(QXmlAttributes attributes)
{

  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  /*
   * <protein_match acc="GRMZM2G083841_P01" checked="true">
                  <peptide_match peptide_evidence_id="pea1" start="619"/>
                  <peptide_match peptide_evidence_id="pea2" start="12"/>

            */
  _p_protein_match = new ProteinMatch();


  _p_protein_match->setProteinXtpSp(
    _map_proteins.at(attributes.value("acc").simplified()));
  _p_protein_match->setChecked(false);
  if(attributes.value("checked").simplified().toLower() == "true")
    {
      _p_protein_match->setChecked(true);
    }
  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  return true;
}

bool
XtpXpipSaxHandler::startElement_fasta_file(QXmlAttributes attributes)
{
  //<fasta_file id="fastaa0" path="/espace/Genome_Z_mays_5a.fasta"/>
  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;

  FastaFileSp fasta_file_sp = _p_project->getFastaFileStore().getInstance(
    FastaFile(attributes.value("path")));
  fasta_file_sp.get()->setXmlId(attributes.value("id"));

  _map_fasta_files.insert(
    std::pair<QString, FastaFileSp>(attributes.value("id"), fasta_file_sp));
  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  return true;
}

bool
XtpXpipSaxHandler::startElement_protein(QXmlAttributes attributes)
{

  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  _count_proteins++;
  _count_total++;
  /*
   *  <protein fasta_id="fastaa0" acc="AC149475.2_FGP003"
   description="seq=translation; coord=9:152490486..152495067:-1;
   parent_transcript=AC149475.2_FGT003; parent_gene=AC149475.2_FG003"
   is_decoy="false" is_contaminant="false">
          <sequence>MFLTRTEYDRGVNTFSPEGRLFQVEYAIEAIKLGSTAIGLKTKDGVVLAVEKRVTSPLLEPSSVEKIMEIDEHIGCAMSGLIADARTLVEHARVETQNHRFSYGEPMTVESSTQAICDLALRFGEGDEESMSRPFGVSLLIAGHDENGPSLYYTDPSGTFWQCNAKAIGSGSEGADSSLQEQYNKELALEEAETIALSILKQVMEEKVTPNNVDIAKVAPKYHLYTPAEVEAVIARL</sequence>
      </protein>
            */
  _sp_current_protein = ProteinXtp().makeProteinXtpSp();

  auto fasta_it = _map_fasta_files.find(attributes.value("fasta_id"));
  if(fasta_it == _map_fasta_files.end())
    {
      throw pappso::ExceptionNotFound(QObject::tr("ERROR fasta_id %1 not found")
                                        .arg(attributes.value("fasta_id")));
    }
  // qDebug() << "startElement_protein fastaid=" <<
  // attributes.value("fasta_id");
  _sp_current_protein.get()->setFastaFileP(fasta_it->second.get());
  _sp_current_protein.get()->setAccession(attributes.value("acc"));

  // qDebug() << "startElement_protein acc=" << attributes.value("acc");
  // qDebug() << "startElement_protein description=" <<
  // attributes.value("description");
  _sp_current_protein.get()->setDescription(attributes.value("description"));
  _sp_current_protein.get()->setIsContaminant(false);
  if(attributes.value("is_contaminant").simplified().toLower() == "true")
    {
      _sp_current_protein.get()->setIsContaminant(true);
    }
  // qDebug() << "startElement_protein iscontaminant";
  _sp_current_protein.get()->setIsDecoy(false);
  if(attributes.value("is_decoy").simplified().toLower() == "true")
    {
      _sp_current_protein.get()->setIsDecoy(true);
    }
  // qDebug() << "startElement_protein isdecoy";

  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  return true;
}
bool
XtpXpipSaxHandler::startElement_peptide(QXmlAttributes attributes)
{

  //    <peptide id="pd1493" seq="FEGVPMAPPDPILGVSEAFK">
  //            <mod ref="moda1" position="6" aa="M"/>
  //        </peptide>
  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  _current_peptide_sp =
    PeptideXtp(attributes.value("seq").simplified()).makePeptideXtpSp();
  _current_id = attributes.value("id").simplified();
  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  return true;
}

bool
XtpXpipSaxHandler::startElement_mod(QXmlAttributes attributes)
{

  //<mod ref="moda1" position="6" aa="M"/>
  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  pappso::AaModificationP modif =
    _map_modifs[attributes.value("ref").simplified()];
  unsigned int position = attributes.value("position").simplified().toUInt();
  _current_peptide_sp.get()->addAaModification(modif, position);
  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  return true;
}
bool
XtpXpipSaxHandler::endElement_identification_group()
{
  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  _current_identification_group_p = nullptr;
  return true;
}
bool
XtpXpipSaxHandler::endElement_identification_source()
{
  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  _sp_current_identification_source = nullptr;
  return true;
}

bool
XtpXpipSaxHandler::endElement_peptide_evidence_list()
{
  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  _sp_current_identification_source.get()->getPeptideEvidenceStore().clearMap();
  _sp_current_identification_source = nullptr;
  return true;
}

bool
XtpXpipSaxHandler::endElement_peptide()
{
  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  _current_peptide_sp =
    _p_project->getPeptideStore().getInstance(_current_peptide_sp);
  _map_peptides.insert(
    std::pair<QString, PeptideXtpSp>(_current_id, _current_peptide_sp));

  if(_sp_labeling_method.get() != nullptr)
    {
      _current_peptide_sp.get()->applyLabelingMethod(_sp_labeling_method);
    }

  _current_peptide_sp = nullptr;

  _count_peptides++;
  _count_total++;
  return true;
}

bool
XtpXpipSaxHandler::endElement_peptide_evidence()
{
  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  _sp_current_peptide_evidence = nullptr;
  _count_peptide_evidences++;
  _count_total++;

  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  return true;
}

bool
XtpXpipSaxHandler::endElement_msrun()
{
  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  _sp_msrun = nullptr;
  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  return true;
}

bool
XtpXpipSaxHandler::endElement_alignmentGroup()
{
  msp_alignment_group = nullptr;
  return true;
}

bool
XtpXpipSaxHandler::endElement_sequence()
{
  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  // if ((_tag_stack.size() > 1) && (_tag_stack[_tag_stack.size() - 1] ==
  // "protein")) {

  //._sequence.replace(QRegExp("\\*"), "")).removeTranslationStop()
  _sp_current_protein.get()->setSequence(_current_text);
  //}
  // else {
  // XtandemHyperscore hyperscore(_curent_spectrum, _current_peptide_sp,
  // _precision, _ion_list, _max_charge,_refine_spectrum_synthesis);
  //}
  // qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  return true;
}
bool
XtpXpipSaxHandler::endElement_protein()
{

  _sp_current_protein =
    _p_project->getProteinStore().getInstance(_sp_current_protein);
  _map_proteins.insert(std::pair<QString, ProteinXtpSp>(
    _sp_current_protein.get()->getAccession(), _sp_current_protein));
  _sp_current_protein = nullptr;
  return true;
}

bool
XtpXpipSaxHandler::endElement_protein_match()
{
  _count_protein_matches++;
  _count_total++;
  _current_identification_group_p->addProteinMatch(_p_protein_match);
  _p_protein_match = nullptr;
  return true;
}


bool
XtpXpipSaxHandler::error(const QXmlParseException &exception)
{
  _errorStr = QObject::tr(
                "Parse error at line %1, column %2 :\n"
                "%3")
                .arg(exception.lineNumber())
                .arg(exception.columnNumber())
                .arg(exception.message());

  return false;
}


bool
XtpXpipSaxHandler::fatalError(const QXmlParseException &exception)
{
  _errorStr = QObject::tr(
                "Parse error at line %1, column %2 :\n"
                "%3")
                .arg(exception.lineNumber())
                .arg(exception.columnNumber())
                .arg(exception.message());
  return false;
}

QString
XtpXpipSaxHandler::errorString() const
{
  return _errorStr;
}


bool
XtpXpipSaxHandler::endDocument()
{
  //_p_project->getProteinStore().setRegexpDecoyPattern(_p_project->getProteinStore().getRegexpDecoy().pattern());
  _p_project->updateAutomaticFilters(_automatic_filter_parameters);
  return true;
}

bool
XtpXpipSaxHandler::startDocument()
{
  return true;
}

bool
XtpXpipSaxHandler::characters(const QString &str)
{
  _current_text += str;
  return true;
}
