/**
 * \file pappsomspp/processing/cbor/psm/psmfileappend.cpp
 * \date 10/07/2025
 * \author Olivier Langella
 * \brief append many PSM cbor file into a single one
 */

/*******************************************************************************
 * Copyright (c) 2025 Olivier Langella <Olivier.Langella@universite-paris-saclay.fr>.
 *
 * This file is part of PAPPSOms-tools.
 *
 *     PAPPSOms-tools 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.
 *
 *     PAPPSOms-tools 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 PAPPSOms-tools.  If not, see <http://www.gnu.org/licenses/>.
 *
 ******************************************************************************/

#include "psmfileappend.h"
#include "pappsomspp/core/pappsoexception.h"

pappso::cbor::psm::PsmFileAppend::PsmFileAppend(pappso::cbor::CborStreamWriter *p_output)
{
  mp_output = p_output;

  mp_output->startMap();

  mpa_temporaryDirectory = new QTemporaryDir();
  mpa_temporaryDirectory->setAutoRemove(false);
}

pappso::cbor::psm::PsmFileAppend::~PsmFileAppend()
{
  delete mpa_temporaryDirectory;
}

void
pappso::cbor::psm::PsmFileAppend::informationsReady(pappso::UiMonitorInterface &monitor
                                                    [[maybe_unused]])
{
  if(!m_isInformations)
    {
      mp_output->append("informations");
      mp_output->writeCborMap(m_cborInformations);
      m_isInformations = true;
    }
}

void
pappso::cbor::psm::PsmFileAppend::parameterMapReady(pappso::UiMonitorInterface &monitor
                                                    [[maybe_unused]])
{
  mergeParameterMap();
}


void
pappso::cbor::psm::PsmFileAppend::close()
{


  qDebug();
  mp_output->append("parameter_map");
  mp_output->writeCborMap(m_outputParameterMap);


  if(!m_outputTargetFastaFiles.isEmpty())
    {
      mp_output->append("target_fasta_files");
      mp_output->writeArray(m_outputTargetFastaFiles);
    }
  if(!m_outputDecoyFastaFiles.isEmpty())
    {
      mp_output->append("decoy_fasta_files");
      mp_output->writeArray(m_outputDecoyFastaFiles);
    }

  mp_output->append("protein_map");
  m_proteinMap.writeMap(*mp_output);

  qDebug();
  mp_output->append("sample_list");
  mp_output->startArray();
  for(auto &tmp_sample : m_sampleStorageList)
    {
      QFile store_sample_file(tmp_sample.temporaryFile);
      store_sample_file.open(QIODevice::ReadOnly);
      CborStreamReader tmp_reader(&store_sample_file);
      if(tmp_reader.isTag() && tmp_reader.toTag() == QCborKnownTags::Signature)
        tmp_reader.next();
      QCborMap cbor_sample;
      if(!tmp_reader.readCborMap(cbor_sample))
        {
          throw pappso::PappsoException(
            QObject::tr("ERROR writing sample %1").arg(tmp_sample.fileId));
        }
      mp_output->writeCborMap(cbor_sample);
      store_sample_file.close();
    }
  mp_output->endArray();


  qDebug();
  mp_output->endMap();
}

void
pappso::cbor::psm::PsmFileAppend::mergeParameterMap()
{
  for(auto cbor_key : m_cborParameterMap.keys())
    {
      if(!m_outputParameterMap.contains(cbor_key))
        {
          m_outputParameterMap.insert(cbor_key, m_cborParameterMap.value(cbor_key));
        }
    }
}

void
pappso::cbor::psm::PsmFileAppend::fastaFilesReady(pappso::UiMonitorInterface &monitor
                                                  [[maybe_unused]])
{
  m_outputDecoyFastaFiles  = m_decoyFastaFiles;
  m_outputTargetFastaFiles = m_targetFastaFiles;
}

void
pappso::cbor::psm::PsmFileAppend::readSample(pappso::UiMonitorInterface &monitor [[maybe_unused]])
{
  QCborMap cbor_current_sample;

  mpa_cborReader->readCborMap(cbor_current_sample);

  SampleStorage sample_file;
  sample_file.fileId  = cbor_current_sample.value("name").toString();
  QString sample_name = sample_file.fileId;
  auto it             = std::find_if(m_sampleStorageList.begin(),
                         m_sampleStorageList.end(),
                         [sample_name](const SampleStorage &sample) {
                           if(sample.fileId == sample_name)
                             return true;
                           return false;
                         });
  if(it != m_sampleStorageList.end())
    {
      throw pappso::PappsoException(
        QObject::tr("adding the same sample twice is forbidden %1").arg(sample_name));
    }
  sample_file.temporaryFile =
    mpa_temporaryDirectory->filePath(QString("file_%1").arg(m_sampleStorageList.size()));
  m_sampleStorageList.push_back(sample_file);

  QFile store_sample_file(sample_file.temporaryFile);
  store_sample_file.open(QIODevice::WriteOnly);
  CborStreamWriter tmp_writer(&store_sample_file);
  tmp_writer.writeCborMap(cbor_current_sample);
  store_sample_file.close();
}
