#ifndef QFITSMAINWINDOW_H
#define QFITSMAINWINDOW_H

#include <QWidget>
#include <QImage>
#include <QString>
#include <QLabel>
#include <QMenuBar>
#include <QCheckBox>
#include <QComboBox>
#include <QSpinBox>
#include <QToolButton>
#include <QProgressBar>
#include <QMainWindow>
#include <QSplitter>
#include <QFileSystemWatcher>
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
#include <QRegExp>
#else
#include <QRegularExpression>
#endif /* QT_VERSION */

#include "QFitsGlobal.h"
#include "QFitsPreferences.h"
#include "fits.h"
#include "QPgplot.h"

class RGBDialog;
class dpCombineDialog;
class QFitsToolBar;
class CubeDisplayDialog;
class PlotOptionsDialog;
class BlinkDialog ;
class qFitsViewPreferences;
class QFitsViewingTools;
class MainWindow;
class QFits2dFit;
class imRedMarkpos;
class QFitsBaseBuffer;
class QFitsSingleBuffer;
class QFitsCubeSpectrum;
class QFitsMainView;
class QFitsHeaderView;
class dpWatchdirDialog;
class dpGalfitDialog;
class About;
class DpHelp;
class moreColourmaps;
class ImageDisplay;
class dpMpfitDialog;
class QFitsToolsWidget;

#ifdef HAS_PLOTTING
class dpPlplotWindow;
#endif /* HAS_PLOTTING */
#ifdef HAS_PLPLOT
class dpPg2PlplotWindow;
#endif /* HAS_PLPLOT */

#ifdef LBT
class dpLuciMaskAlignDialog;
#endif

class QFitsMainWindow : public QMainWindow {
    Q_OBJECT
//----- Functions -----
public:
    QFitsMainWindow(QWidget *parent = NULL);
    ~QFitsMainWindow();

    void StartDpuser();

    std::string getCurrentBufferIndex();
    QFitsBaseBuffer* getCurrentBuffer();
    QFitsBaseBuffer* getBuffer(std::string i);
    QFitsSingleBuffer* getMarkedSingleBuffer();

    QString createCaption(std::string, bool);
    virtual void keyPressEvent(QKeyEvent *e);
    bool headerVisible();
//#ifdef HAS_VTK
    void updateCubeSpectrumViewer();
//#endif
    void updateViewingtools();
    void updateWedge();
    void updateTools(int, int, int, int, bool updateTotal = true);
    void updateTotalVisibleRect();
    void setMagnifierCenterPos(int, int);
    void updateMenuScaling(int);
    void applyAppearance();
    void setActualSB(QFitsSingleBuffer *sb) { actualSB = sb; }
    QFitsSingleBuffer* getActualSB() { return actualSB; }
    QFitsSingleBuffer* getActualMarkedSB();

protected:
    void closeEvent(QCloseEvent *);
    virtual void dragEnterEvent(QDragEnterEvent* event);
    virtual void dropEvent(QDropEvent* event);

