/* 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 <QMainWindow>
#include <QHash>
#include <QMap>


/////////////////////// Local includes
#include <minexpert/nongui/globals.hpp>

#include <minexpert/gui/AnalysisPreferencesDlg.hpp>
#include <minexpert/gui/AnalysisPreferencesDlg.hpp>

#include <minexpert/gui/AbstractPlotWidget.hpp>

#include <minexpert/gui/ConsoleWnd.hpp>
#include <minexpert/gui/ScriptingWnd.hpp>
#include <minexpert/gui/TicChromWnd.hpp>
#include <minexpert/gui/DriftSpecWnd.hpp>
#include <minexpert/gui/MassSpecWnd.hpp>
#include <minexpert/gui/ColorMapWnd.hpp>
#include <minexpert/gui/XicExtractionWnd.hpp>
#include <minexpert/gui/MzIntegrationParamsWnd.hpp>
#include <minexpert/nongui/MassSpecDataSet.hpp>
#include <minexpert/gui/OpenSpectraDlg.hpp>
#include <minexpert/nongui/MassSpecDataFileLoaderSqlite3.hpp>
#include <minexpert/gui/DataPlotWidgetRelation.hpp>
#include <minexpert/gui/SqlMassDataSlicerWnd.hpp>


namespace msXpSmineXpert
{


class MainWindow : public QMainWindow
{
  Q_OBJECT

  private:
  //! The name of the module, at the moment massXpert or mineXpert.
  QString m_moduleName;

  bool m_isScriptedOperation = false;

  public:
  //! DataPlotWidgetRelationer instance responsible for maintaining plot widget
  //! relations.
  DataPlotWidgetRelationer m_dataPlotWidgetRelationer;

  //! Dialog window where to configure the data analysis options.
  AnalysisPreferencesDlg *mp_analysisPrefDlg = Q_NULLPTR;

  //! TIC chromatogram window where all the TIC data are to be displayed.
  TicChromWnd *mp_ticChromWnd = Q_NULLPTR;

  //! Mass spectrum window where all the mass spectra are to be displayed.
  MassSpecWnd *mp_massSpecWnd = Q_NULLPTR;

  //! Drift spectrum window where all the drift spectra are to be displayed.
  DriftSpecWnd *mp_driftSpecWnd = Q_NULLPTR;

  //! Color map window where all the mz=f(dt) color maps are to be displayed.
  ColorMapWnd *mp_colorMapWnd = Q_NULLPTR;

  //! Console window where the feedback messages are to be printed.
  ConsoleWnd *mp_consoleWnd = Q_NULLPTR;

  //! Scripting window where all the scripting activity is performed.
  ScriptingWnd *mp_scriptingWnd = Q_NULLPTR;

  //! XIC extraction configuration window.
  XicExtractionWnd *mp_xicExtractionWnd = Q_NULLPTR;

  //! Mz integration configuration window
  MzIntegrationParamsWnd *mp_mzIntegrationParamsWnd = Q_NULLPTR;

  //! Sql data slicer configuration window.
  SqlMassDataSlicerWnd *mp_sqlMassDataSlicerWnd = Q_NULLPTR;


  // Dialog window displaying all the currently opened data files in a list
  // widget.
  /*!

    The dialog window has a drop down menu allowing to take actions against
    the items in the list widget, like hiding, showing, closing.

*/
  OpenSpectraDlg *mp_openSpectraDlg = Q_NULLPTR;

  //! Minimum value of the progress bar in the status bar.
  int m_progressFeedbackStartValue = -1;
  //! Maximum value of the progress bar in the status bar.
  int m_progressFeedbackEndValue = -1;

  //! Progress bar that is shown in the status bar.
  QProgressBar *mp_statusBarProgressBar = Q_NULLPTR;

  //! Click on that button to let the program know that the running operation
  //! should be cancelled.
  QPushButton *mp_statusBarCancelPushButton = Q_NULLPTR;

  //! Label that is shown in the status bar.
  QLabel *mp_statusBarLabel = Q_NULLPTR;

  //! Tell if the running operation should be cancelled.
  bool m_isOperationCancelled = false;

  //! Analysis preferences.
  AnalysisPreferences *mpa_analysisPreferences = Q_NULLPTR;

  //! File in which to record the analysis steps.
  QFile m_analysisFile;

  //! List of colors that might be used to plot graphs.
  QList<QColor *> m_colorList;
  //! List of colors already used to plot graphs.
  QList<QColor *> m_usedColorList;
  //! Index of the last color used.
  int m_lastUsedColorIndex = -1;

  QMenu *m_fileMenu;
  QMenu *m_plotMenu;
  QMenu *m_utilitiesMenu;
  QMenu *m_windowsMenu;
  QMenu *m_dataProcessingMenu;
  QMenu *m_helpMenu;

  QAction *m_openFullMsFileAct;
  QAction *m_openStreamedMsFileAct;
  QAction *m_openMsClipboardAct;

  QAction *m_isoSpecAct;
  QAction *m_peakShaperAct;

  QAction *m_analysisPrefsAct;
  QAction *m_quitAct;
  QAction *m_clearPlotsAct;
  QAction *m_aboutAct;
  QAction *m_aboutQtAct;
  QAction *m_showTicChromWndAct;
  QAction *m_showMassSpecWndAct;
  QAction *m_showDriftSpecWndAct;
  QAction *m_showColorMapWndAct;
  QAction *m_showOpenSpectraDlgAct;
  QAction *m_showConsoleWndAct;
  QAction *m_showScriptingWndAct;
  QAction *m_showXicExtractionWndAct;
  QAction *m_showMzIntegrationParamsWndAct;
  QAction *m_showSqlMassDataSlicerWndAct;

  QAction *m_showAllWindowsAct;
  QAction *m_saveWorkspaceAct;


  // Construction/destruction
  MainWindow(const QString &moduleName);
  ~MainWindow();

  const OpenSpectraDlg *openSpectraDlg() const;

  void createMenusAndActions();

  void showMzIntegrationParamsHelp(double smallestStepMedian);

  void writeSettings();
  void readSettings();

  Q_INVOKABLE void about();
  Q_INVOKABLE void quit();

  void concludeFileLoading();

  void seedInitialPlots(MassSpecDataSet *massSpecDataSet);

  Q_INVOKABLE void clearPlots();

  void closeEvent(QCloseEvent *event);

  bool setupWindow();

  bool initialize();

  void initializeScripting();

  void recyclePlottingColor(QColor color);
  bool isPlottingColorUsed(const QColor &color) const;

  void
  loadChromatogram(const QString & = QString("total ion current chromatogram"));

  void logConsoleMessage(QString msg,
                         const QColor &color = QColor(),
                         bool overwrite      = false);

  void updateStatusBar(QString msg);

  void dataLoadMessage(QString message, int logType);

  void statusBarMessage(QString msg);
  void statusBarProgress(int value);

  void createMassSpectrumFromXyText(const QString &text, const QString &title);
  void createMassSpectrumFromClipboard();
  Q_INVOKABLE void jsCreateMassSpectrumFromClipboard();

  void openMassSpectrometryFile(const QString &fileName = QString(),
                                bool isStreamed         = false);
  Q_INVOKABLE void
  jsOpenMassSpectrometryFile(const QString &fileName = QString(),
                             bool isStreamed         = false);

  void openMassSpectrometryFiles(const QStringList &fileList, bool isStreamed);
  Q_INVOKABLE void jsOpenMassSpectrometryFiles(const QStringList &fileList,
                                               bool isStreamed);

  void openMassSpectrometryFileSqlite3(QString fileName,
                                       bool isStreamed = false);
  void openMassSpectrometryFilePwiz(QString fileName,
                                    int format,
                                    bool isStreamed = false);
  void openMassSpectrometryFileDx(QString fileName, bool isStreamed = false);
  void openMassSpectrometryFileMs1(QString fileName, bool isStreamed = false);
  void openMassSpectrometryFileBrukerXy(QString fileName,
                                        bool isStreamed = false);
  void openMassSpectrometryFileXy(QString fileName);

  void makeLoaderConnections(MassSpecDataFileLoader *loader);

  void xicExtraction();

  void isoSpecDlg();
  void peakShaperDlg();

  void analysisPrefDlg();
  void showTicChromWnd();
  void showMassSpecWnd();
  void showDriftSpecWnd();
  void showColorMapWnd();
  void showOpenMassSpectraDlg();
  void showConsoleWnd();
  void showScriptingWnd();
  void showXicExtractionWnd();
  void showMzIntegrationParamsWnd();
  void showSqlMassDataSlicerWnd();

  void showAllWindows();
  void saveWorkspace();

  void destroyAlsoAllTargetPlotWidgets(AbstractPlotWidget *originPlotWidget);

  // Multigraph graph visibility toggling.
  void toggleMultiGraph(AbstractPlotWidget *widget, bool recursive);

  void cancelPushButtonClicked();

  public slots:
  void openFullMassSpectrometryFileDlg();
  void openStreamedMassSpectrometryFileDlg();

  void updateFeedback(QString msg,
                      int currentValue = -1,
                      bool setVisible  = true,
                      int logType      = LogType::LOG_TO_CONSOLE,
                      int startValue   = -1,
                      int endValue     = -1);

  void initialTicDone(AbstractPlotWidget *widget,
                      const MassSpecDataSet *massSpecDataSet,
                      QColor color);

  void initialColorMapDone(AbstractPlotWidget *widget,
                           AbstractPlotWidget *originWidget,
                           const MassSpecDataSet *massSpecDataSet,
                           QColor color);

  signals:
  void cancelOperationSignal();
};

} // namespace msXpSmineXpert
