/* 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 <QSettings> #include <QMenuBar>
/// #include <QMenu> #include <QDebug>


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


/////////////////////// Local includes
#include "BaseColorMapPlotWnd.hpp"
#include "ProgramWindow.hpp"
#include <MsXpS/libXpertMassGui/ColorSelector.hpp>

namespace MsXpS
{
namespace MineXpert
{


//! Construct an BaseColorMapPlotWnd instance.
BaseColorMapPlotWnd::BaseColorMapPlotWnd(QWidget *parent,
                                         const QString &title,
                                         const QString &settingsTitle,
                                         const QString &description)
  : BasePlotWnd(parent, title, settingsTitle, description)
{
  // The base class constructor initializes the window and thus the tool bar.
  // But we need to add specific buttons here.

  setupToolBar();
}

//! Destruct \c this BaseColorMapPlotWnd instance.
BaseColorMapPlotWnd::~BaseColorMapPlotWnd()
{
  // qDebug();
  writeSettings();
}

void
BaseColorMapPlotWnd::setupToolBar()
{

  // This tool bar button will trigger the transpose axes operation on all the
  // plot widget that are pinned-down.

  const QIcon transposeAxesIcon = QIcon(":/images/svg/transpose-xy-axes.svg");
  mp_transposeAxesAct           = new QAction(
    transposeAxesIcon, tr("Transpose axes for pinned-down plot widgets"), this);
  mp_transposeAxesAct->setStatusTip(
    "Transpose axes for pinnned-down plot widgets");

  connect(mp_transposeAxesAct, &QAction::triggered, [this]() {
    std::vector<BasePlotCompositeWidget *> widget_list = pinnedDownWidgets();

    for(auto &&widget_p : widget_list)
      {
        BasePlotCompositeWidget *cast_widget_p = widget_p;

        pappso::BasePlotWidget *base_plot_widget_p =
          const_cast<pappso::BasePlotWidget *>(cast_widget_p->getPlotWidget());

        pappso::BaseColorMapPlotWidget *base_color_map_plot_widget_p =
          static_cast<pappso::BaseColorMapPlotWidget *>(base_plot_widget_p);

        base_color_map_plot_widget_p->transposeAxes();
      }
  });

  mp_toolBar->addAction(mp_transposeAxesAct);
}

QCPColorMap *
BaseColorMapPlotWnd::finalNewColorMapPlotConfiguration(
  BaseColorMapPlotCompositeWidget *composite_widget_p,
  std::shared_ptr<std::map<double, pappso::MapTrace>> &double_map_trace_map_sp,
  const pappso::ColorMapPlotConfig &color_map_plot_config,
  MsRunDataSetCstSPtr ms_run_data_set_csp,
  const ProcessingFlow &processing_flow,
  const QColor &color,
  QCPAbstractPlottable *parent_plottable_p)
{
  // qDebug();

  //////// CAUTION ///////
  //////// CAUTION ///////

  // The single graph destruction signal. We do one single connection for the
  // plot widget and not for each graph that is in the plot widget. Otherwise,
  // we get signals multiple times for the same graph. In previous buggy code,
  // we had this connection performed in the BaseColorMapPlotCompositeWidget
  // class qDebug().noquote()
  //<< "Making the connection:"
  //<< "pappso::BaseColorMapPlotWidget::graphDestructionRequestedSignal to "
  //"mp_parentWnd->getProgramWindow()->graphDestructionRequested.";

  connect(composite_widget_p->getPlotWidget(),
          &pappso::BasePlotWidget::plottableDestructionRequestedSignal,
          [composite_widget_p,
           this]([[maybe_unused]] pappso::BasePlotWidget *base_plot_widget_p,
                 QCPAbstractPlottable *plottable_p,
                 const pappso::BasePlotContext &context) {
            mp_programWindow->plottableDestructionRequested(
              composite_widget_p, plottable_p, context);
          });

  //////// CAUTION ///////
  //////// CAUTION ///////

  QColor local_color(color);

  // Get color from the available colors, or if none is available, create one
  // randomly without requesting the user to select one from QColorDialog.
  if(!local_color.isValid())
    local_color = libXpertMassGui::ColorSelector::getRandomColor();

  QString sample_name = ms_run_data_set_csp->getMsRunId()->getSampleName();

  // Sanity check
  if(ms_run_data_set_csp != processing_flow.getMsRunDataSetCstSPtr())
    qFatal() << "Programming error.";

  QCPColorMap *color_map_p =
    composite_widget_p->addColorMap(double_map_trace_map_sp,
                                    color_map_plot_config,
                                    parent_plottable_p,
                                    ms_run_data_set_csp,
                                    sample_name,
                                    processing_flow,
                                    local_color);

  composite_widget_p->setMinimumSize(400, 200);
  mp_splitter->addWidget(composite_widget_p);

  // We now need to inform the parent window that the size of the scroll area
  // might have changed.

  BasePlotWnd::resizeEvent(nullptr);

  return color_map_p;
}

void
BaseColorMapPlotWnd::integrateToMz(QCPAbstractPlottable *parent_plottable_p,
                                   const ProcessingFlow &processing_flow)
{
  // qDebug();

  if(parent_plottable_p == nullptr)
    qFatal() << "Cannot be that pointer is nullptr.";

  // We do not handle integrations to m/z, because each trace plot window
  // handles their own data. So we just relay this call to the main program
  // window that will in turn relay it to the mass spec plot window.

  // qDebug().noquote() << "Integrating to mz for graph with processing flow:"
  //<< processing_flow.toString();

  mp_programWindow->integrateToMz(parent_plottable_p, nullptr, processing_flow);
}

void
BaseColorMapPlotWnd::integrateToDt(QCPAbstractPlottable *parent_plottable_p,
                                   const ProcessingFlow &processing_flow)
{
  // qDebug();

  if(parent_plottable_p == nullptr)
    qFatal() << "Cannot be that pointer is nullptr.";

  // We do not handle integrations to m/z, because each trace plot window
  // handles their own data. So we just relay this call to the main program
  // window that will in turn relay it to the mass spec plot window.

  // qDebug().noquote() << "Integrating to dt for graph with processing flow:"
  //<< processing_flow.toString();

  mp_programWindow->integrateToDt(parent_plottable_p, nullptr, processing_flow);
}

void
BaseColorMapPlotWnd::integrateToDtMz(QCPAbstractPlottable *parent_plottable_p,
                                     const ProcessingFlow &processing_flow)
{
  // qDebug();

  if(parent_plottable_p == nullptr)
    qFatal() << "Cannot be that pointer is nullptr.";

  // We do not handle integrations to m/z, because each trace plot window
  // handles their own data. So we just relay this call to the main program
  // window that will in turn relay it to the mass spec plot window.

  // qDebug().noquote() << "Integrating to drift spectrum / mass spectrum for
  // "
  //"color map plot with processing flow:"
  //<< processing_flow.toString();

  mp_programWindow->integrateToDtMz(
    parent_plottable_p, nullptr, processing_flow);
}

void
BaseColorMapPlotWnd::integrateToRt(QCPAbstractPlottable *parent_plottable_p,
                                   const ProcessingFlow &processing_flow)
{
  // qDebug();

  if(parent_plottable_p == nullptr)
    qFatal() << "Cannot be that pointer is nullptr.";

  // We do not handle integrations to m/z, because each trace plot window
  // handles their own data. So we just relay this call to the main program
  // window that will in turn relay it to the mass spec plot window.

  // qDebug().noquote() << "Integrating to mz for graph with processing flow:"
  //<< processing_flow.toString();

  mp_programWindow->integrateToRt(parent_plottable_p, nullptr, processing_flow);
}

void
BaseColorMapPlotWnd::integrateToMzRt(QCPAbstractPlottable *parent_plottable_p,
                                     const ProcessingFlow &processing_flow)
{
  // qDebug();

  if(parent_plottable_p == nullptr)
    qFatal() << "Cannot be that pointer is nullptr.";

  // We do not handle integrations to m/z, because each trace plot window
  // handles their own data. So we just relay this call to the main program
  // window that will in turn relay it to the mass spec plot window.

  // qDebug().noquote() << "Integrating to TIC|XIC chrom. / mass spectrum for
  // "
  //"color map plot with processing flow:"
  //<< processing_flow.toString();

  mp_programWindow->integrateToMzRt(
    parent_plottable_p, nullptr, processing_flow);
}

void
BaseColorMapPlotWnd::integrateToDtRt(QCPAbstractPlottable *parent_plottable_p,
                                     const ProcessingFlow &processing_flow)
{
  // qDebug();

  if(parent_plottable_p == nullptr)
    qFatal() << "Cannot be that pointer is nullptr.";

  // We do not handle integrations to m/z, because each trace plot window
  // handles their own data. So we just relay this call to the main program
  // window that will in turn relay it to the mass spec plot window.

  mp_programWindow->integrateToDtRt(
    parent_plottable_p, nullptr, processing_flow);
}


} // namespace MineXpert

} // namespace MsXpS
