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


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


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


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

namespace MsXpS
{
namespace MineXpert
{


MultiTreeNodeCombinerVisitor::MultiTreeNodeCombinerVisitor(
  MsRunDataSetCstSPtr ms_run_data_set_csp,
  const ProcessingFlow &processing_flow,
  QObject *parent)
  : BaseMsRunDataSetTreeNodeVisitor(
      ms_run_data_set_csp, processing_flow, parent)
{
  //  qDebug() << "Processing flow has" <<
  //  mp_processingFlow.getStepsCstRef().size() << "steps";
  // qDebug() << "Current thread:" << QThread::currentThreadId();
  // if(parent != nullptr)
  //   qDebug() << "parent thread: " << parent->thread();
}

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

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

  return copy;
}

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

  // We visit a node. In this kind of multi visisor we submit the to a visit for
  // each visitor present the vector of visitors.

  // qDebug() << "Multi-visiting node:" << node.toString();

  // 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);

  // Copy the node because we'll need to modify it later to hand it over to the
  // visitors.
  pappso::MsRunDataSetTreeNode local_node = node;

  // qDebug() << "node copy:" << local_node.toString();

  pappso::QualifiedMassSpectrumCstSPtr qualified_mass_spectrum_csp =
    local_node.getQualifiedMassSpectrum();

  if(qualified_mass_spectrum_csp == nullptr)
    qFatal() << "Cannot be nullptr";
  if(qualified_mass_spectrum_csp.get() == nullptr)
    qFatal() << "Cannot be nullptr";

  if(qualified_mass_spectrum_csp->getMassSpectrumSPtr() == nullptr)
    {
      // qDebug() << "Need to access the mass data right from the file.";

      // Get the mass spectrum index from the data tree using the address of
      // the node, that is, its pointer. That one needs to be the original node
      // pointer because that is the pointer that is located in the ms run data
      // set tree !
      std::size_t mass_spectrum_index =
        mcsp_msRunDataSet->getMsRunDataSetTreeCstSPtr()->massSpectrumIndex(
          &node);

      // To read the data from disk, we need to get a pointer to the ms run
      // reader attached to this data set.
      pappso::MsRunReaderCstSPtr ms_run_reader_csp =
        mcsp_msRunDataSet->getMsRunReaderCstSPtr();

      // Now get the binary data (mz and i) of the mass spectrum (true boolean
      // value below).
      qualified_mass_spectrum_csp =
        std::make_shared<pappso::QualifiedMassSpectrum>(
          ms_run_reader_csp->qualifiedMassSpectrum(mass_spectrum_index, true));

      // Now set the qualified mass spectrum constant shared pointer to the node
      // copy so that we can later use it to perform the node visiting task:
      // that node copy will have the true mass spectral data in it.
      local_node.setQualifiedMassSpectrum(qualified_mass_spectrum_csp);

      // qDebug() << "After reading from file, local node:" <<
      // local_node.toString();
    }

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

  // From now on, the visitors will no need to load the mass spectral data from
  // the file, because that has been done already.

  for(auto &&visitor : m_visitors)
    {
      // Silence the feedback because we have handled it above.
      visitor->silenceFeedback(true);

      // Finally use the local_node that has the actual mass spectral data to do
      // the visiting task. No matter how many visitors are going to visit the
      // local_node, the visiting task will not need to load the mass spectral
      // data from disk as they are there already.
      visitor->visit(local_node);
    }

  return true;
}

void
MultiTreeNodeCombinerVisitor::addVisitor(
  BaseMsRunDataSetTreeNodeVisitor *visitor_p)
{
  m_visitors.push_back(visitor_p);
}


} // namespace MineXpert

} // namespace MsXpS
