//-----------------------------------------------------------------------------
//  Copyright (C) 2002-2025 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: Oct 30, 2025
//-----------------------------------------------------------------------------
#ifndef xyscanWindow_h
#define xyscanWindow_h

#include <ctime>
#include <utility>
#include <QSoundEffect>
#include <QString>
#include "xyscanUpdater.h"
#include "xyscanBaseWindow.h"

class QListWidget;
class QMenu;
class QLineEdit;
class QPushButton;
class QRadioButton;
class QComboBox;
class QGraphicsPixmapItem;
class QGraphicsLineItem;
class QGraphicsPathItem;
class QGraphicsSceneDragDropEvent;
class QDoubleSpinBox;
class QLabel;
class QToolBox;
class QCheckBox;
class QGridLayout;
class QShortcut;
class xyscanHelpBrowser;
class xyscanUpdater;
class xyscanGraphicsView;
class xyscanDataTable;
class xyscanErrorBarScanModeToolBox;
class xyscanScanTasksHandler;

using namespace std;

class xyscanWindow : public xyscanBaseWindow
{
    Q_OBJECT

public:
    explicit xyscanWindow(const QString& commandLineImageFile = QString());
    ~xyscanWindow() override;

    void openFromFile(const QString&);

    friend xyscanScanTasksHandler;

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

private slots:
    // File menu
    void open();
    void openRecent();
    void clearHistory();
    void save();
    void print();
    void finish();
    
    // Edit
    void editCrosshairColor();
    void editMarkerColor();
    void editPathColor();
    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 enablePathMeasuring(bool);
    void updateMeasureDisplay();
    void measurementController(bool = false);
    void normalizeUserScale();
    void clearMeasuredPath();

    // Developer
    void loadCalibrationPlot(bool = false);

    // Histogramming
    void updateHistogramDisplay();

private:
    void connectMenuActions();
    void connectToolBoxActions();
    void connectDockingWidgets();
    void createSettingMarkerActions();

    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();

    pair<double, double> measureDistance(QPointF&, QPointF&);

    bool checkForUnsavedData();

    QPointF scan(QPointF* = nullptr);

private:    
    QString mOpenFileDirectory;
    QString mSaveFileDirectory;
    QString mCurrentSource;
    
    QStringList mRecentFiles;
    
    QGraphicsPixmapItem *mCurrentPixmap;
    QImage *mCurrentShadowImage;

    QSoundEffect mSoundEffect;
    
    QShortcut *mCalibrationLinPlotShortcut;
    QShortcut *mCalibrationLogPlotShortcut;

    xyscanUpdater mUpdater;
    
    xyscanScanTasksHandler *mScanTasksHandler;

    QDateTime mLastReminderTime;

    const double mPointMarkerOffset = 0.5;

    double  mMarkerPixel[4];
    double  mMarkerPlotCoordinate[4];
    double  mMeasureUserScale;
    double  mMeasurePathLength;

    bool mScreenScanIsOn;
    bool mMeasuringIsOn; 
};

#endif

