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


#pragma once


/////////////////////// Qt includes
#include <QMainWindow>
#include <QDir>
#include <QStringList>


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

/////////////////////// libXpertMassCore includes
#include <MsXpS/libXpertMassCore/PolChemDef.hpp>
#include <MsXpS/libXpertMassCore/PolChemDefSpec.hpp>
#include <MsXpS/libXpertMassCore/MassDataServer.hpp>
#include <MsXpS/libXpertMassCore/MassDataClient.hpp>
#include <MsXpS/libXpertMassCore/RecentFilesHandler.hpp>


/////////////////////// libXpertMassGui includes
#include <MsXpS/libXpertMassGui/MassDataClientServerConfigDlg.hpp>
#include <MsXpS/libXpertMassGui/IsotopicClusterGeneratorDlg.hpp>
#include <MsXpS/libXpertMassGui/IsotopicClusterShaperDlg.hpp>
#include <MsXpS/libXpertMassGui/JavaScriptingEnvironment.hpp>
#include <MsXpS/libXpertMassGui/JavaScriptingWnd.hpp>
#include <MsXpS/libXpertMassGui/ActionManager.hpp>


/////////////////////// local includes
#include "AboutDlg.hpp"
#include "../nongui/UserSpec.hpp"
#include "../nongui/ConfigSettings.hpp"


class QAction;
class QMenu;
class QTextEdit;


namespace MsXpS
{
namespace MassXpert
{


class SequenceEditorWnd;
class ApplicationPreferencesWnd;


class ProgramWindow : public QMainWindow
{
  Q_OBJECT

  public:
  ProgramWindow(QWidget *parent,
                const QString &application_name,
                const QString &description);
  ~ProgramWindow();

  const UserSpec &getUserSpec() const;
  ConfigSettingsSPtr getConfigSettings() const;

  void setMaxThreadUseCount(int count);
  int getMaxThreadUseCount();

  void displayArticleCitationHelpPage();

  void updateRecentFilesMenu();

  void setLastFocusedSeqEdWnd(SequenceEditorWnd *);

  std::vector<libXpertMassCore::PolChemDefSpecSPtr> &getPolChemDefSpecsRef();
  const std::vector<libXpertMassCore::PolChemDefSpecSPtr> &
  getPolChemDefSpecsCstRef() const;

  libXpertMassCore::PolChemDefSpecSPtr getPolChemDefSpecByName(const QString &name);
  libXpertMassCore::PolChemDefSpecSPtr
  getPolChemDefSpecByFilePath(const QString &file_path);

  QStringList polChemDefSpecsAsStringList();

  std::vector<libXpertMassCore::PolChemDefCstSPtr> &getPolChemDefsRef();
  const std::vector<libXpertMassCore::PolChemDefCstSPtr> &
  getPolChemDefsCstRef() const;

  libXpertMassCore::PolChemDefCstSPtr getPolChemDefByName(const QString &name);

  bool isSequenceEditorWnd(SequenceEditorWnd *) const;

  Q_INVOKABLE libXpertMassGui::MassDataClientServerConfigDlg *
  configureNetworkConnection(bool no_dlg_show);


  Q_INVOKABLE bool startMineXpertWithClient(const QString &ip_address,
                                            int port_number,
                                            const QByteArray &data);

  static void registerJsConstructor(QJSEngine *engine);

  void setupWindow();

  public slots:
  void openPolChemDef();
  void newPolChemDef();

  void newCalculator();

  SequenceEditorWnd *openSequence(const QString &fileName = QString());
  SequenceEditorWnd *openSampleSequence();
  SequenceEditorWnd *newSequence();
  void delistSequenceEditorWnd(SequenceEditorWnd *wnd);

  // void mzLab();

  void about();
  AboutDlg *showAboutDlg();

  void massListSorter();
  void seqManip();
  void showIsotopicClusterGeneratorDlg();
  void showIsotopicClusterShaperDlg();
  void showScriptingWnd();

  void showApplicationPreferencesWnd();
  const ApplicationPreferencesWnd *getApplicationPreferencesWnd();

  libXpertMassGui::ActionManager *getActionManager();

  signals:
  void aboutToCloseSignal();

  protected:
  void closeEvent(QCloseEvent *);
  QString m_applicationName;
  QString m_windowDescription;

  ConfigSettingsSPtr msp_configSettings = nullptr;

  UserSpec m_userSpec;

  QString m_lastUsedDirectory = QDir::homePath();

