/**
 * \file pappsomspp/processing/cbor/psm/psmcbor2json.cpp
 * \date 19/07/2025
 * \author Olivier Langella
 * \brief convert CBOR PSM to JSON
 */

/*******************************************************************************
 * 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 "psmcbor2json.h"
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonValue>
#include "pappsomspp/core/pappsoexception.h"

pappso::cbor::psm::PsmCbor2Json::PsmCbor2Json(pappso::cbor::JsonStreamWriter *json_output_p)
{
  mp_jsonOutput = json_output_p;

  *mp_jsonOutput << "{" << Qt::endl;
}


pappso::cbor::psm::PsmCbor2Json::~PsmCbor2Json()
{
}

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

  mp_jsonOutput->endMap();
}

void
pappso::cbor::psm::PsmCbor2Json::fastaFilesReady(pappso::UiMonitorInterface &monitor
                                                 [[maybe_unused]])
{
  if(!m_targetFastaFiles.isEmpty())
    {
      mp_jsonOutput->appendKey("target_fasta_files");
      mp_jsonOutput->writeArray(m_targetFastaFiles);
    }
  if(!m_decoyFastaFiles.isEmpty())
    {
      mp_jsonOutput->appendKey("decoy_fasta_files");
      mp_jsonOutput->writeArray(m_decoyFastaFiles);
    }
}

void
pappso::cbor::psm::PsmCbor2Json::informationsReady(pappso::UiMonitorInterface &monitor
                                                   [[maybe_unused]])
{

  mp_jsonOutput->appendKey("informations");
  mp_jsonOutput->writeCborMap(m_cborInformations);
}

void
pappso::cbor::psm::PsmCbor2Json::logReady(pappso::UiMonitorInterface &monitor [[maybe_unused]])
{
  mp_jsonOutput->appendKey("log");
  mp_jsonOutput->writeCborArray(m_cborLog);
}


void
pappso::cbor::psm::PsmCbor2Json::parameterMapReady(pappso::UiMonitorInterface &monitor
                                                   [[maybe_unused]])
{
  mp_jsonOutput->appendKey("parameter_map");
  mp_jsonOutput->writeCborMap(m_cborParameterMap);
}

void
pappso::cbor::psm::PsmCbor2Json::sampleListStarted(pappso::UiMonitorInterface &monitor
                                                   [[maybe_unused]])
{

  mp_jsonOutput->appendKey("sample_list");
  mp_jsonOutput->startArray();
}

void
pappso::cbor::psm::PsmCbor2Json::sampleListFinished(pappso::UiMonitorInterface &monitor
                                                    [[maybe_unused]])
{

  mp_jsonOutput->endArray();
}

void
pappso::cbor::psm::PsmCbor2Json::readProteinMap(pappso::UiMonitorInterface &monitor
                                                [[maybe_unused]])
{
  mp_jsonOutput->appendKey("protein_map");
  mp_jsonOutput->startMap();
  if(!mpa_cborReader->enterContainer())
    {
      throw pappso::PappsoException(QObject::tr("enterContainer in protein map failed"));
    }
  QString accession;
  while(!mpa_cborReader->lastError() && mpa_cborReader->hasNext())
    {
      mpa_cborReader->decodeString(accession);
      mp_jsonOutput->appendKey(accession);

      QCborMap cbor_protein;
      mpa_cborReader->readCborMap(cbor_protein);
      mp_jsonOutput->writeCborMap(cbor_protein);
    }

  mpa_cborReader->leaveContainer();
  mp_jsonOutput->endMap();
}

void
pappso::cbor::psm::PsmCbor2Json::scanStarted(pappso::UiMonitorInterface &monitor [[maybe_unused]])
{

  mp_jsonOutput->startMap();
  mp_jsonOutput->appendKey("id");
  mp_jsonOutput->writeCborMap(m_cborScanId);
  mp_jsonOutput->appendKey("precursor");
  mp_jsonOutput->writeCborMap(m_cborScanPrecursor);
  mp_jsonOutput->appendKey("ms2");
  mp_jsonOutput->writeCborMap(m_cborScanMs2);
  if(!m_cborScanProps.isEmpty())
    {
      mp_jsonOutput->appendKey("props");
      mp_jsonOutput->writeCborMap(m_cborScanProps);
    };
  mp_jsonOutput->appendKey("psm_list");
  mp_jsonOutput->startArray();
}

void
pappso::cbor::psm::PsmCbor2Json::scanFinished(pappso::UiMonitorInterface &monitor [[maybe_unused]])
{
  mp_jsonOutput->endArray(); // psm_list
  mp_jsonOutput->endMap();   // scan
}


void
pappso::cbor::psm::PsmCbor2Json::sampleStarted(pappso::UiMonitorInterface &monitor [[maybe_unused]])
{
  //"name": "tandem2017_nopatch_20120906_balliau_extract_1_A01_urnb-1",
  qDebug();
  mp_jsonOutput->startMap(); // sample
  mp_jsonOutput->appendKey("name");
  mp_jsonOutput->appendValue(m_currentSampleName);


  mp_jsonOutput->appendKey("identification_file_list");
  mp_jsonOutput->startArray();
  for(auto &identification_file : m_currentIdentificationFileList)
    {
      mp_jsonOutput->startMap();
      mp_jsonOutput->appendKey("name");
      mp_jsonOutput->appendValue(identification_file.name);
      mp_jsonOutput->endMap();
    }
  mp_jsonOutput->endArray();


  mp_jsonOutput->appendKey("peaklist_file");
  mp_jsonOutput->startMap();
  mp_jsonOutput->appendKey("name");
  mp_jsonOutput->appendValue(m_currentPeaklistFile.name);
  mp_jsonOutput->endMap();

  mp_jsonOutput->appendKey("scan_list");
  mp_jsonOutput->startArray();
}

void
pappso::cbor::psm::PsmCbor2Json::sampleFinished(pappso::UiMonitorInterface &monitor
                                                [[maybe_unused]])
{
  mp_jsonOutput->endArray(); // scan_list
  mp_jsonOutput->endMap();   // sample
}

void
pappso::cbor::psm::PsmCbor2Json::psmReady(pappso::UiMonitorInterface &monitor [[maybe_unused]])
{
  mp_jsonOutput->startMap(); // psm
  mp_jsonOutput->appendKey("proforma");
  mp_jsonOutput->appendValue(m_currentPsmProforma);
  mp_jsonOutput->appendKey("protein_list");
  mp_jsonOutput->startArray();
  for(auto &protein_ref : m_currentPsmProteinRefList)
    {
      mp_jsonOutput->startMap();
      mp_jsonOutput->appendKey("accession");
      mp_jsonOutput->appendValue(protein_ref.accession);
      mp_jsonOutput->appendKey("positions");
      mp_jsonOutput->startArray();
      for(auto position : protein_ref.positions)
        {
          mp_jsonOutput->appendValue(position);
        }
      mp_jsonOutput->endArray();
      mp_jsonOutput->endMap();
    }
  mp_jsonOutput->endArray();
  if(!m_cborScanPsmProps.isEmpty())
    {
      mp_jsonOutput->appendKey("props");
      mp_jsonOutput->writeCborMap(m_cborScanPsmProps);
    }
  mp_jsonOutput->appendKey("eval");
  mp_jsonOutput->writeCborMap(m_cborScanPsmEval);

  mp_jsonOutput->endMap(); // psm
}