    virtual void resizeEvent(QResizeEvent *r);
//    #ifdef HAS_VTK
    void showCurrentView(std::string which , dpViewMode previousMode = ViewUndefined);
//    #else
//    void showCurrentView(int which);
//    #endif
    void arrangeChildren();
private:
    void updateBufferList();

//----- Slots -----
public slots:
    void updateScaling();
    void copyImage();
    void pasteImage();
    void menuZoomTriggered(QAction *);
    void imredClicked(int);
    void imredTriggered(QAction *);
    void imfilterTriggered(QAction *);
    void imcubeTriggered(QAction *);
    void spectralTriggered(QAction *);
    void userMenuTriggered(QAction *);
    void scalingTriggered(QAction *);
    void viewTriggered(QAction *);
    void buffersTriggered(QAction *);
    void windowsTriggered(QAction *);
    void updateWindowsMenu();
    void helpTriggered(QAction *);
    void moreColormaps(void);
    void viewClicked(dpViewMode);
    void helpClicked(int);
    void buffersClicked(int);
    void showSpectrum(bool);
    void adaptFileMenu();
    void showRGBDialog();
    void showCombineDialog();
    void showMpfitDialog();
    void moveToNextBuffer();
    void moveToPreviousBuffer();
#ifdef HAS_PLOTTING
    void showPlottingDialog();
#endif /* HAS_PLOTTING */
    void updateImageOptions();
    void updateCubeOptions();
    void updateLinemapInfo(int);
    void fillBufferMenu();
    void fillUserMenu();
    void fillViewMenu();
    void reloadImage();
    void dpuserInterrupt();
    void dpuserExecuteScript();
    void dpuserChangeDirectory();
    void dpuserCopyHistory();
    void updateOrientation();
    void updateToolbar();
    void longslitChangedValues(int, int, double, int, double);
    void longslitChangedCenter(int, int);
    void longslitChangedAngle(double);
    void markposNewPosition(int, int);
    void ellipticalProfileChangedValues(int, int, double, double, int);
    void markposChangedValues(QVector <int>);
    void updateCubeMode(int);
    void blinkTimerTimeout();
    void DisplayFITSHeader();
    void LoadClicked();
    void ImportClicked();
    void userMenuClicked(int);
    void dpuserProgress(const int &, const QString &);
    void dpuserHelp(const QString &);
    void dpuserVar(const std::string &);
    void dpuserView(const std::string &);
    void dpuserCommand(const QString &cmd, const QString &arg, const int &option);
    void updatePgplot(const int &, const QImage &);
    void updatePgplot(const int &, const int &, const int &);
    void LoadFile(bool);
    void FileSystemChanged(const QString &);
    void setDirToWatch(const dpString &, const dpString &, const dpString &);

//----- Signals -----
signals:
    void currentBufferChanged(int);
    void longslitCenterChanged(int, int);
    void longslitAngleChanged(double);
    void markPosition(int, int);
    void setVisibleRect(int, int);
    void progressActive(bool);

//----- Members -----
public:
    QSplitter           *splitter, *hsplitter;
    QMenu               *imfilter, *imcube, *scaling, *map, *zoom, *options, *imred,
                        *spectral, *view, *buffer, *windows, *help;
    QAction             *invertAction;
    QMenu               *userMenu;
    QMap<int,std::string>       bufferMenuList;
    QFitsViewingTools   *viewingtools;
    QWidget             *emptyTool;
    QFits2dFit          *fitter2d;
    imRedMarkpos        *markposDialog;
    QFitsCubeSpectrum   *spectrum;
    MainWindow          *scriptEditor;
    RGBDialog           *rgbdialog;
    dpCombineDialog     *combinedialog;
    dpMpfitDialog       *mpfitdialog;
    QFitsHeaderView     *headerView;
    QFitsPrefDialog     *preferences;

#ifdef HAS_PLOTTING
    dpPlplotWindow      *plplotWindow;
#endif /* HAS_PLOTTING */
#ifdef HAS_PLPLOT
    dpPg2PlplotWindow   *pg2plplotWindow[10];
#endif /* HAS_PLPLOT */

#ifdef LBT
    dpLuciMaskAlignDialog *luciMaskAlign;
#endif
    dpWatchdirDialog    *watchdir;
    dpGalfitDialog      *galfit;
    About               *about;
    DpHelp              *dphelp;
    moreColourmaps      *morecolourmaps;
    ImageDisplay        *imagedisplay;
    CubeDisplayDialog   *cubeDisplayDialog;
    PlotOptionsDialog   *plotoptions;
    BlinkDialog         *blinkdialog;
    QStringList         blinklist;
    QFitsToolBar        *mytoolbar;
    QProgressBar        *progressbar;
    QTimer              *blinkTimer;
    QActionGroup        *mapActions,
                        *viewActions;
    int                 viewingTools_width, toolbar_height,
                        blinkcount;
    bool                bufferChangedByKey,
                        overrideSet,
                        zoomCorr_spectrumVisible,
                        zoomCorr_wedgeVisible,
                        zoomCorr_ComboZoomTriggered;
    QFitsMainView       *main_view;
    QPgplotDialog       *qpgplot_windows[10];
    QActionGroup        *scalingMethods;
    QFileSystemWatcher  fsWatcher;
    QString             FileSystemChangedAction;
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    QRegExp             FileSystemChangedPattern;
#else
    QRegularExpression  FileSystemChangedPattern;
#endif /* QT_VERSION */
    QFitsToolsWidget    *toolsWidget;

private:
    double              centralWavelength;
    QByteArray          windowState;
    QAction             *menu_displayFitsHeader, *nextBufferAction, *previousBufferAction;
    QFitsSingleBuffer   *actualSB;

    QStringList         dirEntryList;
};

#endif /* FITSVIEW_H */