  // The user can limit the max number of threads to use. 0 is no limitation
  // (all the available threads are going to be used).
  int m_maxThreadUseCount = 0;

  // Last sequence editor window that got the focus.
  SequenceEditorWnd *mp_lastFocusedSeqEdWnd;

  // The QList of all the sequence editor windows.
  QList<SequenceEditorWnd *> m_sequenceEditorWndList;

  // Container of all the polymer chemistry definition specifications that
  // were created during parsing of all the different catalogue files
  // on the system.
  std::vector<libXpertMassCore::PolChemDefSpecSPtr> m_polChemDefSpecs;

  // List of all the polymer chemistry definitions that are loaded in
  // memory and usable to load polymer sequences.
  std::vector<libXpertMassCore::PolChemDefCstSPtr> m_polChemDefs;

  libXpertMassGui::JavaScriptingEnvironment *m_scriptingEnvironment = nullptr;
  libXpertMassGui::JavaScriptingWnd *mp_javaScriptingWnd            = nullptr;

  libXpertMassGui::MassDataClientServerConfigDlg *mp_clientServerConfigDlg =
    nullptr;

  libXpertMassCore::MassDataClient *mp_massDataClient = nullptr;
  libXpertMassCore::MassDataServer *mp_massDataServer = nullptr;

  libXpertMassGui::ActionManager *mp_actionManager = nullptr;

  QMenu *mp_fileMenu                      = nullptr;
  QMenu *mp_recentFilesMenu               = nullptr;
  QAction *mp_recentFilesMenuSeparator = nullptr;

  QMenu *mp_xpertDefMenu         = nullptr;
  QMenu *mp_xpertCalcMenu        = nullptr;
  QMenu *mp_xpertEditMenu        = nullptr;
  QMenu *mp_xpertMinerMenu       = nullptr;
  QMenu *mp_xpertScriptMenu      = nullptr;
  QMenu *mp_isotopicClustersMenu = nullptr;
  QMenu *mp_preferencesMenu      = nullptr;
  QMenu *mp_utilitiesMenu        = nullptr;
  QMenu *mp_helpMenu             = nullptr;

  QAction *mp_openPolChemDefAct;
  QAction *mp_newPolChemDefAct;

  QAction *mp_newCalculatorAct;

  QAction *mp_openSequenceAct;
  QAction *mp_openSampleSequenceAct;
  QAction *mp_newSequenceAct;

  QAction *mp_mzLabAct;

  QAction *mp_massListSorterAct;
  QAction *mp_seqManipAct;
  QAction *mp_isotopicClusterGeneratorDlgAct;
  QAction *mp_isotopicClusterShaperDlgAct;

  QAction *mp_clientServerConfigDlgAct;

  QAction *mp_scriptingConsoleAct;

  QAction *mp_exitAct;
  QAction *mp_configSettingsAct;

  QAction *mp_aboutAct;
  QAction *mp_aboutQtAct;

  libXpertMassCore::RecentFilesHandler m_recentFilesHandler;

  libXpertMassGui::IsotopicClusterGeneratorDlg *mp_isotopicClusterGeneratorDlg =
    nullptr;
  libXpertMassGui::IsotopicClusterShaperDlg *mp_isotopicClusterShaperDlg =
    nullptr;

  ApplicationPreferencesWnd *mp_applicationPreferencesWnd = nullptr;

  void addToMenu(QObject *, const QStringList &, QMenu *, const char *);

  void readSettings();
  void writeSettings();

  void createActions();
  void createMenus();
  void createStatusBar();

  bool setupConfigSettings();
  bool initializeSystemConfig();
  bool initializeUserConfig();
  void initializeScripting();

  // The server started in MassXpert is used to serve mass
  // data to MineXpert.
  Q_INVOKABLE bool startServer();
  Q_INVOKABLE void stopServer();
  // Only for hypothetical later work. At the moment MassXpert
  // only start a server to serve data to MineXpert.
  Q_INVOKABLE bool startClient(const QString &ip_address,
                               int port_number);
  Q_INVOKABLE void stopClient();

  void dispatchReceivedData(const QByteArray &byte_array);

  private slots:

    void massDataToBeServed(const QByteArray &byte_array);
    void massSpectrumToBeDisplayed(const QString &title, const QByteArray &color_byte_array, pappso::TraceCstSPtr trace_csp);
};


} // namespace MassXpert
MSXPS_REGISTER_JS_CLASS(MsXpS::MassXpert, ProgramWindow)
} // namespace MsXpS

