/**
 * \file /output/mcqr/mcqrscpeptide.cpp
 * \date 28/3/2018
 * \author Olivier Langella
 * \brief write peptide sheet in MassChroqR format
 */

/*******************************************************************************
 * Copyright (c) 2018 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 "mcqrscpeptide.h"
#include <pappsomspp/core/pappsoexception.h>

bool
ScPeptideLabel::operator<(const ScPeptideLabel &other) const
{
  return std::tie(_p_grp_peptide, _p_label) <
         std::tie(other._p_grp_peptide, other._p_label);
}

McqRscPeptide::McqRscPeptide(CalcWriterInterface *p_writer,
                             const Project *p_project)
  : _p_project(p_project)
{
  _p_writer = p_writer;
}

void
McqRscPeptide::writeSheet()
{
  _p_writer->writeSheet("peptide_sc");

  std::vector<IdentificationGroup *> identification_list =
    _p_project->getIdentificationGroupList();
  if(identification_list.size() > 1)
    {
      throw pappso::PappsoException(
        QObject::tr("error : cannot write MassChroqR spectral count file in "
                    "individual mode"));
    }

  for(IdentificationGroup *p_ident : identification_list)
    {
      // writeHeaders(p_ident);
      writeIdentificationGroup(p_ident);
    }
}


void
McqRscPeptide::writeHeaders(IdentificationGroup *p_ident [[maybe_unused]])
{

  // ProteinID, msrun, msrunfile, accession, description, q
  _p_writer->writeCell("peptide");
  _p_writer->writeCell("label");
  _p_writer->writeCell("msrun");
  _p_writer->writeCell("msrunfile");
  //_p_writer->writeCell("sequence");
  _p_writer->writeCell("sc");
  _p_writer->writeCell("sc_specific");
  //_p_writer->writeCell(p_protein_match->countSampleScan(state, p_msrun));
}


void
McqRscPeptide::writeIdentificationGroup(IdentificationGroup *p_ident)
{
  ValidationState validation_state = ValidationState::grouped;

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

      std::vector<const ProteinMatch *> protein_match_list =
        group_pair.second.get()->getProteinMatchList();

      std::sort(protein_match_list.begin(),
                protein_match_list.end(),
                [](const ProteinMatch *a, const ProteinMatch *b) {
                  return a->getGrpProteinSp().get()->getSubGroupNumber() <
                         b->getGrpProteinSp().get()->getSubGroupNumber();
                });

      for(auto &protein_match : protein_match_list)
        {

          // count number of scan fore each GrpPeptide
          std::map<ScPeptideLabel, std::size_t> count_scan_zero;
          for(const PeptideMatch &peptide_match :
              protein_match->getPeptideMatchList(validation_state))
            {
              count_scan_zero.insert(std::pair<ScPeptideLabel, std::size_t>(
                {peptide_match.getPeptideEvidence()->getGrpPeptideSp().get(),
                 peptide_match.getPeptideEvidence()
                   ->getPeptideXtpSp()
                   ->getLabel()},
                0));
            }

          for(auto &msrun_sp : ms_run_sp_list)
            {
              std::vector<PeptideMatch> peptide_match_in_msrun =
                protein_match->getPeptideMatchList(validation_state,
                                                   msrun_sp.get());
              writePeptidesInMsrun(protein_match,
                                   msrun_sp.get(),
                                   peptide_match_in_msrun,
                                   count_scan_zero);
            }
        }
    }
  _p_writer->writeLine();
}


void
McqRscPeptide::writePeptidesInMsrun(
  const ProteinMatch *p_protein_match,
  const MsRun *p_msrun,
  const std::vector<PeptideMatch> &peptide_match_in_msrun,
  const std::map<ScPeptideLabel, std::size_t> &count_scan_zero)
{
  try
    {

      qDebug() << "McqRscPeptide::writePeptidesInMsrun begin";
      // count number of scan fore each GrpPeptide
      std::map<ScPeptideLabel, std::size_t> count_scan(count_scan_zero);


      for(const PeptideMatch &peptide_match : peptide_match_in_msrun)
        {
          std::pair<std::map<ScPeptideLabel, std::size_t>::iterator, bool> ret;
          ret = count_scan.insert(std::pair<ScPeptideLabel, std::size_t>(
            {peptide_match.getPeptideEvidence()->getGrpPeptideSp().get(),
             peptide_match.getPeptideEvidence()->getPeptideXtpSp()->getLabel()},
            0));
          if(ret.second == false)
            {
              // already exists
              ret.first->second++;
            }
          else
            {
              // error : it should exists
              throw pappso::PappsoException(QObject::tr("error in %1 %2 %3")
                                              .arg(__FILE__)
                                              .arg(__FUNCTION__)
                                              .arg(__LINE__));
            }
        }

      for(const std::pair<const ScPeptideLabel, std::size_t> &pair_count :
          count_scan)
        {
          _p_writer->writeLine();

          _p_writer->writeCell(
            pair_count.first._p_grp_peptide->getGroupingId());
          if(pair_count.first._p_label == nullptr)
            {
              _p_writer->writeEmptyCell();
            }
          else
            {
              _p_writer->writeCell(pair_count.first._p_label->getXmlId());
            }

          _p_writer->writeCell(p_msrun->getXmlId());
          _p_writer->writeCell(p_msrun->getSampleName());
          //_p_writer->writeCell(pair.first->getSequence());
          _p_writer->writeCell(pair_count.second);

          _p_writer->writeCell(
            p_protein_match->getGroupingGroupSp()
              .get()
              ->countSpecificSequenceLi(p_protein_match,
                                        ValidationState::grouped,
                                        p_msrun,
                                        pair_count.first._p_label));
        }
      qDebug() << "McqRscPeptide::writePeptidesInMsrun end";
    }
  catch(pappso::PappsoException &error)
    {
      throw pappso::PappsoException(
        QObject::tr("Error writing scan count in msrun %1 :\n%2")
          .arg(p_msrun->getXmlId())
          .arg(error.qwhat()));
    }
}
