/**
 * \file src/lib/loadpappsomsdata.cpp
 * \date 11/01/2024
 * \author Olivier Langella
 * \brief reads MS data file using the PAPPSOms++ library
 */

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

#include "loadpappsomsdata.h"
#include <pappsomspp/core/pappsoexception.h>
#include <pappsomspp/core/msfile/msfileaccessor.h>
#include <pappsomspp/core/msrun/private/timsmsrunreaderms2.h>
#include <pappsomspp/core/processing/filters/filtersuitestring.h>
#include <pappsomspp/core/processing/filters/filterchargedeconvolution.h>

QString
mspectrumToString(const mspectrum &tandem_spectrum)
{
  QString print = QString(
                    "description=%1 m_bActive=%2 m_dMH=%3 m_fI=%4 m_fZ=%5 "
                    "m_strRt=%6 m_tId=%7 m_uiType=%8\n")
                    .arg(tandem_spectrum.m_strDescription.c_str())
                    .arg(tandem_spectrum.m_bActive)
                    .arg(QString::number(tandem_spectrum.m_dMH, 'f', 10))
                    .arg(tandem_spectrum.m_fI)
                    .arg(tandem_spectrum.m_fZ)
                    .arg(tandem_spectrum.m_retentionTimeInSeconds)
                    .arg(tandem_spectrum.m_tId)
                    .arg(tandem_spectrum.m_uiType);

  for(const mi &tandem_point : tandem_spectrum.m_vMI)
    {
      print.append(QString("%1 %2\n")
                     .arg(QString::number(tandem_point.m_fM, 'f', 10))
                     .arg(tandem_point.m_fI));
    }
  return print;
};

LoadPappsoMsData::LoadPappsoMsData(vector<mspectrum> &vSpectra,
                                   mspectrumcondition &specCondition,
                                   mscore *pScore)
  : m_vSpectra(vSpectra), m_specCondition(specCondition)
{
  m_pScore = pScore;
}

LoadPappsoMsData::~LoadPappsoMsData()
{
}

bool
LoadPappsoMsData::needPeakList() const
{
  return true;
}

pappso::MsRunReaderSPtr
LoadPappsoMsData::getMsRunReaderSPtr(XmlParameter &xml_performance,
                                     XmlParameter &xml_values,
                                     pappso::MsFileAccessor *p_file_accessor,
                                     const QString &filename)
{

  pappso::MsRunReaderSPtr msrun_reader_sp;


  qDebug() << filename;
  try
    {
      p_file_accessor = new pappso::MsFileAccessor(filename, "");
      p_file_accessor->setPreferredFileReaderType(
        pappso::Enums::MsDataFormat::brukerTims,
        pappso::Enums::FileReaderType::tims_ms2);
      msrun_reader_sp =
        p_file_accessor->getMsRunReaderSPtrByRunId("", "runa01");
      qDebug() << msrun_reader_sp.get();
    }
  catch(const pappso::PappsoException &error)
    {
      throw pappso::PappsoException(
        QObject::tr("failure opening file %1: %2, check path or permissions")
          .arg(filename)
          .arg(error.qwhat()));
      return msrun_reader_sp;
    }

  std::string parameter_name("output, spectrum index");
  std::string parameter_value("true");
  xml_performance.set(parameter_name, parameter_value);
  // set it to "used"
  xml_performance.get(parameter_name, parameter_value);

  pappso::TimsMsRunReaderMs2 *tims2_reader =
    dynamic_cast<pappso::TimsMsRunReaderMs2 *>(msrun_reader_sp.get());
  if(tims2_reader != nullptr)
    {
      qDebug();
      tims2_reader->setMs2BuiltinCentroid(true);

      std::shared_ptr<pappso::FilterSuiteString> ms2filter;
      QString filters_str =
        "chargeDeconvolution|0.02dalton mzExclusion|0.01dalton";


      ms2filter = std::make_shared<pappso::FilterSuiteString>(filters_str);

      tims2_reader->setMs2FilterCstSPtr(ms2filter);


      parameter_name  = "spectrum, timstof MS2 filters";
      parameter_value = filters_str.toStdString();
      xml_values.set(parameter_name, parameter_value);
      // set it to "used"
      xml_values.get(parameter_name, parameter_value);
      qDebug();
    }

  /*
   *  m_mapParam m_mapUsed
wrap_output.setInputParameters("spectrum, timstof MS2 filters",
                           getMs2FilterSuiteString());
wrap_output.setInputParameters("spectrum, mzFormat",
                           QString("%1").arg((int)m_mzFormat));
wrap_output.setInputParameters("output, spectrum index", "true");
*/

  parameter_name = "spectrum, mzFormat";
  parameter_value =
    QString::number((std::int8_t)p_file_accessor->getFileFormat())
      .toStdString();
  xml_values.set(parameter_name, parameter_value);
  // set it to "used"
  xml_values.get(parameter_name, parameter_value);

  return msrun_reader_sp;
}

