/**
 * \file output/exportfastafile.cpp
 * \date 15/01/2019
 * \author Olivier Langella
 * \brief FASTA file writer
 */

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

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

ExportFastaFile::ExportFastaFile(QString filename, ExportFastaType type)
{
  mp_outputFastaFile = new QFile(filename);
  m_exportType       = type;
}

ExportFastaFile::~ExportFastaFile()
{
  close();
}


void
ExportFastaFile::write(ProjectSp project_sp)
{
  qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  if(mp_outputFastaFile == nullptr)
    {
      throw pappso::PappsoException(
        QObject::tr("error : mp_outputFastaFile is null\n"));
    }
  mp_outputFastaFile->open(QIODevice::WriteOnly);
  QTextStream *p_outputStream = new QTextStream(mp_outputFastaFile);


  pappso::FastaOutputStream fasta_output(*p_outputStream);

  for(IdentificationGroup *identification :
      project_sp.get()->getIdentificationGroupList())
    {
      writeIdentificationGroup(fasta_output, identification);
    }
  qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  mp_outputFastaFile->flush();
  qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  mp_outputFastaFile->close();
  qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  close();
  qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
}

void
ExportFastaFile::close()
{
  if(mp_outputFastaFile != nullptr)
    {
      delete mp_outputFastaFile;
      mp_outputFastaFile = nullptr;
    }
}


void
ExportFastaFile::writeIdentificationGroup(
  pappso::FastaOutputStream &fasta_output, IdentificationGroup *p_ident)
{
  qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  for(const std::pair<unsigned int, GroupingGroupSp> &group_pair :
      p_ident->getGroupStore().getGroupMap())
    {
      // unsigned int protein_rank        = 0;
      unsigned int group_number        = 0;
      unsigned int subgroup_number     = 0;
      unsigned int old_group_number    = 0;
      unsigned int old_subgroup_number = 0;

      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)
        {
          pappso::GrpProtein *p_grp_protein =
            protein_match->getGrpProteinSp().get();
          ProteinXtp *p_protein = protein_match->getProteinXtpSp().get();

          group_number    = p_grp_protein->getGroupNumber();
          subgroup_number = p_grp_protein->getSubGroupNumber();

          if((m_exportType == ExportFastaType::oneBySubgroup) &&
             (group_number == old_group_number) &&
             (subgroup_number == old_subgroup_number) &&
             (p_grp_protein->getRank() > 1))
            continue;

          if((m_exportType == ExportFastaType::oneByGroup) &&
             (group_number == old_group_number))
            continue;

          old_group_number    = group_number;
          old_subgroup_number = subgroup_number;

          pappso::Protein protein(QString("%1|%2 %3")
                                    .arg(p_grp_protein->getGroupingId())
                                    .arg(p_protein->getAccession())
                                    .arg(p_protein->getDescription()),
                                  p_protein->getSequence());
          fasta_output.writeProtein(protein);
        }
    }
  qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
}
