/**
 * \file output/masschroqprm.cpp
 * \date 10/6/2017
 * \author Olivier Langella
 * \brief MassChroqPRM writer
 */

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

#include "masschroqprm.h"
#include <pappsomspp/core/pappsoexception.h>
#include <pappsomspp/core/utils.h>

MassChroqPrm::MassChroqPrm(const QString &out_filename)
{
  //_p_digestion_pipeline = p_digestion_pipeline;

  //_mzidentml = "http://psidev.info/psi/pi/mzIdentML/1.1";
  QString complete_out_filename = out_filename;
  _output_file                  = new QFile(complete_out_filename);

  if(_output_file->open(QIODevice::WriteOnly))
    {
      _output_stream = new QXmlStreamWriter();
      _output_stream->setDevice(_output_file);
    }
  else
    {
      throw pappso::PappsoException(
        QObject::tr("error : cannot open the MassChroqPRM output file : %1\n")
          .arg(out_filename));
    }

  _output_stream->setAutoFormatting(true);
  _output_stream->writeStartDocument("1.0");
}

MassChroqPrm::~MassChroqPrm()
{
  delete _output_file;
  delete _output_stream;
}

void
MassChroqPrm::close()
{
  _output_stream->writeEndDocument();
  _output_file->close();
}

void
MassChroqPrm::write(ProjectSp sp_project)
{

  _sp_project = sp_project;
  if(_sp_project.get() == nullptr)
    {
      throw pappso::PappsoException(
        QObject::tr("Error writing MassChroqPRM file :\n project is empty"));
    }

  //<masschroq>
  _output_stream->writeStartElement("masschroqprm");
  /*
   *
  <parameters>
  <parentIonMassTolerance>
  <daltonPrecision value="1.5"/>
  </parentIonMassTolerance>
  <fragmentIonMassTolerance>
  <daltonPrecision value="0.02"/>
  </fragmentIonMassTolerance>
  </parameters>
   */
  _output_stream->writeStartElement("parameters");
  _output_stream->writeStartElement("parentIonMassTolerance");
  _output_stream->writeComment(
    "choose dalton or ppm mass precision to select parent ions based on the "
    "precursor mass of each MS/MS spectrum");
  _output_stream->writeStartElement("ppmPrecision");
  _output_stream->writeAttribute("value", "10");
  _output_stream->writeEndElement();
  _output_stream->writeEndElement();
  _output_stream->writeStartElement("fragmentIonMassTolerance");
  _output_stream->writeComment(
    "choose dalton or ppm mass precision to MS/MS fragment ion observed mass "
    "with theoretical mass");
  _output_stream->writeStartElement("daltonPrecision");
  _output_stream->writeAttribute("value", "0.02");
  _output_stream->writeEndElement();
  _output_stream->writeEndElement();
  _output_stream->writeEndElement();

  writePeptides();
}

void
MassChroqPrm::writePeptides()
{

  /*
   *
   *
   * <peptide seq="TCVADESHAGCEK" id="p1"> <psimod at="2"
   * acc="MOD:00397"/> <psimod at="11" acc="MOD:00397"/> </peptide>
   */
  try
    {

      _output_stream->writeStartElement("peptideList");

      for(IdentificationDataSourceSp identification_data_source_sp :
          _sp_project.get()
            ->getIdentificationDataSourceStore()
            .getIdentificationDataSourceList())
        {
          for(const PeptideEvidenceSp &peptide_evidence_sp :
              identification_data_source_sp.get()
                ->getPeptideEvidenceStore()
                .getPeptideEvidenceList())
            {
              const pappso::GrpPeptide *p_grp_peptide =
                peptide_evidence_sp.get()->getGrpPeptideSp().get();

              if(p_grp_peptide != nullptr)
                {
                  std::set<const pappso::GrpPeptide *> _already_writed;
                  if(_already_writed.find(p_grp_peptide) ==
                     _already_writed.end())
                    {
                      _already_writed.insert(p_grp_peptide);
                      PeptideXtp *p_peptide =
                        peptide_evidence_sp.get()->getPeptideXtpSp().get();
                      _output_stream->writeStartElement("peptide");
                      _output_stream->writeAttribute(
                        "id", p_grp_peptide->getGroupingId());
                      _output_stream->writeAttribute("seq",
                                                     p_peptide->getSequence());


                      unsigned int i = 0;
                      for(const pappso::Aa &amino_acid : *p_peptide)
                        {

                          std::vector<pappso::AaModificationP> aa_modif_list =
                            amino_acid.getModificationList();


                          for(auto &&aa_modif : aa_modif_list)
                            {
                              if(!aa_modif->isInternal())
                                {
                                  _output_stream->writeStartElement("psimod");
                                  _output_stream->writeAttribute(
                                    "acc", aa_modif->getAccession());
                                  _output_stream->writeAttribute(
                                    "at", QString("%1").arg(i));
                                  _output_stream->writeEndElement(); // mod
                                }
                            }
                          i++;
                        }
                      _output_stream->writeEndElement();
                    }
                }
            }
        }
      // peptideList
      _output_stream->writeEndElement();
    }
  catch(pappso::PappsoException &error)
    {
      throw pappso::PappsoException(
        QObject::tr("Error in MassChroqPrm::writePeptides :\n%1")
          .arg(error.qwhat()));
    }
  catch(std::exception &error)
    {
      throw pappso::PappsoException(
        QObject::tr("Error in MassChroqPrm::writePeptides stdex :\n%1")
          .arg(error.what()));
    }
}
