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


/////////////////////// stdlib includes


/////////////////////// Qt includes
#include <QMainWindow>
#include <QGraphicsScene>
#include <QClipboard>
#include <QProgressBar>
#include <QListWidgetItem>

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


/////////////////////// libXpertMass includes
// For MSXPS_REGISTER_JS_CLASS at the end of the class declaration
#include <MsXpS/libXpertMassCore/CalcOptions.hpp>
#include <MsXpS/libXpertMassCore/Ionizer.hpp>
#include <MsXpS/libXpertMassCore/PolChemDef.hpp>


/////////////////////// libXpertMassGui includes
#include <MsXpS/libXpertMassGui/MassPeakShaperConfigDlg.hpp>


/////////////////////// Local includes
#include "SequenceEditorWnd.hpp"
#include "AbstractMainTaskWindow.hpp"
#include "MonomerCodeEvaluator.hpp"
#include "PolChemDefRendering.hpp"
#include "SequenceEditorGraphicsView.hpp"

namespace Ui
{
class SequenceEditorWnd;
}


namespace MsXpS
{
namespace MassXpert
{


class SequenceEditorGraphicsView;
class SequenceEditorFindDlg;
class CleavageDlg;
class FragmentationDlg;
class MassSearchDlg;
class MzCalculationDlg;
class CompositionsDlg;
class PkaPhPiDlg;
class MonomerModificationDlg;
class PolymerModificationDlg;
class MonomerCrossLinkDlg;

/*  BEGIN CLASS JS REFERENCE
 *  namespace: MsXpS::MassXpert
 *  class name: SequenceEditorWnd
 */

class SequenceEditorWnd : public AbstractMainTaskWindow
{
  Q_OBJECT

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

  ~SequenceEditorWnd();

  bool m_forciblyClose   = 0;
  bool m_postInitialized = 0;

  SequenceEditorGraphicsView *mpa_editorGraphicsView;
  QGraphicsScene *mpa_editorGraphicsScene;

  QProgressBar *progressBar();

  Q_INVOKABLE bool openSequence(QString &sequence_file_path);
  Q_INVOKABLE bool newSequence(QString &pol_chem_def_file_path);
  Q_INVOKABLE bool maybeSave();

  Q_INVOKABLE void updateMonomerPosition(int);

  bool preparePolChemDefRendering(const QString &name);
  void populateCalculationOptions();
  bool populateAvailableMonomerCodesList(bool = false);

  Q_INVOKABLE bool readFile(const QString &file_path);

  Q_INVOKABLE int
  setIndexRanges(const QString &text,
                 libXpertMassCore::Enums::LocationType location_type =
                   libXpertMassCore::Enums::LocationType::INDEX);

  PolChemDefRenderingCstRPtr getPolChemDefRenderingCstRPtr() const;
  PolChemDefRenderingRPtr getPolChemDefRenderingRPtr();

  Q_INVOKABLE libXpertMassCore::PolymerQSPtr getPolymerSPtr();
  Q_INVOKABLE libXpertMassCore::Polymer *getPolymer();

  QList<libXpertMassCore::Prop *> *propList();

  Q_INVOKABLE void
  setCalcOptions(const libXpertMassCore::CalcOptions *calc_options_p);
  Q_INVOKABLE void
  setCalcOptions(const libXpertMassCore::CalcOptions &calc_options);
  Q_INVOKABLE libXpertMassCore::CalcOptions *getCalcOptions();
  Q_INVOKABLE const libXpertMassCore::CalcOptions &getCalcOptionsCstRef() const;

  Q_INVOKABLE const libXpertMassCore::Ionizer &getIonizerCstRef() const;
  Q_INVOKABLE libXpertMassCore::Ionizer &getIonizerRef();
  Q_INVOKABLE libXpertMassCore::Ionizer *getIonizer();

  void clearCompletionsListSelection();
  void completionsListSelectAt(int);

  void setWindowModified(bool);

  void updateWindowTitle();

  void getsFocus();

  void wholeSequenceMasses(double * = 0, double * = 0);
  void selectedSequenceMasses(double * = 0, double * = 0);

  void updatePolymerEndsModifs();

  void newCalculator(QString, QString);

  signals:
  void polymerSequenceModifiedSignal();
  void polymerSequenceWndAboutToClose(SequenceEditorWnd *);
  void displayMassSpectrumSignal(const QString &title,
                                 const QByteArray &color_byte_array,
                                 pappso::TraceCstSPtr trace);


  public slots:
  bool save();
  bool saveAs();

  void updateMassesNewDecimalsOptions();

  // Whole sequence
  void initialNonIonizedWholePolymerSequenceMassCalculation(bool deep = false);
  void updateWholeSequenceMasses(bool deep = false);

  // Selected sequence
  void
  initialNonIonizedSelectedPolymerSequenceMassCalculation(bool deep = false);
  void updateSelectedSequenceMasses(bool deep = false);

  // libXpertMassCore::Sequence importers.
  void importRaw();

  void exportClipboard();
  void exportFile();
  bool exportSelectFile();

  void clipboardCopy(QClipboard::Mode = QClipboard::Clipboard);
  void clipboardCut(QClipboard::Mode = QClipboard::Clipboard);
  void clipboardPaste(QClipboard::Mode = QClipboard::Clipboard);
  void clipboardClear(QClipboard::Mode);
  void findSequence();

  void vignetteSizeChanged();
  void nameLineEditChanged(const QString &text);

  void calculationOptionsChanged();

