/* BEGIN software license
 *
 * msXpertSuite - mass spectrometry software suite
 * -----------------------------------------------
 * Copyright(C) 2009,...,2026 Filippo Rusconi
 *
 * http://www.msxpertsuite.org
 *
 * This file is part of the msXpertSuite project.
 *
 * The msXpertSuite project is the successor of the massXpert project. This
 * project now includes various independent modules:
 *
 * - massXpert, model polymer chemistries and simulate mass spectrometric data;
 * - mineXpert, a powerful TIC chromatogram/mass spectrum viewer/miner;
 *
 * 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/>.
 *
 * END software license
 */


/////////////////////// StdLib includes
#include <cmath>


/////////////////////// Qt includes
#include <QDebug>
#include <QThread>


/////////////////////// pappsomspp includes


/////////////////////// Local includes
#include "TicChromTreeNodeCombinerVisitor.hpp"

namespace MsXpS
{
namespace MineXpert
{


TicChromTreeNodeCombinerVisitor::TicChromTreeNodeCombinerVisitor(
  MsRunDataSetCstSPtr ms_run_data_set_csp,
  const ProcessingFlow &processing_flow,
  QObject *parent)
  : BaseMsRunDataSetTreeNodeVisitor(
      ms_run_data_set_csp, processing_flow, parent)
{
}

TicChromTreeNodeCombinerVisitor::~TicChromTreeNodeCombinerVisitor()
{
  // qDebug();
}

BaseMsRunDataSetTreeNodeVisitor *
TicChromTreeNodeCombinerVisitor::clone(QObject *parent) const
{
  TicChromTreeNodeCombinerVisitor *copy = new TicChromTreeNodeCombinerVisitor(
    mcsp_msRunDataSet, *mp_processingFlow, parent);

  return copy;
}

// void
// TicChromTreeNodeCombinerVisitor::nodesToProcess(std::size_t nodes_to_process)
//{
//// Do nothing here because this nodes_to_process count is relative to the
//// thread in which this visitor is operating and thus does not correspond to
//// the total number of nodes that need processing. That total count of nodes
//// to be processed is set in the main thread once for all.
//}


const pappso::MapTrace &
TicChromTreeNodeCombinerVisitor::getTicChromMapTrace() const
{
  return m_ticChromMapTrace;
}

bool
TicChromTreeNodeCombinerVisitor::visit(const pappso::MsRunDataSetTreeNode &node)
{

  // We visit a node, such that we can compute the TIC chromatogram.

  // qDebug() << "Visiting node:" << node.toString();

  if(!m_isProgressFeedbackSilenced)
    {
      // Whatever the status of this node (to be or not processed) let the user
      // know that we have gone through one more.

      // The "%c" format refers to the current value in the task monitor widget
      // that will craft the new text according to the current value after
      // having incremented it in the call below. This is necessary because this
      // visitor might be in a thread and the  we need to account for all the
      // thread when giving feedback to the user.

      emit taskSetStatusMessageAndIncrementCurrentValueSignal(
        "Processed %c nodes", 1);
    }

  // qDebug().noquote() << "Visiting node:" << &node << "text format:" <<
  // node.toString()
  //<< "with quaified mass spectrum:"
  //<< node.getQualifiedMassSpectrum()->toString();

  pappso::QualifiedMassSpectrumCstSPtr qualified_mass_spectrum_csp =
    checkQualifiedMassSpectrum(node);

  if(qualified_mass_spectrum_csp == nullptr)
    {
      qFatal() << "Failed to read the mass spectral data from the file.";
    }


  // Immediately check if the qualified mass spectrum is of a MS level that
  // matches the greatest MS level found in the member processing flow instance.

  if(!checkMsLevel(qualified_mass_spectrum_csp))
    {
      // qDebug() << "The checkMsLevel failed. Returning false, mass spectrum
      // not " "accounted for.";

      return false;
    }
  // else
  //{
  // qDebug() << "The MS level check succeeded.";
  //}

  // Make easy check about RT and DT.

  if(!checkRtRange(qualified_mass_spectrum_csp))
    {
      qDebug() << "checkRtRange failed check.";

      return false;
    }
  if(!checkDtRange(qualified_mass_spectrum_csp))
    {
      qDebug() << "checkDtRange failed check.";

      return false;
    }

  // qDebug() << "The current qualified mass spectrum has size:"
  //<< qualified_mass_spectrum_csp->size();

  double sumY = 0;

  if(!std::isnan(m_mzRange.first) && !std::isnan(m_mzRange.second))
    {
      sumY = qualified_mass_spectrum_csp->getMassSpectrumSPtr()->sumY(
        m_mzRange.first, m_mzRange.second);
    }
  else
    {
      sumY = qualified_mass_spectrum_csp->getMassSpectrumSPtr()->sumY();
    }

  if(!sumY)
    {
      // qDebug() << "sumY is zero, returning true.";
      return true;
    }

  double rt = qualified_mass_spectrum_csp->getRtInMinutes();

  using Pair     = std::pair<double, double>;
  using Map      = std::map<double, double>;
  using Iterator = Map::iterator;

  std::pair<Iterator, bool> res = m_ticChromMapTrace.insert(Pair(rt, sumY));

  if(!res.second)
    {
      // One other same rt value was seen already (like in ion mobility mass
      // spectrometry, for example). Only increment the y value.

      res.first->second += sumY;
    }

  // qDebug() << "This visitor:" << this
  //<< "has size:" << m_ticChromMapTrace.size();

  return true;
}


} // namespace MineXpert

} // namespace MsXpS
