/**
 * \file pappsomspp/msrun/private/timsmsrunreaderbase.cpp
 * \date 15/07/2024
 * \author Olivier Langella
 * \brief Base class for all tims ms run reader objects
 */

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

#include "pappsomspp/core/msrun/private/timsmsrunreaderbase.h"
#include "pappsomspp/core/exception/exceptionnotimplemented.h"
#include "pappsomspp/core/exception/exceptioninterrupted.h"
#include <QDebug>
#include "../../obo/obopsims.h"
#include "../../obo/filterobopsimodmap.h"

namespace pappso
{
TimsMsRunReaderBase::TimsMsRunReaderBase(MsRunIdCstSPtr &msrun_id_csp) : MsRunReader(msrun_id_csp)
{
  initialize();
}

TimsMsRunReaderBase::TimsMsRunReaderBase(const TimsMsRunReaderBase &msrun_reader_base)
  : MsRunReader(msrun_reader_base.getMsRunId()), msp_timsData(msrun_reader_base.msp_timsData)
{
  initialize();
}


TimsMsRunReaderBase::~TimsMsRunReaderBase()
{

  msp_timsData = nullptr;
}

void
TimsMsRunReaderBase::initialize()
{
  if(msp_timsData == nullptr)
    msp_timsData = std::make_shared<TimsData>(mcsp_msRunId.get()->getFileName());

  if(msp_timsData.get() == nullptr)
    {
      throw PappsoException(QObject::tr("ERROR in TimsMsRunReaderBase::initialize "
                                        "msp_timsData is null for MsRunId %1")
                              .arg(mcsp_msRunId.get()->toString()));
    }
}


bool
TimsMsRunReaderBase::accept(const QString &file_name) const
{
  qDebug() << file_name;
  return true;
}

bool
TimsMsRunReaderBase::hasScanNumbers() const
{
  return false;
}


bool
TimsMsRunReaderBase::releaseDevice()
{
  msp_timsData = nullptr;
  return true;
}

bool
TimsMsRunReaderBase::acquireDevice()
{
  if(msp_timsData == nullptr)
    {
      initialize();
    }
  return true;
}

TimsDataSp
TimsMsRunReaderBase::getTimsDataSPtr()
{
  acquireDevice();
  return msp_timsData;
}


Trace
TimsMsRunReaderBase::getTicChromatogram()
{
  // Use the Sqlite database to fetch the total ion current chromatogram (TIC
  // chromatogram).

  acquireDevice();

  // The time unit here is seconds, not minutes!!!
  return msp_timsData->getTicChromatogram();
}


std::vector<double>
pappso::TimsMsRunReaderBase::getRetentionTimeLine()
{
  return msp_timsData.get()->getRetentionTimeLineInSeconds();
}


XicCoordSPtr
TimsMsRunReaderBase::newXicCoordSPtrFromSpectrumIndex(std::size_t spectrum_index [[maybe_unused]],
                                                      pappso::PrecisionPtr precision
                                                      [[maybe_unused]]) const
{
  throw ExceptionNotImplemented(
    QObject::tr("Not implemented %1 %2 %3").arg(__FILE__).arg(__FUNCTION__).arg(__LINE__));
}

XicCoordSPtr
TimsMsRunReaderBase::newXicCoordSPtrFromQualifiedMassSpectrum(
  const pappso::QualifiedMassSpectrum &mass_spectrum [[maybe_unused]],
  pappso::PrecisionPtr precision [[maybe_unused]]) const
{
  throw ExceptionNotImplemented(
    QObject::tr("Not implemented %1 %2 %3").arg(__FILE__).arg(__FUNCTION__).arg(__LINE__));
}


} // namespace pappso

const pappso::OboPsiModTerm
pappso::TimsMsRunReaderBase::getOboPsiModTermInstrumentModelName() const
{

  pappso::FilterOboPsiModMap psims_map;

  pappso::OboPsiMs psims_file(psims_map);

  pappso::OboPsiModTerm term;

  term = psims_map.getOboPsiModTermWithAccession("MS:1003123");
  /*
   * [Term]
  id: MS:1003123
  name: Bruker Daltonics timsTOF series
  def: "Bruker Daltonics timsTOF series" [PSI:MS]
  is_a: MS:1000122 ! Bruker Daltonics instrument model
  */
  /*
   *
[Term]
id: MS:1003124
name: timsTOF fleX
def: "Bruker Daltonics' timsTOF fleX" [PSI:MS]
is_a: MS:1003123 ! Bruker Daltonics timsTOF series

[Term]
id: MS:1003229
name: timsTOF
def: "Bruker Daltonics' timsTOF." [PSI:MS]
is_a: MS:1003123 ! Bruker Daltonics timsTOF series

[Term]
id: MS:1003230
name: timsTOF Pro 2
def: "Bruker Daltonics' timsTOF Pro 2." [PSI:MS]
is_a: MS:1003123 ! Bruker Daltonics timsTOF series

[Term]
id: MS:1003231
name: timsTOF SCP
def: "Bruker Daltonics' timsTOF SCP." [PSI:MS]
is_a: MS:1003123 ! Bruker Daltonics timsTOF series

[Term]
id: MS:1003383
name: timsTOF Ultra
def: "Bruker Daltonics' timsTOF Ultra." [PSI:MS]
is_a: MS:1003123 ! Bruker Daltonics timsTOF series


[Term]
id: MS:1003397
name: timsTOF fleX MALDI-2
def: "Bruker Daltonics' timsTOF fleX MALDI-2." [PSI:MS]
is_a: MS:1003123 ! Bruker Daltonics timsTOF series


[Term]
id: MS:1003404
name: timsTOF HT
def: "Bruker Daltonics' timsTOF HT." [PSI:MS]
is_a: MS:1003123 ! Bruker Daltonics timsTOF series


[Term]
id: MS:1003412
name: timsTOF Ultra 2
def: "Bruker Daltonics timsTOF Ultra 2." [PSI:MS]
is_a: MS:1003123 ! Bruker Daltonics timsTOF series
*/
  QStringList timstof_list;
  timstof_list << "MS:1003005"
               << "MS:1003412"
               << "MS:1003404"
               << "MS:1003397"
               << "MS:1003383"
               << "MS:1003231"
               << "MS:1003230"
               << "MS:1003229"
               << "MS:1003124";

  QString instrument_name = msp_timsData.get()->getGlobalMetadataValue("InstrumentName").toString();

  for(auto &accession : timstof_list)
    {
      pappso::OboPsiModTerm test_term = psims_map.getOboPsiModTermWithAccession(accession);
      if(test_term.m_name == instrument_name)
        {
          term = test_term;
          break;
        }
    }
  return term;
}