  void leftModifOptionsChanged();
  void forceLeftModifOptionsChanged();
  void rightModifOptionsChanged();
  void forceRightModifOptionsChanged();

  void setMultiRegionSelection(bool is_multi_region_selection);
  void setMultiSelectionRegion(bool is_multi_selection_region);
  void multiRegionSelectionOptionChanged(int);
  bool isMultiRegionSelection();

  void regionSelectionOligomerOptionChanged(bool);
  void regionSelectionResChainOptionChanged(bool);

  int coordinatesManuallyEdited(const QString &);

  void multiSelectionRegionOptionChanged(int);
  bool isMultiSelectionRegion();

  void monomerModifOptionChanged(int);

  void monomerCrossLinkOptionChanged(int);

  Q_INVOKABLE MonomerModificationDlg *modifMonomer();

  Q_INVOKABLE PolymerModificationDlg *modifPolymer();
  Q_INVOKABLE PolymerModificationDlg *modifLeftEnd();
  Q_INVOKABLE PolymerModificationDlg *modifRightEnd();
  Q_INVOKABLE void modifPolymerEnd(libXpertMassCore::Enums::PolymerEnd end,
                                   const QString &modif_name);

  MonomerCrossLinkDlg *crossLinkMonomers();
  CleavageDlg *cleave();
  FragmentationDlg *fragment();
  MassSearchDlg *massSearch();
  MzCalculationDlg *mzCalculation();
  CompositionsDlg *compositions();
  PkaPhPiDlg *pkaPhPi();

  void decimalPlacesOptions();

  void newCalculatorWholeSequenceMasses();
  void newCalculatorSelectedSequenceMasses();

  void crossLinksPartiallyEncompassedSlot(int);

  void vignetteListWidgetItemDoubleClicked(QListWidgetItem *);

  Q_INVOKABLE QString getSequenceName() const;

  static void registerJsConstructor(QJSEngine *engine);

  protected:
  libXpertMassGui::MassPeakShaperConfigDlg *mp_massPeakShaperConfigDlg =
    nullptr;

  libXpertMassCore::IsotopicDataSPtr msp_isotopicData = nullptr;

  // The results-exporting strings. ////////////////////////////////
  QString *mpa_resultsString;
  QString m_resultsFilePath;
  //////////////////////////////////// The results-exporting strings.

  QMenu *fileMenu;
  QMenu *fileImportMenu;
  QMenu *editMenu;
  QMenu *chemistryMenu;
  QMenu *optionsMenu;
  QMenu *calculatorMenu;

  QAction *closeAct;
  QAction *saveAct;
  QAction *saveAsAct;
  QAction *importRawAct;
  QAction *exportClipboardAct;
  QAction *exportFileAct;
  QAction *exportSelectFileAct;

  QAction *clipboardCopyAct;
  QAction *clipboardCutAct;
  QAction *clipboardPasteAct;
  QAction *findSequenceAct;

  QAction *modifMonomerAct;
  QAction *modifPolymerAct;
  QAction *crossLinkMonomersAct;
  QAction *cleaveAct;
  QAction *fragmentAct;
  QAction *massSearchAct;
  QAction *mzCalculationAct;
  QAction *compositionsAct;
  QAction *pkaPhPiAct;

  QAction *decimalPlacesOptionsAct;

  QAction *newCalculatorWholeSequenceMassesAct;
  QAction *newCalculatorSelectedSequenceMassesAct;

  // Allocated but reparented to QStatusBar.
  QProgressBar *mp_progressBar;

  libXpertMassCore::PolymerQSPtr msp_polymer = nullptr;
  PolChemDefRenderingUPtr mup_polChemDefRendering;
  libXpertMassCore::CalcOptions *mp_calcOptions = nullptr;

  QList<libXpertMassCore::Prop *> m_propList;

  libXpertMassCore::MassPeakShaperConfig m_massPeakShaperConfig;

  pappso::Trace m_syntheticMassSpectrum;

  // For the mass spectra that are synthesized and served.
  QByteArray m_colorByteArray;


  Ui::SequenceEditorWnd *mp_ui;

  void writeSettings();
  void readSettings();

  // Before the creation of the polChemDef/polymer relationship.
  Q_INVOKABLE bool initializeIonizerFromPolChemDef();
  bool initialize();

  // Creates the polChemDef/polymer relationship.
  bool postInitialize();

  void closeEvent(QCloseEvent *event);

  void focusInEvent(QFocusEvent *event);
  void focusOutEvent(QFocusEvent *event);

  void createActions();
  void createMenus();

  void keyPressEvent(QKeyEvent *);

  void massSpectrumSynthesisMenuActivated(int index);
  Q_INVOKABLE bool
  loadIsotopicDataFromFile(const QString &file_path = QString());

  Q_INVOKABLE void setCumulatedProbabilities(double cumul_probs);
  Q_INVOKABLE void setNormalizationIntensity(double intensity);

  void traceColorPushButtonClicked();
  Q_INVOKABLE void setTraceColor(QColor color);
  Q_INVOKABLE void setTraceTitle(const QString &title);

  Q_INVOKABLE libXpertMassGui::MassPeakShaperConfigDlg *
  configureMassPeakShaper();
  Q_INVOKABLE void synthesizeMassSpectra();

  // The results-exporting functions. ////////////////////////////////
  Q_INVOKABLE void prepareResultsTxtString();
  //////////////////////////////////// The results-exporting functions.
};

/*  END CLASS JS REFERENCE
 *  namespace: MsXpS::MassXpert
 *  class name: SequenceEditorWnd
 */

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