/**
 * \file core/spoms/aaposition.h
 * \date 11/02/2026
 * \author Aurélien Berthier, BENOIST Emile, TESSIER Dominique
 * \brief handle processed spectrum
 */


/*
 * 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 <QString>
#include <cstdint>

namespace pappso
{
namespace spoms
{
/*
 * Contient toutes les informations liées à la présence d'un AA dans un spectre.
 * "right_column" et "left_column" correspondent respectivement aux colonnes
 * formant le pic de droite et le pic de gauche de l'AA.
 *
 * "condition" est un
 * attribut utilise dans la version 3peaks (voir la methode
 * "runOneRealignmentThreePeaksVersion" de "SpecGlobThread"). Il s'agit d'un
 * entier sur 32 bits dont les 24 premiers bits sont utilises comme des
 * booleens. Les 22 derniers bits correspondent aux 22 AAs possible. En appelant
 * 'X', l'AA correspondant a un objet "AAPosition", tout AA 'Y' precedant 'X'
 * dans le spectre voit sont bit correspondant dans "condition" mit a 1. Les
 * autres sont mis a 0. Si plusieurs AAs precedent 'X', c'est qu'ils sont tous
 * situe juste avant lui (ils ne forment pas une grande sequence mais plusieurs
 * sequences de taille 2). Les 2 premiers bits sont utilises lorsque 'X' n'est
 * precede d'aucun AA. Soit dans le cas ou 'X' est situe au debut du spectre,
 * auquel cas, le deuxieme bit est mit a 1 (les autres a 0), soit parce qu'il
 * n'est simplement pas precede par un autre AA, auquel cas le premier bit est
 * mit a 1 (les autres a 0). L'objectif de cela est de facilement pouvoir
 * determiner si un AA d'une proteine doit etre considere s'il est present dans
 * le spectre, en fonction de l'AA precedent dans la proteine et de cette
 * "condition". L'acide amine est concidere dans 2 cas :
 *  - le bit correspondant a l'AA precedent dans la protein est a 1 (impossible
 * au debut de la proteine)
 *  - l'un des 2 premier bit est a 1
 *  Pour verifier ces conditions, il suffit de faire un 'et bit a bit' entre
 * "condition" et un entier 32 bits avec les 2 premier bits a 1 et un 1 sur le
 * bit correspondant a l'AA precedent dans la proteine (si il y en a un). Si le
 * resultat de cette operation est 0, alors il ne faut pas conciderer l'AA,
 * sinon, il doit l'etre. Les fait de distinguer le cas ou l'AA se trouve au
 * debut de spectre et le cas ou il ne l'est pas et qu'il n'est pas precede par
 * un AA dans le spectre est utile pour autre chose.
 */
class AAPosition
{


  public:
  AAPosition();

  AAPosition(const AAPosition &other);

  AAPosition &operator=(const AAPosition &other);

  virtual ~AAPosition();

  AAPosition(int right_column,
             int left_column,
             int right_peak,
             int left_peak,
             double right_mass,
             double left_mass);


  int getRightPeak() const;

  int getLeftPeak() const;

  int getRightColumn() const;

  int getLeftColumn() const;

  std::uint32_t getCondition() const;

  void setCondition(std::uint32_t condition);

  /*
   * Les colonnes attribues a l'AAPosition en premier lieu ont le meme numero
   * que leur pic correspondant. Etant donne que certaines colonnes sont
   * supprimees juste apres, il est necessaire de reattribuer un numero aux
   * colonnes de maniere a ce que les numeros se suivent. Cette methode met a
   * jour les numeros des colonnes de l'AAPosition.
   */
  void updateColumn(const std::vector<int> &column_correspondance);

  QString toString() const;

  double getLeftMass() const;
  double getRightMass() const;


  public:
  // static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("0.00");

  int right_column;
  int left_column;
  int left_peak;
  int right_peak;
  double right_mass;
  double left_mass;
  std::uint32_t condition = 0;
};


} // namespace spoms
} // namespace pappso
