/**
 * \file output/ods/proteinlistsheet.h
 * \date 05/07/2021
 * \author Olivier Langella
 * \brief ODS protein list for huge spectra output
 */

/*******************************************************************************
 * Copyright (c) 2021 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/>.
 *
 ******************************************************************************/

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

ProteinListSheet::ProteinListSheet(OdsExport *p_ods_export,
                                   CalcWriterInterface *p_writer,
                                   const Project *p_project,
                                   SubMonitor &sub_monitor)
  : mp_project(p_project), m_subMonitor(sub_monitor)
{
  mp_writer    = p_writer;
  mp_odsExport = p_ods_export;
  mp_writer->writeSheet("protein list");

  OdsTableSettings table_settings;
  table_settings.setVerticalSplit(1);
  mp_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
ProteinListSheet::writeCellHeader(ProteinListColumn column)
{
  qDebug() << (std::int8_t)column;
  mp_writer->setCellAnnotation(ProteinTableModel::getDescription(column));
  mp_writer->writeCell(ProteinTableModel::getTitle(column));
  qDebug();
}

void
ProteinListSheet::writeHeaders(IdentificationGroup *p_ident)
{
  mp_writer->writeLine();

  mp_writer->setCellAnnotation("group number");
  mp_writer->writeCell("Group ID");
  mp_writer->setCellAnnotation("subgroup number");
  mp_writer->writeCell("Sub-group ID");

  mp_writer->setCellAnnotation(
    ProteinTableModel::getDescription(ProteinListColumn::protein_grouping_id));
  mp_writer->writeCell("Protein ID");
  // writeCellHeader(ProteinListColumn::protein_grouping_id);
  //_p_writer->setCellAnnotation("unique protein identifier within this grouping
  // experiment"); _p_writer->writeCell("Protein ID");

  writeCellHeader(ProteinListColumn::accession);
}

void
ProteinListSheet::writeIdentificationGroup(IdentificationGroup *p_ident)
{

  writeHeaders(p_ident);
  for(const std::pair<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()->getGroupingId() <
                         b->getGrpProteinSp().get()->getGroupingId();
                });

      for(auto &protein_match : protein_match_list)
        {
          writeOneProtein(group_pair.second.get(), protein_match);
        }
    }
  mp_writer->writeLine();
}


void
ProteinListSheet::writeOneProtein(const GroupingGroup *p_group,
                                  const ProteinMatch *p_protein_match)
{
  try
    {
      mp_writer->writeLine();

      qDebug() << "ProteinListSheet::writeOneProtein begin";
      ValidationState validation_state = ValidationState::validAndChecked;

      pappso::GrpProtein *p_grp_protein =
        p_protein_match->getGrpProteinSp().get();

      ProteinXtp *p_protein = p_protein_match->getProteinXtpSp().get();

      unsigned int group_number    = p_grp_protein->getGroupNumber();
      unsigned int subgroup_number = p_grp_protein->getSubGroupNumber();
      mp_odsExport->setEvenOrOddStyle(group_number, mp_writer);
      mp_writer->writeCell(
        pappso::Utils::getLexicalOrderedString(group_number));
      mp_odsExport->setEvenOrOddStyle(subgroup_number, mp_writer);
      mp_writer->writeCell(
        QString("%1.%2")
          .arg(pappso::Utils::getLexicalOrderedString(group_number))
          .arg(pappso::Utils::getLexicalOrderedString(subgroup_number)));
      mp_writer->clearTableCellStyleRef();
      mp_writer->writeCell(p_grp_protein->getGroupingId());

      const std::list<DbXref> &dbxref_list = p_protein->getDbxrefList();
      if(dbxref_list.size() == 0)
        {
          mp_writer->writeCell(p_protein->getAccession());
        }
      else
        {
          mp_writer->writeCell(dbxref_list.front().getUrl(),
                               p_protein->getAccession());
        }
      mp_writer->writeCell(p_protein->getDescription());
      mp_writer->writeCell(p_protein_match->getLogEvalue());
      // _p_writer->writeCell("Coverage");
      mp_writer->writeCellPercentage(p_protein_match->getCoverage());
      // _p_writer->writeCell("MW");
      mp_writer->writeCell(p_protein->getMass());
      mp_writer->writeCell((std::size_t)p_protein->size());
      // _p_writer->writeCell("Spectra");
      mp_writer->writeCell(p_protein_match->countSampleScan(validation_state));

      // _p_writer->writeCell("Specific");
      mp_writer->writeCell(
        p_group->countSpecificSampleScan(p_protein_match, validation_state));

      // _p_writer->writeCell("Uniques");
      mp_writer->writeCell(p_protein_match->countSequenceLi(validation_state));

      // _p_writer->writeCell("Specific uniques");
      mp_writer->writeCell(
        p_group->countSpecificSequenceLi(p_protein_match, validation_state));


      mp_writer->writeCell(
        p_protein_match->countPeptideMassCharge(validation_state));
      qDebug() << "ProteinListSheet::writeOneProtein tryptic";
      mp_writer->writeCell(p_protein->countTrypticPeptidesForPAI());
      // _p_writer->writeCell("PAI");
      // _p_writer->writeCell(new Double((float) hashProt
      // .getTotalHashSampleScan() / prot.get_PAI_count()));
      mp_writer->writeCell(p_protein_match->getPAI());
      // _p_writer->writeCell(match.getPAI());//this is the same
      /*
       * ancien PAI _p_writer->writeCell(new Double((float)
       * top.get_spectra_numbers_to(sample) /
       * top.get_protein_match().get_PAI_count()));
       */
      mp_writer->writeCell(p_protein_match->getEmPAI());

      //_p_writer->writeCell(p_protein_match->getSpectralCountAI());

      // _p_writer->writeCell("Redundancy");
      mp_writer->writeCell((std::size_t)p_group->countProteinInSubgroup(
        p_grp_protein->getSubGroupNumber()));

      // number of MS sample
      mp_writer->writeCell(
        (std::size_t)p_protein_match->countDistinctMsSamples(validation_state));

      qDebug() << "ProteinListSheet::writeOneProtein end";
    }
  catch(pappso::PappsoException &error)
    {
      throw pappso::PappsoException(
        QObject::tr("Error writing protein %1 :\n%2")
          .arg(p_protein_match->getProteinXtpSp().get()->getAccession())
          .arg(error.qwhat()));
    }
}
