/**
 * \file core/spoms/alignment.cpp
 * \date 18/02/2026
 * \author Aurélien Berthier, BENOIST Emile, TESSIER Dominique
 * \brief store alignment interpretations for precise alignment
 */


/*
 * 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/>.
 *
 */

#include <memory>
#include <pappsomspp/core/amino_acid/aa.h>
#include <pappsomspp/core/exception/exceptionnotimplemented.h>
#include <pappsomspp/core/types.h>
#include <qcontainerfwd.h>
#include <qlogging.h>
#include <qobject.h>
#include "alignment.h"
#include "locationbackup.h"
#include "peptidemodel.h"
#include "protein.h"
#include "spomsutils.h"

namespace pappso
{
namespace spoms
{

Alignment::Alignment(
  const InterpretationBackup &interpretation_backup,
  std::shared_ptr<const TransformedSpectrum> transformed_spectrum_sp,
  const std::vector<std::vector<Scenario>> &scenarios_matrice,
  const LocationBackup &location_backup)
{
  m_ms2accuracy = SpomsUtils::GetInstance()->getMs2Accuracy();
  m_score       = pappso::spoms::SpomsUtils::GetInstance()
              ->getParameterValue("alignment", "min_scenario_score")
              .toInt();
  m_nbPeaksInCommon         = -1;
  int current_line_number   = interpretation_backup.getLineNumber();
  int current_column_number = interpretation_backup.getColumnNumber();
  // Scenario current_scenario = new Scenario(current_line_number
  // ,current_column_number); this.scenarios = new ArrayList<Scenario>();
  // this.scenarios.add(current_scenario);
  Scenario current_scenario;
  m_scenarioList.push_back(current_scenario);

  m_scenarioList.at(0).update(current_line_number, current_column_number);
  int position = 1;
  while(current_column_number > 0)
    {
      current_scenario =
        scenarios_matrice.at(current_line_number).at(current_column_number);
      // this.scenarios.add(new Scenario(current_scenario));
      if(position >= (int)m_scenarioList.size())
        {
          m_scenarioList.push_back(current_scenario);
        }
      else
        {
          m_scenarioList.at(position).update(current_scenario);
        }
      current_line_number   = current_scenario.getPreviousLineNumber();
      current_column_number = current_scenario.getPreviousColumnNumber();
      ++position;
    }
  mcsp_transformedSpectrum = transformed_spectrum_sp;
  msp_locationList =
    std::make_shared<Location>(location_backup.mp_protein->getSequence(),
                               location_backup.start_line - 1,
                               location_backup.end_line - 1);
  msp_locationBackupList = std::make_shared<LocationBackup>(location_backup);
  m_score                = interpretation_backup.getScore();
  m_nbPeaksInCommon      = -1;
}

Alignment::Alignment(const Alignment &other [[maybe_unused]])
{
  throw pappso::ExceptionNotImplemented("no Alignment copy constructor");
}

Alignment::~Alignment()
{
}

const std::vector<Scenario> &
Alignment::getScenarios() const
{
  return m_scenarioList;
}

// public int[] getSequence() {return this.sequence;}

const std::shared_ptr<const TransformedSpectrum> &
Alignment::getTransformedSpectrum() const
{
  return mcsp_transformedSpectrum;
}

const std::shared_ptr<Location> &
Alignment::getLocation() const
{
  return msp_locationList;
}

const std::shared_ptr<LocationBackup> &
Alignment::getLocationBackup() const
{
  return msp_locationBackupList;
}

int
Alignment::getScore() const
{
  return m_score;
}

int
Alignment::getNBPeaksInCommon() const
{
  return m_nbPeaksInCommon;
}


std::vector<double>
Alignment::computePossibleNonAlignedMasses()
{
  /*
throw pappso::ExceptionNotImplemented(QObject::tr("not implemented %1 %2 %3")
                                        .arg(__FILE__)
                                        .arg(__FUNCTION__)
                                        .arg(__LINE__));
return std::vector<double>();
*/

  double last_shift;
  // ArrayList<Double> possible_non_aligned_masses = new ArrayList<Double>();
  m_possibleNonAlignedMassList.clear();
  m_possibleNonAlignedMassNterList.clear();
  m_possibleNonAlignedMassCterList.clear();
  int current_line_number    = m_scenarioList.at(0).getPreviousLineNumber();
  int current_column_number  = m_scenarioList.at(0).getPreviousColumnNumber();
  int previous_line_number   = m_scenarioList.at(1).getPreviousLineNumber();
  int previous_column_number = m_scenarioList.at(1).getPreviousColumnNumber();
  double shift =
    mcsp_transformedSpectrum.get()->getLastShift(current_column_number);
  bool found;
  if(shift > m_ms2accuracy &&
     current_line_number < msp_locationList.get()->getLength())
    {
      found = false;
      if(current_line_number + 1 < msp_locationList.get()->getLength())
        {
          int realignment_length = 2;
          double masses_sum =
            msp_locationList.get()->get(current_line_number).mass +
            msp_locationList.get()->get(current_line_number + 1).mass;
          while(current_line_number + realignment_length + 1 <=
                  msp_locationList.get()->getLength() &&
                shift - m_ms2accuracy > masses_sum)
            {
              masses_sum += msp_locationList.get()
                              ->get(current_line_number + realignment_length)
                              .mass;
              ++realignment_length;
            }
          if(current_line_number + realignment_length >
               msp_locationList.get()->getLength() ||
             std::abs(shift - masses_sum) > m_ms2accuracy)
            {
              found = true;
            }
        }
      else
        {
          found = true;
        }
      if(found) // nter
        {
          int line_expended = current_line_number;
          shift -= msp_locationList.get()->get(line_expended).mass;
          // while (shift > m_ms2accuracy)
          while(shift > -pappso::MPROTIUM - m_ms2accuracy)
            {
              // possible_non_aligned_masses.add(shift);
              m_possibleNonAlignedMassNterList.push_back(shift);
              ++line_expended;
              if(line_expended == msp_locationList.get()->getLength())
                {
                  // shift = -1.0;
                  shift = -pappso::MPROTIUM - m_ms2accuracy - 1.0;
                }
              else
                {
                  shift -= msp_locationList.get()->get(line_expended).mass;
                }
            }
          if(m_possibleNonAlignedMassNterList.size() > 0)
            {
              last_shift = m_possibleNonAlignedMassNterList.at(
                m_possibleNonAlignedMassNterList.size() - 1);
              if(std::abs(last_shift - pappso::MPROTIUM) <= m_ms2accuracy ||
                 std::abs(-last_shift - pappso::MPROTIUM) <= m_ms2accuracy)
                {
                  m_possibleNonAlignedMassNterList.clear();
                  m_possibleNonAlignedMassNterList.push_back(last_shift);
                }
              else if(last_shift < 0.0)
                {
                  m_possibleNonAlignedMassNterList.erase(
                    m_possibleNonAlignedMassNterList.begin() +
                    m_possibleNonAlignedMassNterList.size() - 1);
                }
            }
        }
    }
  int counter = 2;
  while(previous_column_number > 0)
    {
      double mass_sum = 0.0;
      for(int j = current_line_number - 1; j > previous_line_number; --j)
        {
          mass_sum += msp_locationList.get()->get(j - 1).mass;
        }

      shift = mcsp_transformedSpectrum.get()->getShift(
        previous_column_number,
        current_column_number,
        msp_locationList.get()->get(current_line_number - 1).mass);
      if(shift - mass_sum > m_ms2accuracy)
        {
          m_possibleNonAlignedMassList.push_back(shift - mass_sum);
        }
      current_line_number   = previous_line_number;
      current_column_number = previous_column_number;
      if(previous_column_number > 0)
        {
          previous_line_number =
            m_scenarioList.at(counter).getPreviousLineNumber();
          previous_column_number =
            m_scenarioList.at(counter).getPreviousColumnNumber();
          ++counter;
        }
    }
  if(current_line_number == previous_line_number + 1)
    {
      shift = mcsp_transformedSpectrum.get()->getShift(
        previous_column_number,
        current_column_number,
        msp_locationList.get()->get(current_line_number - 1).mass);
      if(std::abs(shift) > m_ms2accuracy && current_line_number > 1) // cter
        {
          int line_expended = current_line_number - 2;
          shift -= msp_locationList.get()->get(line_expended).mass;
          // while (shift > m_ms2accuracy)
          while(shift > -pappso::MPROTIUM - m_ms2accuracy)
            {
              // possible_non_aligned_masses.add(shift);
              m_possibleNonAlignedMassCterList.push_back(shift);
              --line_expended;
              if(line_expended < 0)
                {
                  // shift = -1.0;
                  shift = -pappso::MPROTIUM - m_ms2accuracy - 1.0;
                }
              else
                {
                  shift -= msp_locationList.get()->get(line_expended).mass;
                }
            }
          if(m_possibleNonAlignedMassCterList.size() > 0)
            {
              last_shift = m_possibleNonAlignedMassCterList.at(
                m_possibleNonAlignedMassCterList.size() - 1);
              if(std::abs(last_shift - pappso::MPROTIUM) <= m_ms2accuracy ||
                 std::abs(-last_shift - pappso::MPROTIUM) <= m_ms2accuracy)
                {
                  m_possibleNonAlignedMassCterList.clear();
                  m_possibleNonAlignedMassCterList.push_back(last_shift);
                }
              else if(last_shift < 0.0)
                {
                  m_possibleNonAlignedMassCterList.erase(
                    m_possibleNonAlignedMassCterList.begin() +
                    m_possibleNonAlignedMassCterList.size() - 1);
                }
            }
        }
    }
  m_possibleNonAlignedMassList.insert(m_possibleNonAlignedMassList.end(),
                                      m_possibleNonAlignedMassNterList.begin(),
                                      m_possibleNonAlignedMassNterList.end());
  m_possibleNonAlignedMassList.insert(m_possibleNonAlignedMassList.end(),
                                      m_possibleNonAlignedMassCterList.begin(),
                                      m_possibleNonAlignedMassCterList.end());
  return m_possibleNonAlignedMassList;
}

QStringList
Alignment::computeHitModifiedAndRealSequence() const
{

  /*
    throw pappso::ExceptionNotImplemented(QObject::tr("not implemented %1 %2
    %3") .arg(__FILE__) .arg(__FUNCTION__) .arg(__LINE__));
                                            */
  // String hits_modified = "";
  // String real_sequence = "";
  // StringBuilder hits_modified2 = new StringBuilder();
  // StringBuilder real_sequence2 = new StringBuilder();
  // StringBuilder not_found_plus_shift2 = new StringBuilder();
  //

  QString hits_modified2;
  QString real_sequence2;
  // DecimalFormat DECIMAL_FORMAT = new DecimalFormat("0.00");
  Scenario current_scenario  = m_scenarioList.at(0);
  int current_line_number    = current_scenario.getPreviousLineNumber();
  int current_column_number  = current_scenario.getPreviousColumnNumber();
  current_scenario           = m_scenarioList.at(1);
  int previous_line_number   = current_scenario.getPreviousLineNumber();
  int previous_column_number = current_scenario.getPreviousColumnNumber();
  double shift =
    mcsp_transformedSpectrum.get()->getLastShift(current_column_number);
  if(shift > m_ms2accuracy)
    {
      if(current_line_number + 1 < msp_locationList.get()->getLength())
        {
          int realignment_length = 2;
          double masses_sum =
            msp_locationList.get()->get(current_line_number).mass +
            msp_locationList.get()->get(current_line_number + 1).mass;
          while(current_line_number + realignment_length + 1 <=
                  msp_locationList.get()->getLength() &&
                shift - m_ms2accuracy > masses_sum)
            {
              masses_sum += msp_locationList.get()
                              ->get(current_line_number + realignment_length)
                              .mass;
              ++realignment_length;
            }
          if(current_line_number + realignment_length <=
               msp_locationList.get()->getLength() &&
             std::abs(shift - masses_sum) <= m_ms2accuracy)
            {
              // hits_modified = String.format("[%c]",
              // AminoAcid.getLetter(this.location.get(current_line_number +
              // realignment_length - 1))); real_sequence =
              //  Character.toString(AminoAcid.getLetter(this.location.get(current_line_number
              // + realignment_length - 1)));
              hits_modified2.append('[');
              hits_modified2.append(
                (char)msp_locationList.get()
                  ->get(current_line_number + realignment_length - 1)
                  .aa);
              hits_modified2.append(']');
              real_sequence2.append(
                (char)msp_locationList.get()
                  ->get(current_line_number + realignment_length - 1)
                  .aa);
              --realignment_length;
              for(; realignment_length > 0; --realignment_length)
                {
                  // hits_modified = String.format("%s[%c]", hits_modified,
                  // AminoAcid.getLetter(this.location.get(current_line_number
                  // + realignment_length - 1))); real_sequence =
                  // String.format("%s%c", real_sequence,
                  // AminoAcid.getLetter(this.location.get(current_line_number
                  // + realignment_length - 1)));
                  hits_modified2.append('[');
                  hits_modified2.append(
                    (char)msp_locationList.get()
                      ->get(current_line_number + realignment_length - 1)
                      .aa);
                  hits_modified2.append(']');
                  real_sequence2.append(
                    (char)msp_locationList.get()
                      ->get(current_line_number + realignment_length - 1)
                      .aa);
                }
            }
          else
            {
              // hits_modified = String.format("[%s]",
              // DECIMAL_FORMAT.format(shift));
              hits_modified2.append('[');
              hits_modified2.append(QString::number(shift, 'f', 2));
              hits_modified2.append(']');
            }
        }
      else
        {
          // hits_modified = String.format("[%s]",
          // DECIMAL_FORMAT.format(shift));
          hits_modified2.append('[');
          hits_modified2.append(QString::number(shift, 'f', 2));
          hits_modified2.append(']');
        }
    }
  int counter = 2;
  while(current_column_number > 0)
    {
      // hits_modified = String.format("%s%c", hits_modified,
      // AminoAcid.getLetter(this.location.get(current_line_number - 1)));
      // real_sequence = String.format("%s%c", real_sequence,
      // AminoAcid.getLetter(this.location.get(current_line_number - 1)));
      hits_modified2.append(
        (char)msp_locationList.get()->get(current_line_number - 1).aa);
      real_sequence2.append(
        (char)msp_locationList.get()->get(current_line_number - 1).aa);
      // String not_found_plus_shift = "";
      QString not_found_plus_shift2;
      double mass_sum = 0.0;
      for(int j = current_line_number - 1; j > previous_line_number; --j)
        {
          mass_sum += msp_locationList.get()->get(j - 1).mass;
          // not_found_plus_shift = String.format("%s[%c]",
          // not_found_plus_shift, AminoAcid.getLetter(this.location.get(j -
          // 1)));
          not_found_plus_shift2.append('[');
          not_found_plus_shift2.append(
            (char)msp_locationList.get()->get(j - 1).aa);
          not_found_plus_shift2.append(']');
          // real_sequence = String.format("%s%c", real_sequence,
          // AminoAcid.getLetter(this.location.get(j - 1)));
          real_sequence2.append((char)msp_locationList.get()->get(j - 1).aa);
        }
      // hits_modified = hits_modified.concat(not_found_plus_shift);
      hits_modified2.append(not_found_plus_shift2);

      shift = mcsp_transformedSpectrum.get()->getShift(
        previous_column_number,
        current_column_number,
        msp_locationList.get()->get(current_line_number - 1).mass);
      if(std::abs(shift - mass_sum) > m_ms2accuracy)
        {
          // hits_modified = String.format("%s[%s]", hits_modified,
          // DECIMAL_FORMAT.format(shift - mass_sum));
          hits_modified2.append('[');
          hits_modified2.append(QString::number((shift - mass_sum), 'f', 2));
          hits_modified2.append(']');
        }
      current_line_number   = previous_line_number;
      current_column_number = previous_column_number;
      if(previous_column_number > 0)
        {
          current_scenario       = m_scenarioList.at(counter);
          previous_line_number   = current_scenario.getPreviousLineNumber();
          previous_column_number = current_scenario.getPreviousColumnNumber();
          ++counter;
        }
    }
  // String[] res = {hits_modified, real_sequence};
  QStringList res;
  res << hits_modified2;
  res << real_sequence2;
  return res;
}


void
pappso::spoms::Alignment::computeNbPeaksInCommon()
{
  if(m_nbPeaksInCommon == -1)
    {
      m_nbPeaksInCommon       = 0;
      int current_line_number = m_scenarioList.at(0).getPreviousLineNumber();
      int current_column_number =
        m_scenarioList.at(0).getPreviousColumnNumber();
      int previous_line_number = m_scenarioList.at(1).getPreviousLineNumber();
      int previous_column_number =
        m_scenarioList.at(1).getPreviousColumnNumber();
      double shift =
        mcsp_transformedSpectrum.get()->getLastShift(current_column_number);
      double masses_sum;
      int realignment_length;
      if(shift > m_ms2accuracy)
        {
          if(current_line_number + 1 < msp_locationList.get()->getLength())
            {
              realignment_length = 2;
              masses_sum =
                msp_locationList.get()->get(current_line_number).mass +
                msp_locationList.get()->get(current_line_number + 1).mass;
              while(current_line_number + realignment_length + 1 <=
                      msp_locationList.get()->getLength() &&
                    abs(shift - masses_sum) > m_ms2accuracy)
                {
                  masses_sum +=
                    msp_locationList.get()
                      ->get(current_line_number + realignment_length)
                      .mass;
                  ++realignment_length;
                }
              if(current_line_number + realignment_length <=
                   msp_locationList.get()->getLength() &&
                 abs(shift - masses_sum) <= m_ms2accuracy)
                {
                  ++m_nbPeaksInCommon;
                  masses_sum = mcsp_transformedSpectrum.get()->getColumnMass(
                    mcsp_transformedSpectrum.get()->getColumnCount() - 1);
                  for(; realignment_length > 1; --realignment_length)
                    {
                      masses_sum -=
                        msp_locationList.get()
                          ->get(current_line_number - 1 + realignment_length)
                          .mass;
                      m_nbPeaksInCommon +=
                        mcsp_transformedSpectrum.get()->massCount(masses_sum);
                    }
                }
            }
        }
      int counter = 2;
      while(previous_column_number > 0)
        {
          if(mcsp_transformedSpectrum.get()->isDoubleColumn(
               current_column_number))
            {
              m_nbPeaksInCommon += 2;
            }
          else
            {
              ++m_nbPeaksInCommon;
            }

          shift = mcsp_transformedSpectrum.get()->getShift(
            previous_column_number,
            current_column_number,
            msp_locationList.get()->get(current_line_number - 1).mass);
          if(shift > m_ms2accuracy)
            {
              masses_sum = 0.0;
              for(int j = current_line_number - 1; j > previous_line_number;
                  --j)
                {
                  masses_sum += msp_locationList.get()->get(j - 1).mass;
                }
              m_nbPeaksInCommon += mcsp_transformedSpectrum.get()->massCount(
                mcsp_transformedSpectrum.get()->getColumnMass(
                  current_column_number) -
                msp_locationList.get()->get(current_line_number - 1).mass);
              if(abs(shift - masses_sum) <= m_ms2accuracy)
                {
                  masses_sum = mcsp_transformedSpectrum.get()->getColumnMass(
                    previous_column_number);

                  for(realignment_length = 1;
                      realignment_length <
                      current_line_number - previous_line_number - 1;
                      ++realignment_length)
                    {
                      masses_sum +=
                        msp_locationList.get()
                          ->get(previous_line_number - 1 + realignment_length)
                          .mass;
                      m_nbPeaksInCommon +=
                        mcsp_transformedSpectrum.get()->massCount(masses_sum);
                    }
                }
            }

          current_line_number   = previous_line_number;
          current_column_number = previous_column_number;
          if(previous_column_number > 0)
            {
              previous_line_number =
                m_scenarioList.at(counter).getPreviousLineNumber();
              previous_column_number =
                m_scenarioList.at(counter).getPreviousColumnNumber();
              ++counter;
            }
        }
      if(mcsp_transformedSpectrum.get()->isDoubleColumn(current_column_number))
        {
          m_nbPeaksInCommon += 2;
        }
      else
        {
          ++m_nbPeaksInCommon;
        }

      shift = mcsp_transformedSpectrum.get()->getShift(
        previous_column_number,
        current_column_number,
        msp_locationList.get()->get(current_line_number - 1).mass);
      if(shift > m_ms2accuracy)
        {
          masses_sum = 0.0;
          for(int j = current_line_number - 1; j > previous_line_number; --j)
            {
              masses_sum += msp_locationList.get()->get(j - 1).mass;
            }
          m_nbPeaksInCommon += mcsp_transformedSpectrum.get()->massCount(
            mcsp_transformedSpectrum.get()->getColumnMass(
              current_column_number) -
            msp_locationList.get()->get(current_line_number - 1).mass);
          if(abs(shift - masses_sum) <= m_ms2accuracy)
            {
              ++m_nbPeaksInCommon;
              masses_sum = mcsp_transformedSpectrum.get()->getColumnMass(
                previous_column_number);

              for(realignment_length = 1;
                  realignment_length <
                  current_line_number - previous_line_number - 1;
                  ++realignment_length)
                {
                  masses_sum +=
                    msp_locationList.get()
                      ->get(previous_line_number - 1 + realignment_length)
                      .mass;
                  m_nbPeaksInCommon +=
                    mcsp_transformedSpectrum.get()->massCount(masses_sum);
                }
            }
        }
      else
        {
          ++m_nbPeaksInCommon;
        }
    }
}

bool
Alignment::compareTo(Alignment &other)
{
  if(m_score > other.getScore())
    {
      return false;
    }
  else if(m_score < other.m_score)
    {
      return true;
    }
  else
    {
      computeNbPeaksInCommon();
      other.computeNbPeaksInCommon();
      if(m_nbPeaksInCommon < other.getNBPeaksInCommon())
        {
          return true;
        }
      else
        {
          return false;
        }
    }
}

bool
Alignment::compareToPostProcessing(Alignment &other)
{
  qDebug() << m_score << " / " << other.getScore();
  if(m_score > other.getScore())
    {
      return false;
    }
  else
    {
      computeNbPeaksInCommon();
      other.computeNbPeaksInCommon();
      if(m_nbPeaksInCommon < other.getNBPeaksInCommon())
        {
          return true;
        }
      else
        {
          return false;
        }
    }
}

const std::shared_ptr<PeptideModel>
Alignment::getPeptideModel() const
{
  std::shared_ptr<PeptideModel> peptide_model =
    std::make_shared<PeptideModel>();
  peptide_model.get()->setPrecursorMass(
    mcsp_transformedSpectrum.get()->getPrecursorMass());
  AminoAcidModel aa_model;
  Scenario current_scenario  = m_scenarioList.at(0);
  int current_line_number    = current_scenario.getPreviousLineNumber();
  int current_column_number  = current_scenario.getPreviousColumnNumber();
  current_scenario           = m_scenarioList.at(1);
  int previous_line_number   = current_scenario.getPreviousLineNumber();
  int previous_column_number = current_scenario.getPreviousColumnNumber();
  double shift =
    mcsp_transformedSpectrum.get()->getLastShift(current_column_number);
  if(shift > m_ms2accuracy)
    {
      if(current_line_number + 1 < msp_locationList.get()->getLength())
        {
          int realignment_length = 2;
          double masses_sum =
            msp_locationList.get()->get(current_line_number).mass +
            msp_locationList.get()->get(current_line_number + 1).mass;
          while(current_line_number + realignment_length + 1 <=
                  msp_locationList.get()->getLength() &&
                shift - m_ms2accuracy > masses_sum)
            {
              masses_sum += msp_locationList.get()
                              ->get(current_line_number + realignment_length)
                              .mass;
              ++realignment_length;
            }
          if(current_line_number + realignment_length <=
               msp_locationList.get()->getLength() &&
             std::abs(shift - masses_sum) <= m_ms2accuracy)
            {
              aa_model.m_aminoAcid =
                msp_locationList.get()
                  ->get(current_line_number + realignment_length - 1)
                  .aa;
              aa_model.m_massDifference = 0;
              aa_model.m_skipped        = true;
              peptide_model.get()->push_back(aa_model);
              --realignment_length;
              for(; realignment_length > 0; --realignment_length)
                {
                  aa_model.m_aminoAcid =
                    msp_locationList.get()
                      ->get(current_line_number + realignment_length - 1)
                      .aa;
                  aa_model.m_massDifference = 0;
                  aa_model.m_skipped        = true;
                  peptide_model.get()->push_back(aa_model);
                }
            }
          else
            {
              peptide_model.get()->setNterShift(shift);
            }
        }
      else
        {
          peptide_model.get()->setNterShift(shift);
        }
    }
  int counter = 2;
  while(current_column_number > 0)
    {
      aa_model.m_aminoAcid =
        msp_locationList.get()->get(current_line_number - 1).aa;
      aa_model.m_massDifference = 0;
      aa_model.m_skipped        = false;
      peptide_model.get()->push_back(aa_model);
      QString not_found_plus_shift2;
      double mass_sum = 0.0;
      for(int j = current_line_number - 1; j > previous_line_number; --j)
        {
          mass_sum += msp_locationList.get()->get(j - 1).mass;
          aa_model.m_aminoAcid      = msp_locationList.get()->get(j - 1).aa;
          aa_model.m_massDifference = 0;
          aa_model.m_skipped        = true;
          peptide_model.get()->push_back(aa_model);
        }

      shift = mcsp_transformedSpectrum.get()->getShift(
        previous_column_number,
        current_column_number,
        msp_locationList.get()->get(current_line_number - 1).mass);
      if(std::abs(shift - mass_sum) > m_ms2accuracy)
        {
          aa_model.m_massDifference = shift - mass_sum;
          aa_model.m_skipped        = false;
          peptide_model.get()->push_back(aa_model);
        }
      current_line_number   = previous_line_number;
      current_column_number = previous_column_number;
      if(previous_column_number > 0)
        {
          current_scenario       = m_scenarioList.at(counter);
          previous_line_number   = current_scenario.getPreviousLineNumber();
          previous_column_number = current_scenario.getPreviousColumnNumber();
          ++counter;
        }
    }
  return peptide_model;
}

double
Alignment::getNonAlignedMass() const
{
  return mcsp_transformedSpectrum.get()->getNonAlignedMass();
}

} // namespace spoms
} // namespace pappso
