/* BEGIN software license
 *
 * msXpertSuite - mass spectrometry software suite
 * -----------------------------------------------
 * Copyright(C) 2009,...,2018 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
 */


#pragma once


/////////////////////// Qt includes
#include <QObject>
#include <QString>
#include <QWidget>
#include <QColor>
#include <QHash>
#include <QThread>


/////////////////////// Local includes
#include <minexpert/gui/AbstractMultiPlotWnd.hpp>
#include <minexpert/gui/MassSpecPlotWidget.hpp>
#include <minexpert/nongui/AnalysisPreferences.hpp>
#include <minexpert/nongui/MassSpecDataSet.hpp>
#include <minexpert/nongui/MassDataIntegrator.hpp>


namespace msXpSmineXpert
{


//! The MassSpecWnd class provides a window to display mass spectra.
/*!

  The window will host two main parts:

  - the upper part will host a single plot widget where the graphs
  corresponding to all the mass spectra will be plotted overlaid.

  - the lower part will host as many plot widgets as there are mass spectra
  to be plotted. Indeed, in the lower part of the window, each plot widget
  will contain a single graph. Each single graph of the various plot widgets
  is replicated in the multigraph plot widget located in the upper part of the
  window.

*/
class MassSpecWnd : public AbstractMultiPlotWnd
{
  Q_OBJECT

  private:
  //! Plot widget in which multiple graphs will be plotted.
  MassSpecPlotWidget *mp_multiGraphPlotWidget = nullptr;

  //! Number of plot widgets located in the lower part of the window.
  /*!

    The lower part of the window hosts single-graph plot widgets. This
    counter logs the number of such plot widgets and is used by the
    scripting framework to provide a numerical suffix to the plot widget
    name in the scripting environment.

*/
  static int widgetCounter;

  //! Widget in which to set the span between two peaks.
  /*!

    When performing a charge state envelope-based deconvolution, the user
    may state that the two peaks pointed with the mouse cursor are either
    immediately consecutive in the envelope (span value is 1) or that they
    are separated by another peak (span value is 2) or more than one peaks.
    This widget allows the user the set that span value.
    */
  QSpinBox *mp_massPeakSpanSpinBox = nullptr;

  QDoubleSpinBox *mp_chargeFracPartToleranceSpinBox = nullptr;

  public:
  MassSpecWnd(QWidget *parent);
  ~MassSpecWnd();

  void initialize();
  void initializePlotRegion();

  Q_INVOKABLE void
  hide()
  {
    QMainWindow::hide();
  };
  Q_INVOKABLE void
  show()
  {
    QMainWindow::show();
  };

  int massPeakSpan() const;
  double chargeFracPartTolerance() const;

  MassSpecPlotWidget *
  addPlotWidget(const QVector<double> &keyVector,
                const QVector<double> &valVector,
                const QString &desc                    = QString(),
                const QColor &color                    = Qt::black,
                const MassSpecDataSet *massSpecDataSet = Q_NULLPTR,
                bool isMultiGraph                      = false);

  void newMassSpectrum(const MassSpecDataSet *massSpecDataSet,
                       const QString &msg,
                       History history,
                       QColor color);

  void jsNewMassSpectrum(AbstractPlotWidget *caller,
                         const MassSpecDataSet *massSpecDataSet,
                         const QString &msg,
                         History history,
                         QColor color);

  void ticIntensity(const MassSpecDataSet *massSpecDataSet,
                    const QString &msg,
                    History history);

  void newPlot(AbstractPlotWidget *senderPlotWidget,
               const MassSpecDataSet *massSpecDataSet,
               QVector<double> keys,
               QVector<double> values,
               const QString &msg,
               History history,
               QColor color);

  bool focusNextPrevChild(bool next);

  void recordAnalysisStanza(const QString &stanza,
                            const QColor &color = QColor());

  public slots:

  void newMassSpectrumDone(MassDataIntegrator *integrator,
                           AbstractPlotWidget *senderPlotWidget,
                           QColor color);

  void ticIntensityDone(MassDataIntegrator *integrator,
                        QString msg,
                        AbstractPlotWidget *senderPlotWidget);

  signals:
  void integrateToMzSignal();
  void integrateToTicIntensitySignal();
};

} // namespace msXpSmineXpert
