//-----------------------------------------------------------------------------
//  Copyright (C) 2002-2020 Thomas S. Ullrich
//
//  This file is part of "xyscan".
//
//  This file may be used under the terms of the GNU General Public License.
//  This project is free software; you can redistribute it and/or modify it
//  under the terms of the GNU General Public License.
//  
//  Author: Thomas S. Ullrich
//  Last update: Mar 9, 2020
//-----------------------------------------------------------------------------
#ifndef xyscanWindow_h
#define xyscanWindow_h

#include <ctime>
#include <QMainWindow>
#include <QSoundEffect>
#include <QString>
#include "xyscanUpdater.h"
#include <QtCharts>
#include <QBarSet>

class QAction;
class QActionGroup;
class QListWidget;
class QMenu;
class QGraphicsView;
class QGraphicsScene;
class QLineEdit;
class QPushButton;
class QRadioButton;
class QComboBox;
class QGraphicsPixmapItem;
class QGraphicsLineItem;
class QGraphicsSceneDragDropEvent;
class QDoubleSpinBox;
class QLabel;
class QToolBox;
class QCheckBox;
class QGridLayout;
class QShortcut;
class xyscanAbout;
class xyscanHelpBrowser;
class xyscanUpdater;
class xyscanGraphicsView;
class xyscanDataTable;
class xyscanErrorBarScanModeToolBox;
class xyscanScanTasksHandler;

class xyscanWindow : public QMainWindow
{
    Q_OBJECT

public:
    xyscanWindow();
    ~xyscanWindow();
 
    void openFromFile(const QString&);

    friend xyscanScanTasksHandler;

protected:
    bool eventFilter(QObject*, QEvent*);
    void closeEvent(QCloseEvent*);

private slots:
    // File menu
    void open();
    void openRecent();
    void clearHistory();
    void save();
    void print();
    void finish();
    
    // Edit
    void editCrosshairColor();
    void editMarkerColor();
    void editComment();
    void pasteImage(); 
    
    // View
    void showPrecision();
    
    // Help menu
    void checkForUpdates();
    void about();
    void help();
    
    // Setting markers and define their coordinates
    void setPlotCoordinateValueForMarker(int markerType);
    
    // Axis scale, image scale and rotation ange
    void rotateImage(double);
    void scaleImage(double);
    void zoomScale(double);
    void updateWhenAxisScaleChanged();

    // Drops
    void loadDroppedFile(QString);
    
    // Updater
    void userWasRemindedOfAvailableUpdate();
    void updateSignificantDigits(QAction*);
    
    // Transparency and screen scan
    void enableScreenScan(bool);
    
    // Measuring
    void enableMeasuring(bool);
    void updateMeasureDisplay();
    void normalizeUserScale();

    // Developer
    void loadCalibrationPlot(bool = false);

    // Histogramming
    void updateHistogramDisplay();

private:
    void createMenuActions();
    void createSettingMarkerActions();
    void createMenus();
    void createStatusBar();
    void createTableDockingWidget();
    void createZoomDockingWidget();
    void createHistogramDockingWidget();
    void createCoordinateToolBoxItem(QWidget*);
    void createMeasureToolBoxItem(QWidget*);
    void createAxisSettingsToolBoxItem(QWidget*);
    void createAdjustmentToolBoxItem(QWidget*);    
    void createMarker();
    void createCrosshair();
    void createHelpBrowser();
    void createToolBox();
    void createToolTips();
    
    void loadSettings();
    void writeSettings();
    
    void loadPixmap(QPixmap*);
    void updatePixelDisplay();
    void updateZoomDisplay();
    void updateStatusBarCoordinateDisplay();
    void updatePlotCoordinateDisplay();
    void enableSignificantDigitsMenu(bool);
    void ensureCursorVisible();
    void handleKeyEvent(QKeyEvent*);
    bool readyForScan();
    int  numberOfMarkersSet();
    void resetMarker();
    
    bool checkForUnsavedData();

    QPointF scan(QPointF* = nullptr);

private:    
    enum {mXLower, mXUpper, mYLower, mYUpper};
    enum {mPixelUnits, mPlotUnits, mUserUnits};
    enum {mHorizontalAndVerticalHistogram=0, mHorizontalHistogram, mVerticalHistogram};
    enum {mMaxRecentFiles = 5};
    enum {mMaxSignificantDigits = 16};

    QWidget *mCentralWidget;
    QWidget *mPlotAdjustmentItem;
    QWidget *mAxisSettingsItem;
    QWidget *mErrorScanModeItem;
    QWidget *mCoordinatesItem;
    QWidget *mMeasureItem;

    xyscanGraphicsView *mImageView;
    QGraphicsView      *mZoomView;
    QGraphicsScene     *mImageScene;
    