bool
LoadPappsoMsData::readAllMs2Spectrum(
  const pappso::MsRunReaderSPtr &msrun_reader,
  vector<mspectrum> &vSpectra,
  mspectrumcondition &m_specCondition,
  mscore *m_pScore)
{

  try
    {
      LoadPappsoMsData spectrum_list_reader(
        vSpectra, m_specCondition, m_pScore);
      spectrum_list_reader.setNeedMsLevelPeakList(1, false);
      spectrum_list_reader.setNeedMsLevelPeakList(2, true);
      pappso::MsRunReadConfig config;
      config.setNeedPeakList(true);
      config.setMsLevels({2});
      qDebug();
      // msrunA01.get()->readSpectrumCollection(spectrum_list_reader);
      msrun_reader.get()->readSpectrumCollection2(config, spectrum_list_reader);
    }
  catch(const pappso::PappsoException &error)
    {
      throw pappso::PappsoException(
        QObject::tr("failure reading MS data : %1").arg(error.qwhat()));
      return false;
    }


  setlocale(LC_ALL, "C");
  return true;
}


void
LoadPappsoMsData::setQualifiedMassSpectrum(
  const pappso::QualifiedMassSpectrum &qualified_mass_spectrum)
{
  qDebug();
  if(qualified_mass_spectrum.getMsLevel() > 1)
    {
      mspectrum tandem_spectrum;
      // 20120906_balliau_extract_1_A01_urnb-1.mzxml scan 1825 (charge 3)

      qDebug();
      bool ok = true;
      tandem_spectrum.m_fI =
        (float)qualified_mass_spectrum.getPrecursorIntensity(&ok);
      if(!ok)
        {
          throw pappso::PappsoException(
            QObject::tr("missing precursor intensity"));
          // tandem_spectrum.m_fI = 1.0;
        }
      if(tandem_spectrum.m_fI == 0.0)
        tandem_spectrum.m_fI = 1.0;
      tandem_spectrum.m_fZ =
        (float)qualified_mass_spectrum.getPrecursorCharge(&ok);
      if(!ok)
        {
          throw pappso::PappsoException(
            QObject::tr("missing precursor charge"));
        }
      qDebug();
      // specCurrent.m_dMH = (specCurrent.m_dMH - dProton)*specCurrent.m_fZ +
      // dProton;
      tandem_spectrum.m_dMH = (qualified_mass_spectrum.getPrecursorMz(&ok) *
                               ((double)tandem_spectrum.m_fZ)) -
                              ((double)tandem_spectrum.m_fZ * pappso::MHPLUS) +
                              pappso::MHPLUS;
      qDebug();
      if(!ok)
        {
          throw pappso::PappsoException(QObject::tr("missing precursor mass"));
        }
      qDebug() << "tandem_spectrum.m_dMH="
               << QString::number(tandem_spectrum.m_dMH, 'f', 10);
      // PT564.357S
      tandem_spectrum.m_retentionTimeInSeconds =
        qualified_mass_spectrum.getRtInSeconds();
      /*
        tandem_spectrum.m_vdStats.clear();
        tandem_spectrum.m_vdStats.push_back(m_dSum);
        tandem_spectrum.m_vdStats.push_back(m_dMax);
        tandem_spectrum.m_vdStats.push_back(m_dFactor);
        */
      tandem_spectrum.m_strDescription =
        qualified_mass_spectrum.getMassSpectrumId().getNativeId().toStdString();
      tandem_spectrum.m_tId =
        qualified_mass_spectrum.getMassSpectrumId().getSpectrumIndex();

      //			specCurrent.m_strRt = strTemp.substr(tEquals+1,tSize-tEquals+1);
      //		specCurrent.m_strDescription += "RTINSECONDS=";


      // if(m_strActivation == "CID")	{
      // tandem_spectrum.m_strActivation = "CID";
      tandem_spectrum.m_uiType = 0;
      // tandem_spectrum.m_uiType = I_Y | I_B;
      //}
      // else if(m_strActivation == "ETD")	{
      //	m_specCurrent.m_uiType = I_C|I_Z;
      //}

      qDebug();
      mi tandem_point;
      const pappso::MassSpectrum *mass_spectrum_p =
        qualified_mass_spectrum.getMassSpectrumCstSPtr().get();
      if(mass_spectrum_p != nullptr)
        {
          for(auto &data_point : *mass_spectrum_p)
            {
              tandem_point.m_fM = (float)data_point.x;
              tandem_point.m_fI = (float)data_point.y;
              tandem_spectrum.m_vMI.push_back(tandem_point);
            }

          if(tandem_spectrum.m_fZ != 0.0 &&
             m_specCondition.condition(tandem_spectrum, *m_pScore))
            {
              qDebug() << mspectrumToString(tandem_spectrum);


              m_vSpectra.push_back(tandem_spectrum);
            }
        }
      qDebug();
    }
  qDebug();
}

void
LoadPappsoMsData::spectrumListHasSize(std::size_t size)
{
}
