/**
 * \file core/runningspoms.h
 * \date 20/02/2026
 * \author Olivier Langella
 * \brief Running spoms
 */


/*
 * PeptidOMS, Spectra to protein alignment tool
 * Copyright (C) 2025  Olivier Langella
 * <olivier.langella@universite-paris-saclay.fr>
 *
 * This program 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 program 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 program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */


#pragma once

#include <QJsonObject>
#include <QFileInfo>
#include <memory>
#include <pappsomspp/core/processing/uimonitor/uimonitorinterface.h>
#include <pappsomspp/core/msrun/spectrumcollectionhandlerinterface.h>
#include <pappsomspp/core/processing/cbor/cborstreamwriter.h>
#include <pappsomspp/core/amino_acid/aacode.h>
#include <pappsomspp/core/fasta/fastahandlerinterface.h>
#include <pappsomspp/core/protein/protein.h>
#include "../output/peptidomscboroutput.h"
#include "core/onescanprocessspoms.h"
#include "core/spoms/protein_list.h"
/**
 * @todo write docs
 */
class RunningSpoms
{
  friend OneScanProcessSpoms;

  public:
  /**
   * Default constructor
   */
  RunningSpoms(pappso::UiMonitorInterface &monitor,
               const QJsonObject &json_params);

  /**
   * Destructor
   */
  virtual ~RunningSpoms();

  void run(pappso::MsRunReaderSPtr msrun_reader,
           const std::vector<QFileInfo> &fasta_fileinfo_list,
           pappso::cbor::CborStreamWriter *p_cbor_stream_writer);

  private:
  class FastaSeqHandler : public pappso::FastaHandlerInterface
  {
    public:
    FastaSeqHandler(RunningSpoms *p_parent)
    {
      mp_parent = p_parent;
    }
    void
    setSequence(const QString &description_in,
                const QString &sequence_in) override
    {
      QString sequence = sequence_in.trimmed().simplified();
      if(!sequence.contains("X") && !sequence.contains("U"))
        {
          mp_parent->mpa_proteinList->addProtein(
            std::make_shared<pappso::Protein>(description_in, sequence));
        }
    };

    private:
    RunningSpoms *mp_parent;
  };

  class SpectrumCollectionHandler
    : public pappso::SpectrumCollectionHandlerInterface
  {
    public:
    SpectrumCollectionHandler(RunningSpoms *p_parent,
                              pappso::UiMonitorInterface &monitor)
      : m_monitor(monitor)
    {
      mp_parent = p_parent;
    }
    virtual ~SpectrumCollectionHandler() {};

    virtual void setQualifiedMassSpectrum(
      const pappso::QualifiedMassSpectrum &spectrum) override;

    virtual bool
    needPeakList() const override
    {
      return true;
    };

    private:
    pappso::UiMonitorInterface &m_monitor;
    RunningSpoms *mp_parent;
  };

  void loadProteinList(const QFileInfo &fasta_file_info);

  void processScanResultArray();

  void onOneScanProcessSpomsStarted(std::size_t spectrum_index);
  void onOneScanProcessSpomsFinished(std::size_t spectrum_index);

  private:
  pappso::UiMonitorInterface &m_monitor;
  pappso::PrecisionPtr m_fragmentTolerance;
  double m_minimumMz;
  std::size_t m_nMostIntense;
  bool m_deisotope = true;
  pappso::AaCode m_aaCode;
  pappso::spoms::ProteinList *mpa_proteinList;

  PeptidOmsCborOutput *mpa_spomsCborOutput = nullptr;

  std::vector<OneScanProcessSpoms *> m_scanResultArray;


  std::vector<std::size_t> m_runningSpectrumStack;

  std::size_t m_countScanFinished = 0;

  QMutex m_mutex;
};
