/**
 * \file /output/mcqrspectralcount.h
 * \date 23/3/2018
 * \author Olivier Langella
 * \brief write simple TSV file for MassChroqR spectral count studies
 */

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

#include "mcqrspectralcount.h"
#include <pappsomspp/pappsoexception.h>


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


  _sp_labelling_method = p_project->getLabelingMethodSp();

  if(_sp_labelling_method.get() != nullptr)
    {
      _label_list = _sp_labelling_method.get()->getLabelList();
    }
}

void
McqrSpectralCount::writeSheet()
{
  _p_writer->writeSheet("MassChroqR spectral counting");

  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
McqrSpectralCount::writeHeaders(IdentificationGroup *p_ident [[maybe_unused]])
{

  // ProteinID, msrun, msrunfile, accession, description, q
  _p_writer->writeCell("protein");
  _p_writer->writeCell("msrun");
  _p_writer->writeCell("msrunfile");
  if(_sp_labelling_method != nullptr)
    {
      _p_writer->writeCell("label");
    }
  _p_writer->writeCell("accession");
  _p_writer->writeCell("description");
  _p_writer->writeCell("sc");
  _p_writer->writeCell("sc_specific");
  //_p_writer->writeCell(p_protein_match->countSampleScan(state, p_msrun));
}


void
McqrSpectralCount::writeIdentificationGroup(IdentificationGroup *p_ident)
{

  _ms_run_sp_list = p_ident->getMsRunSpList();
  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()->getSubGroupNumber() <
                         b->getGrpProteinSp().get()->getSubGroupNumber();
                });

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


void
McqrSpectralCount::writeOneProtein(const GroupingGroup *p_group
                                   [[maybe_unused]],
                                   const ProteinMatch *p_protein_match)
{
  try
    {

      qDebug() << "McqrSpectralCount::writeOneProtein begin";

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

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

      // const Label *p_label = nullptr;


      for(MsRunSp &msrun_sp : _ms_run_sp_list)
        {

          if(_label_list.size() == 0)
            {
              writeOneProteinLabel(p_grp_protein,
                                   msrun_sp.get(),
                                   nullptr,
                                   p_protein,
                                   p_protein_match);
            }
          else
            {
              for(auto &p_label : _label_list)
                {
                  writeOneProteinLabel(p_grp_protein,
                                       msrun_sp.get(),
                                       p_label,
                                       p_protein,
                                       p_protein_match);
                }
            }
        }
      qDebug() << "McqrSpectralCount::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()));
    }
}

void
McqrSpectralCount::writeOneProteinLabel(const pappso::GrpProtein *p_grp_protein,
                                        const MsRun *p_msrun,
                                        const Label *p_label,
                                        const ProteinXtp *p_protein,
                                        const ProteinMatch *p_protein_match)
{

  _p_writer->writeLine();

  _p_writer->writeCell(p_grp_protein->getGroupingId());

  _p_writer->writeCell(p_msrun->getXmlId());
  _p_writer->writeCell(p_msrun->getFileName());

  if(p_label != nullptr)
    {
      _p_writer->writeCell(p_label->getXmlId());
    }

  // const std::list<DbXref> & dbxref_list = p_protein->getDbxrefList();
  // if (dbxref_list.size() == 0) {
  _p_writer->writeCell(p_protein->getAccession());
  //}
  // else {
  //    _p_writer->writeCell(dbxref_list.front().getUrl(),
  //    p_protein->getAccession());
  //}
  _p_writer->writeCell(p_protein->getDescription());
  _p_writer->writeCell(p_protein_match->countSampleScan(
    ValidationState::grouped, p_msrun, p_label));

  _p_writer->writeCell(
    p_protein_match->getGroupingGroupSp().get()->countSpecificSampleScan(
      p_protein_match, ValidationState::grouped, p_msrun, p_label));
}
