/**
 * \file input/sage/sagefilereader.cpp
 * \date 11/10/2024
 * \author Olivier Langella
 * \brief read data files from Sage output containin multiple samples
 */

/*******************************************************************************
 * Copyright (c) 2024 Olivier Langella
 *<Olivier.Langella@universite-paris-saclay.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 "sagefilereader.h"
#include <pappsomspp/core/pappsoexception.h>
#include <pappsomspp/core/processing/project/projectparameters.h>
#include <pappsomspp/core/exception/exceptionnotrecognized.h>
#include <pappsomspp/core/processing/cbor/psm/sage/sagefilereader.h>
#include <QJsonObject>
#include <QJsonArray>
#include <QBuffer>
#include "../psmcbor/cborpsmfilereader.h"

SageFileReader::SageFileReader(pappso::UiMonitorInterface *p_monitor,
                               Project *p_project,
                               const QFileInfo &sage_json_file)
  : m_sageJsonFile(sage_json_file)
{
  qDebug() << m_sageJsonFile.absoluteFilePath() << "'";

  QBuffer *binary_buffer                      = nullptr;
  pappso::cbor::CborStreamWriter *cbor_writer = nullptr;
  try
    {
      // qWarning() << "json start";
      binary_buffer = new QBuffer();
      binary_buffer->open(QIODevice::ReadWrite);
      pappso::cbor::CborStreamWriter *cbor_writer =
        new pappso::cbor::CborStreamWriter(binary_buffer);

      pappso::cbor::psm::SageFileReader sage_file_convert(
        p_monitor, cbor_writer, sage_json_file);
      // qWarning() << "json OK";
      //  binary_buffer->close();
    }
  catch(pappso::ExceptionNotRecognized &err)
    {
      if(cbor_writer != nullptr)
        delete cbor_writer;
      if(binary_buffer != nullptr)
        delete binary_buffer;
      throw err;
    }
  catch(pappso::PappsoException &other_err)
    {
      if(cbor_writer != nullptr)
        delete cbor_writer;
      if(binary_buffer != nullptr)
        delete binary_buffer;
      throw pappso::PappsoException(
        QObject::tr("Error reading Sage JSON file %1:\n%2")
          .arg(m_sageJsonFile.absoluteFilePath())
          .arg(other_err.qwhat()));
    }

  try
    {
      // qWarning() << "cbor start";
      binary_buffer->seek(0);

      CborPsmFileReader cbor_file_reader(p_project);
      // qWarning() << "sagefilereader.cpp";
      cbor_file_reader.readCbor(binary_buffer, *p_monitor);

      // qWarning() << "sagefilereader.cpp";
      binary_buffer->close();
      if(binary_buffer != nullptr)
        delete binary_buffer;
      if(cbor_writer != nullptr)
        delete cbor_writer;
      // qWarning() << "cbor OK";
    }
  catch(pappso::ExceptionNotRecognized &err)
    {
      if(binary_buffer != nullptr)
        delete binary_buffer;
      if(cbor_writer != nullptr)
        delete cbor_writer;
      throw err;
    }
  catch(pappso::PappsoException &other_err)
    {
      if(binary_buffer != nullptr)
        delete binary_buffer;
      if(cbor_writer != nullptr)
        delete cbor_writer;
      throw pappso::PappsoException(
        QObject::tr("Error reading Sage JSON file %1:\n%2")
          .arg(m_sageJsonFile.absoluteFilePath())
          .arg(other_err.qwhat()));
    }
}

SageFileReader::~SageFileReader()
{
}


void
SageFileReader::readJson(Project *p_project)
{
  QFile mfile(m_sageJsonFile.absoluteFilePath());
  if(!mfile.open(QFile::ReadOnly))
    {
      throw pappso::ExceptionNotRecognized(
        QObject::tr("Unable to read Sage JSON file %1")
          .arg(m_sageJsonFile.absoluteFilePath()));
    }
  QByteArray iContents = mfile.readAll();

  QJsonParseError parseError;
  m_jsonData = QJsonDocument::fromJson(iContents, &parseError);
  if(parseError.error != QJsonParseError::NoError)
    {
      throw pappso::ExceptionNotRecognized(
        QObject::tr("Error reading Sage JSON file %1 at %2:%3")
          .arg(m_sageJsonFile.absoluteFilePath())
          .arg(parseError.offset)
          .arg(parseError.errorString()));
    }

  QJsonValue mzml_value = m_jsonData.object().value("mzml_paths");

  if(mzml_value.isNull())
    {
      throw pappso::ExceptionNotRecognized(
        QObject::tr("Sage JSON file %1 does not contain mzml_paths")
          .arg(m_sageJsonFile.absoluteFilePath()));
    }
  for(const QJsonValue &value :
      m_jsonData.object().value("mzml_paths").toArray())
    {
      qDebug() << value.toString();

      MsRunSp msrun_sp =
        p_project->getMsRunStore().getInstance(value.toString());
      m_mapFilePath2MsRunSp.insert(
        {QFileInfo(value.toString()).fileName(), msrun_sp});
    }


  m_sageVersion = m_jsonData.object().value("version").toString();
}

const QJsonDocument &
SageFileReader::getJsonDocument() const
{
  return m_jsonData;
}

void
SageFileReader::addFastaFile(FastaFileSp file) const
{
  if(!file.get()->getQFileInfo().exists())
    {
      throw pappso::PappsoException(
        QObject::tr("fasta file %1 not found")
          .arg(file.get()->getQFileInfo().absoluteFilePath()));
    }
  for(auto &sage_source : m_mapFilePath2IdentificationSageJsonFileSp)
    {
      sage_source.second.get()->addFastaFile(file);
    }
}

MsRunSp
SageFileReader::getMsRunSpWithFileName(const QString &msrun_filename) const
{
  auto it = m_mapFilePath2MsRunSp.find(msrun_filename);
  if(it != m_mapFilePath2MsRunSp.end())
    return it->second;


  throw pappso::PappsoException(
    QObject::tr("msrun filename %1 not found").arg(msrun_filename));
}

IdentificationSageJsonFileSp
SageFileReader::getIdentificationSageJsonFileSpWithFileName(
  const QString &msrun_filename) const
{
  auto it = m_mapFilePath2IdentificationSageJsonFileSp.find(msrun_filename);
  if(it != m_mapFilePath2IdentificationSageJsonFileSp.end())
    return it->second;


  throw pappso::PappsoException(
    QObject::tr("Error reading Sage JSON file %1 msrun filename %2 not found")
      .arg(m_sageJsonFile.absoluteFilePath())
      .arg(msrun_filename));
}

IdentificationGroup *
SageFileReader::getIdentificationGroupPtrWithFileName(
  const QString &msrun_filename) const
{
  auto it = m_mapFilePath2IdentificationGroupPtr.find(msrun_filename);
  if(it != m_mapFilePath2IdentificationGroupPtr.end())
    return it->second;


  throw pappso::PappsoException(
    QObject::tr("Error reading Sage JSON file %1 msrun filename %2 not found")
      .arg(m_sageJsonFile.absoluteFilePath())
      .arg(msrun_filename));
}
