/**
 * \file output/ods/peptidesheet.cpp
 * \date 27/4/2017
 * \author Olivier Langella
 * \brief ODS peptide sheet
 */

/*******************************************************************************
 * 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 "peptidesheet.h"
#include <pappsomspp/core/utils.h>


PeptideSheet::PeptideSheet(OdsExport *p_ods_export,
                           CalcWriterInterface *p_writer,
                           const Project *p_project)
  : _p_project(p_project)
{
  _p_ods_export = p_ods_export;
  _p_writer     = p_writer;
  p_writer->writeSheet("peptides");

  OdsTableSettings table_settings;
  table_settings.setVerticalSplit(1);
  _p_writer->setCurrentOdsTableSettings(table_settings);

  std::vector<IdentificationGroup *> identification_list =
    p_project->getIdentificationGroupList();
  for(IdentificationGroup *p_ident : identification_list)
    {
      // writeHeaders(p_ident);
      writeIdentificationGroup(p_ident);
    }
}


void
PeptideSheet::writeHeaders(IdentificationGroup *p_ident)
{
  // Group ID	Peptide ID	SequenceLI	Modifs	Charge	MH+ theo	Number of
  // subgroups Subgroup ids	Number of spectra MS Sample :
  // 20120906_balliau_extract_1_A01_urnb-1
  const std::vector<MsRunSp> msrun_list = p_ident->getMsRunSpList();
  if(msrun_list.size() == 1)
    {
      _p_writer->writeCell("sample");
      _p_writer->writeLine();
      _p_writer->writeCell(msrun_list[0].get()->getSampleName());
      _p_writer->writeLine();
    }


  _p_writer->writeLine();
  _p_writer->writeCell("Group ID");
  _p_writer->writeCell("Peptide ID");
  _p_writer->setCellAnnotation(
    "peptide sequence where all leucine are turned into isoleucine");
  _p_writer->writeCell("SequenceLI");
  _p_writer->writeCell("Modifs");
  _p_writer->setCellAnnotation(
    "chemical formula for this peptide, containing H+");
  _p_writer->writeCell("Formula");
  _p_writer->setCellAnnotation(
    "the charge associated to the best peptide Evalue for this sequenceLI");
  _p_writer->writeCell("Charge");
  _p_writer->setCellAnnotation("theoretical mh");
  _p_writer->writeCell("MH+ theo");
  _p_writer->writeCell("Number of subgroups");
  _p_writer->writeCell("Subgroup ids");
  _p_writer->setCellAnnotation("number of scans associated to this peptide");
  _p_writer->writeCell("Number of spectra");
}

void
PeptideSheet::writeIdentificationGroup(IdentificationGroup *p_ident)
{

  writeHeaders(p_ident);
  for(const std::pair<const unsigned int, GroupingGroupSp> &group_pair :
      p_ident->getGroupStore().getGroupMap())
    {

      std::vector<const PeptideEvidence *> peptide_evidence_list =
        group_pair.second.get()->getPeptideEvidenceList();

      std::sort(peptide_evidence_list.begin(),
                peptide_evidence_list.end(),
                [](const PeptideEvidence *a, const PeptideEvidence *b) {
                  return a->getGrpPeptideSp().get()->getRank() <
                         b->getGrpPeptideSp().get()->getRank();
                });

      const PeptideEvidence *p_best_peptide_evidence = nullptr;
      _sample_scan_list.clear();

      for(auto &peptide_evidence : peptide_evidence_list)
        {
          if(p_best_peptide_evidence == nullptr)
            {
              p_best_peptide_evidence = peptide_evidence;
            }
          if(p_best_peptide_evidence->getGrpPeptideSp().get() !=
             peptide_evidence->getGrpPeptideSp().get())
            {
              // write p_best_peptide_match
              writeBestPeptideEvidence(group_pair.second.get(),
                                       p_best_peptide_evidence);
              p_best_peptide_evidence = peptide_evidence;
            }
          else
            {
              if(p_best_peptide_evidence->getEvalue() >
                 peptide_evidence->getEvalue())
                {
                  p_best_peptide_evidence = peptide_evidence;
                }
            }
          _sample_scan_list.push_back(peptide_evidence->getHashSampleScan());
        }

      if(p_best_peptide_evidence != nullptr)
        {
          writeBestPeptideEvidence(group_pair.second.get(),
                                   p_best_peptide_evidence);
        }
    }
  _p_writer->writeLine();
  _p_writer->writeLine();
}

void
PeptideSheet::writeBestPeptideEvidence(
  const GroupingGroup *p_group, const PeptideEvidence *p_peptide_evidence)
{

  std::sort(_sample_scan_list.begin(), _sample_scan_list.end());
  auto last = std::unique(_sample_scan_list.begin(), _sample_scan_list.end());
  _sample_scan_list.erase(last, _sample_scan_list.end());

  _p_writer->writeLine();


  unsigned int group_number =
    p_peptide_evidence->getGrpPeptideSp().get()->getGroupNumber();

  _p_ods_export->setEvenOrOddStyle(group_number, _p_writer);
  _p_writer->writeCell(pappso::Utils::getLexicalOrderedString(group_number));
  _p_writer->clearTableCellStyleRef();
  _p_writer->writeCell(
    p_peptide_evidence->getGrpPeptideSp().get()->getGroupingId());
  _p_writer->writeCell(
    p_peptide_evidence->getGrpPeptideSp().get()->getSequence());
  _p_writer->writeCell(
    p_peptide_evidence->getPeptideXtpSp().get()->getModifString());
  _p_writer->writeCell(
    p_peptide_evidence->getPeptideXtpSp().get()->getFormula(1));
  _p_writer->writeCell((std::size_t)p_peptide_evidence->getCharge());
  _p_writer->writeCell(
    p_peptide_evidence->getPeptideXtpSp().get()->getNativePeptideP()->getMz(1));
  QStringList sg_list = p_group->getSubgroupIdList(p_peptide_evidence);
  _p_writer->writeCell((std::size_t)sg_list.size());
  _p_writer->writeCell(sg_list.join(" "));
  _p_writer->writeCell(_sample_scan_list.size());

  _sample_scan_list.clear();
}
