/**
 * \file core/spoms/protein.h
 * \date 06/02/2026
 * \author Aurélien Berthier, BENOIST Emile, TESSIER Dominique
 * \brief Running specpeptidoms on one scan
 */


/*
 * PeptidOMS, Spectra to protein alignment tool
 * Copyright (C) 2026  Olivier Langella
 * <olivier.langella@cnrs.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 "location.h"
#include <pappsomspp/core/protein/protein.h>
#include "interpretationsaver.h"
#include "transformedspectrum.h"
#include "interpretationbackup.h"
#include "scenario.h"
#include "alignment.h"

namespace pappso
{
namespace spoms
{

/**
 * This class represents a protein with its sequence of amino acids, its name
 * and a description
 * @author 	BENOIST Emile, TESSIER Dominique
 *
 */

class Protein
{

  public:
  struct InterestCell
  {
    int row_number = 0;
    int score      = 0;
    int tree_id    = 0;
    int beginning  = 0;

    QString
    toString()
    {
      return QString("row: %1 score: %2 tree: %3 beginning: %4")
        .arg(row_number)
        .arg(score)
        .arg(tree_id)
        .arg(beginning);
    }
  };
  struct MemoryBuffer
  {
    MemoryBuffer(int column_count, int sequence_length)
    {
      interest_cells  = new InterestCell[column_count];
      scenario_buffer = new InterestCell[column_count];
      current_masses  = new double[sequence_length];
      trees_position  = new int[(sequence_length + 1) * (column_count + 1)];
    }
    ~MemoryBuffer()
    {
      delete[] interest_cells;
      delete[] scenario_buffer;
      delete[] current_masses;
      delete[] trees_position;
    }

    InterestCell *interest_cells  = nullptr; // column_count
    InterestCell *scenario_buffer = nullptr; // column_count
    double *current_masses        = nullptr; // sequence_length
    int *trees_position = nullptr; //(sequence_length + 1) * (column_count + 1)
  };

  public:
  /*
   * Creation d'une proteine à partir d'une "sequence" d'AAs (lettre en
   * majuscule). L'argument "reference" contient l'ensemble des informations sur
   * la proteine qui sont presentes dans le fichier et qui ne sont pas la
   * sequence.
   */
  /**
   * Constructor
   * @param sequence: the amino acids sequence
   * @param name: its name
   * @param reference: its reference
   */
  Protein(const pappso::AaCode &aaCode, pappso::ProteinSp protein_sp);

  Protein(const Protein &other);

  virtual ~Protein();

  const pappso::ProteinSp &getProteinSp() const;

  /**
   * Return the reference of the integer version of the protein sequence
   * @return protein sequence with integers
   */
  const std::vector<SpomsAa> &getSequence() const;


  std::vector<LocationBackup>
  preliminaryTreatmentV1(const TransformedSpectrum &transformed_spectrum,
                         const pappso::AaCode &aaCode,
                         int minimum_scenario_score,
                         const QJsonObject &score_grid) const;


  std::vector<LocationBackup>
  preliminaryTreatmentV1(MemoryBuffer &memory_buffer,
                         const TransformedSpectrum &transformed_spectrum,
                         const pappso::AaCode &aaCode,
                         int minimum_scenario_score,
                         const QJsonObject &score_grid) const;

  /** @brief final treatment for a protein selected by the 5 best protein
   * locations
   *
   * @fixme not completely implemented
   * This function launches a precise alignment + correction1 + post processing
   * + correction2
   * @return a pair containing the alignments after precise alignment +
   * correction1 and post-processing + correction2. Returns nullptr if no
   * alignment is obtained.
   */
  std::shared_ptr<Alignment> finalTreatment(
    std::shared_ptr<const TransformedSpectrum> transformed_spectrum_sp,
    const LocationBackup &location_backup,
    bool force_no_cleaning) const;

  /**
   * Return the integer version of the subsequence starting (resp. ending) at
   * position 'start' (resp. 'end'), both include
   * @param start: the beginning of the subsequence
   * @param end: the end of the subsequence
   * @return the integer subsequence
   */
  std::vector<SpomsAa> getSubSequence(int start, int end) const;

  /**
   * Return the amino acid at the position in parameter
   * @param position: the position in the sequence of the returned amino acid
   * @return the amino acid at the given position
   */
  const SpomsAa &getSpomsAa(int position);

  /**
   *
   * Return the string version of the subsequence starting (resp. ending) at
   * position 'start' (resp. 'end'), both include
   * @param start: the beginning of the subsequence
   * @param end: the end of the subsequence
   * @return the string subsequence
   */
  QString subSequence(int start, int end);

  private:
  private:
  InterpretationBackup
  preciseAlignment(const TransformedSpectrum &transformed_spectrum,
                   const Location &location,
                   std::vector<std::vector<Scenario>> &scenarios_matrice) const;


  private:
  double m_ACCURACY = 0.02;
  int m_NB_LOCATIONS_SAVED;
  pappso::ProteinSp msp_protein;
  /* @brief reversed protein sequence */
  std::vector<SpomsAa> m_sequence;
};

} // namespace spoms
} // namespace pappso
