/**
 * \file /output/ods/validpsmsheet.cpp
 * \date 12/10/2022
 * \author Olivier Langella
 * \brief write all valid PSMs (not only grouped ones)
 * this displays target and decoy information
 */

/*******************************************************************************
 * Copyright (c) 2022 Olivier Langella
 *<Olivier.Langella@universite-paris-saclay.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/>.
 *
 ******************************************************************************/

#include "validpsmsheet.h"
#include <tuple>
#include <pappsomspp/core/utils.h>

ValidPsmSheet::ValidPsmSheet(OdsExport *p_ods_export,
                             CalcWriterInterface *p_writer,
                             const Project *p_project,
                             const QString &sheet_name)
  : mp_project(p_project)
{
  mp_odsExport = p_ods_export;
  mp_writer    = p_writer;
  mp_writer->writeSheet(sheet_name);

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


  for(IdentificationGroup *identification_group :
      mp_project->getIdentificationGroupList())
    {
      for(auto &p_protein_match : identification_group->getProteinMatchList())
        {
          std::vector<PeptideEvidence *> peptide_evidence_list;
          p_protein_match->collectPeptideEvidences(peptide_evidence_list,
                                                   ValidationState::valid);

          for(auto &peptide_evidence : peptide_evidence_list)
            {
              m_peptideEvidenceList.push_back(peptide_evidence);
            }

          if(!p_protein_match->getProteinXtpSp().get()->isDecoy())
            {
              m_peptideEvidenceListTarget.insert(
                m_peptideEvidenceListTarget.end(),
                peptide_evidence_list.begin(),
                peptide_evidence_list.end());
            }
        }

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


      std::sort(m_peptideEvidenceListTarget.begin(),
                m_peptideEvidenceListTarget.end());
      auto last2 = std::unique(m_peptideEvidenceListTarget.begin(),
                               m_peptideEvidenceListTarget.end());
      m_peptideEvidenceListTarget.erase(last2,
                                        m_peptideEvidenceListTarget.end());
    }


  writeHeaders();

  for(auto &peptide_evidence : m_peptideEvidenceList)
    {
      writePeptideEvidence(peptide_evidence);
    }
}

ValidPsmSheet::ValidPsmSheet(OdsExport *p_ods_export,
                             CalcWriterInterface *p_writer,
                             const Project *p_project)
  : ValidPsmSheet(p_ods_export, p_writer, p_project, QString("valid PSMs"))
{
}

ValidPsmSheet::~ValidPsmSheet()
{
}

void
ValidPsmSheet::writeCellHeader(PeptideListColumn column)
{
  qDebug() << (std::int8_t)column;
  mp_writer->setCellAnnotation(PeptideTableModel::getDescription(column));
  mp_writer->writeCell(PeptideTableModel::getTitle(column));
  qDebug();
}


void
ValidPsmSheet::writeHeaders()
{
  // Group ID	Peptide ID	Sample	Scan	Rt (minutes)	Sequence (top)	Modifs
  // (top)
  // Number of subgroups	Sub-groups Ids	Best E-value	Best hyperscore	m/z Obs
  // Charge	MH+ Obs	MH+ theo	DeltaMH+	Delta-ppm

  mp_writer->writeCell("Group ID");
  mp_writer->writeCell("Peptide ID");

  writeCellHeader(PeptideListColumn::sample);
  writeCellHeader(PeptideListColumn::scan);
  writeCellHeader(PeptideListColumn::rt);
  writeCellHeader(PeptideListColumn::experimental_mz);
  mp_writer->setCellAnnotation("peptide sequence");
  mp_writer->writeCell("Sequence");
  mp_writer->setCellAnnotation("peptide charge");
  mp_writer->writeCell("Charge");
  mp_writer->setCellAnnotation("peptide modifications");
  mp_writer->writeCell("Modifs");
  if(mp_project->getLabelingMethodSp().get() != nullptr)
    {
      mp_writer->setCellAnnotation("peptide label");
      mp_writer->writeCell("Label");
    }
  mp_writer->writeCell("SVM prob");
  mp_writer->writeCell("E-value");
  mp_writer->writeCell("hyperscore");
  writeCellHeader(PeptideListColumn::delta_mhplus);
  writeCellHeader(PeptideListColumn::delta_ppm);

  if(m_displaySpecOmsInformations)
    {
      writeCellHeader(PeptideListColumn::deepprot_delta_positions);
      writeCellHeader(PeptideListColumn::deepprot_match_type);
    }
  mp_writer->writeCell("target");
}

void
ValidPsmSheet::writePeptideEvidence(const PeptideEvidence *p_peptide_evidence)
{

  mp_writer->writeLine();

  pappso::GrpPeptideSp grp_peptide_sp = p_peptide_evidence->getGrpPeptideSp();

  if(grp_peptide_sp.get() == nullptr)
    {
      mp_writer->writeEmptyCell();
      mp_writer->writeEmptyCell();
    }
  else
    {
      unsigned int group_number =
        p_peptide_evidence->getGrpPeptideSp().get()->getGroupNumber();

      mp_writer->writeCell(
        pappso::Utils::getLexicalOrderedString(group_number));
      mp_writer->writeCell(
        p_peptide_evidence->getGrpPeptideSp().get()->getGroupingId());
    }

  mp_writer->writeCell(p_peptide_evidence->getMsRunP()->getSampleName());
  mp_writer->writeCell((std::size_t)p_peptide_evidence->getScanNumber());
  mp_writer->writeCell(p_peptide_evidence->getRetentionTime());
  mp_writer->writeCell(p_peptide_evidence->getExperimentalMz());
  mp_writer->writeCell(
    p_peptide_evidence->getPeptideXtpSp().get()->getSequence());
  mp_writer->writeCell((std::size_t)p_peptide_evidence->getCharge());
  mp_writer->writeCell(
    p_peptide_evidence->getPeptideXtpSp().get()->getModifString());
  if(mp_project->getLabelingMethodSp().get() != nullptr)
    {
      const Label *p_label =
        p_peptide_evidence->getPeptideXtpSp().get()->getLabel();
      if(p_label != nullptr)
        {
          mp_writer->writeCell(p_label->getXmlId());
        }
      else
        {
          mp_writer->writeEmptyCell();
        }
    }
  // SVM prob
  mp_writer->writeCell(
    p_peptide_evidence->getParam(PeptideEvidenceParam::svmProb).toDouble());

  mp_writer->writeCell(p_peptide_evidence->getEvalue());
  mp_writer->writeCell(
    p_peptide_evidence->getParam(PeptideEvidenceParam::tandem_hyperscore)
      .toDouble());
  mp_writer->writeCell(p_peptide_evidence->getDeltaMass());
  mp_writer->writeCell(p_peptide_evidence->getPpmDeltaMass());
  if(m_displaySpecOmsInformations)
    {
      mp_writer->writeCell(
        p_peptide_evidence
          ->getParam(PeptideEvidenceParam::deepprot_delta_positions)
          .toInt());
      mp_writer->writeCell(
        p_peptide_evidence->getParam(PeptideEvidenceParam::deepprot_match_type)
          .toInt());
    }

  if(std::find(m_peptideEvidenceListTarget.begin(),
               m_peptideEvidenceListTarget.end(),
               p_peptide_evidence) != m_peptideEvidenceListTarget.end())
    {
      mp_writer->writeCell(true);
    }
  else
    {
      mp_writer->writeCell(false);
    }
}