    QMenu *mFileMenu;
    QMenu *mEditMenu;
    QMenu *mViewMenu;
    QMenu *mHelpMenu;
    QMenu *mRecentFilesMenu;
    QMenu *mSignificantDigitsMenu;

    QToolBox *mToolBox;

    QDockWidget *mTableDock;
    QDockWidget *mZoomDock;
    QDockWidget *mHistogramDock;

    QBarSeries *mBarSeries;

    QLineEdit *mPixelXDisplay;
    QLineEdit *mPixelYDisplay;
    QLineEdit *mPlotXDisplay;
    QLineEdit *mPlotYDisplay;
    QLineEdit *mMeasureDXDisplay;
    QLineEdit *mMeasureDYDisplay;
    QLineEdit *mMeasureDRDisplay;
    QLineEdit *mMeasureDADisplay;

    QAction *mOpenAction;
    QAction *mSaveAction;
    QAction *mPrintAction;
    QAction *mFinishAction;
    QAction *mDeleteLastAction;
    QAction *mDeleteAllAction;
    QAction *mEditCommentAction;
    QAction *mEditCrosshairColorAction;
    QAction *mEditMarkerColorAction;
    QAction *mAboutAction;
    QAction *mHelpAction;
    QAction *mCheckForUpdatesAction;
    QAction *mSetLowerXAction;
    QAction *mSetUpperXAction;
    QAction *mSetLowerYAction;
    QAction *mSetUpperYAction;
    QAction *mPasteImageAction;
    QAction *mRecentFileAction[mMaxRecentFiles];
    QAction *mSignificantDigitsAction[mMaxSignificantDigits];
    QAction *mClearHistoryAction;
    QAction *mShowPrecisionAction;
    QAction *mScreenScanAction;
    QAction *mShowTooltipsAction;
    
    QActionGroup *mSignificantDigitsActionGroup;
    
    QPushButton *mSetLowerXButton;
    QPushButton *mSetUpperXButton;
    QPushButton *mSetLowerYButton;
    QPushButton *mSetUpperYButton;
    QPushButton *mStartMeasureButton;

    QLineEdit *mUpperYValueField;
    QLineEdit *mLowerYValueField;
    QLineEdit *mUpperXValueField;
    QLineEdit *mLowerXValueField;
    QLineEdit *mMeasureUserScaleField;

    QRadioButton *mLogXRadioButton;
    QRadioButton *mLogYRadioButton;

    QComboBox *mMeasureScaleComboBox;
    QComboBox *mHistogramModeComboBox;

    QDoubleSpinBox *mAngleSpinBox;
    QDoubleSpinBox *mScaleSpinBox;
    QDoubleSpinBox *mZoomSpinBox;
    
    QCheckBox *mMeasureAngleRadiansCheckBox;

    xyscanDataTable *mDataTable;

    QString mOpenFileDirectory;
    QString mSaveFileDirectory;
    QString mCurrentSource;
    
    QStringList mRecentFiles;
    
    QGraphicsPixmapItem *mCurrentPixmap;
    QGraphicsPixmapItem *mPointMarker;
    QGraphicsLineItem   *mMarker[4];

    QImage *mCurrentShadowImage;

    QGraphicsLineItem *mCrosshairH;
    QGraphicsLineItem *mCrosshairV;
    QGraphicsLineItem *mMeasureLine;
    
    QLabel *mPlotInfoLabel;
    QLabel *mMessageLabel;
    QLabel *mXCoordinateLabel;
    QLabel *mYCoordinateLabel;
    QLabel *mMeasuredDistanceLabel;
    QLabel *mMeasureScaleValueLabel;

    QColor  mCrosshairColor;
    QColor  mMarkerColor;

    QSoundEffect mSoundEffect;
    
    QShortcut *mCalibrationLinPlotShortcut;
    QShortcut *mCalibrationLogPlotShortcut;

    xyscanAbout       *mAboutDialog;
    xyscanHelpBrowser *mHelpBrowser;
    xyscanUpdater      mUpdater;
    
    xyscanErrorBarScanModeToolBox *mErrorBarScanModeToolBox;

    xyscanScanTasksHandler *mScanTasksHandler;

    double  mMarkerPixel[4];
    double  mMarkerPlotCoordinate[4];
    double  mImageAngle;
    double  mImageScale;
    double  mZoomScale;
    double  mMeasureUserScale;

    const double mPointMarkerOffset = 0.5;
    const int    mHistogramRange = 5;



    QDateTime mLastReminderTime;
    
    bool mScreenScanIsOn;
    bool mMeasuringIsOn;
    
    unsigned int mSignificantDigits = 6;
};

#endif

