/***************************** LICENSE START ***********************************

 Copyright 2016 ECMWF and INPE. This software is distributed under the terms
 of the Apache License version 2.0. In applying this license, ECMWF does not
 waive the privileges and immunities granted to it by virtue of its status as
 an Intergovernmental Organization or submit itself to any jurisdiction.

 ***************************** LICENSE END *************************************/

#pragma once

#include <string>

#include <QComboBox>
#include <QMessageBox>
#include <QModelIndex>
#include <QPointF>
#include <QSettings>

#include "MvQDragDrop.h"
#include "MvQMainWindow.h"
#include "MvQMenuItem.h"

#include "Presentable.h"

class MvRequest;

class QAction;
class QComboBox;
class QGraphicsRectItem;
class QGraphicsScene;
class QGraphicsView;
class QSlider;
class QUndoStack;

class ExportDialog;
class MgQPlotScene;
class MgQSceneItem;
class MvQDrop;
class MvQPlotView;
class MvQProgressBarPanel;
class MvQZoomStackWidget;

class ShareTarget;
class MvQProgressManager;

class uPlotBase;

class ExportMessageBox : public QMessageBox
{
    Q_OBJECT
public:
    ExportMessageBox(uPlotBase*);
protected slots:
    void doDelayedProc();

protected:
    uPlotBase* owner_;
};

class uPlotBase : public MvQMainWindow
{
    Q_OBJECT
    friend class ExportMessageBox;

public:
    uPlotBase(QWidget* parent = nullptr);
    ~uPlotBase() override;

    void setPlot(float hor, float ver);
    void setPlotWidgetSize(float hor, float ver);
    // void messageToLogWindow (const std::string&, int severity);

    MvQPlotView* plotView() { return plotView_; }
    MgQPlotScene* plotScene() { return plotScene_; }

    virtual void newRequestForDriversBegin() = 0;
    virtual void newRequestForDriversEnd() = 0;
    virtual void progressMessage(const std::string&) {}

    void processContentsRequest(MvRequest&);

    void setPresentable(Presentable& owner)
    {
        owner_ = &owner;
    }

    static Presentable* owner() { return owner_; }

    std::string currentWorkDir() const;

    virtual MvRequest SuperPageRequest() { return {}; }

    void tempDir(std::string& dir)
    {
        uPlotTempDir_ = dir;
    }
    static std::string& tempDir()
    {
        return uPlotTempDir_;
    }

#ifdef METVIEW_WEATHER_ROOM
    // Wheater room
    bool plotWeatherRoom(bool checkSync = false);
#endif

signals:
    void plotWindowUpdated();
    void plotScaleChanged();
    void sendDropRequest(MvRequest*);

public slots:
    void slotEnableAntialias(bool);
    void slotZoomStackLevelChanged(QString, int);
    void slotPerformZoom(const std::string& sid, const std::string& def);
    void slotStepCacheStateChanged();
    void slotLoadExportDialog();
    void slotLoadPrintDialog();
    void slotGenerateMacro();
    void slotLoadEcChartsDialog();
    void slotShowAboutBox();
    void slotSizeChanged(int);
    void slotSizeDown();
    void slotSizeUp();
    void slotBuildContextMenu(const QPoint&, const QPointF&);
    void slotResizeEvent(const QSize&);
    void slotProcessDropInView(const MvQDrop&, QPoint);
    virtual void slotSetActiveScene(MgQSceneItem*) = 0;

    // Weather room
    void slotLoadWeatherRoomDialog();
    void slotEnableWroomSync(bool);

    // Export files
    void processExport();
    void processExportQt();

protected slots:
    void startExportDialogMsgBox();
    void processExportDialogRequest();
    virtual void slotAddRibbonEditor(QWidget*) {}

protected:
    void SetupResources();

    virtual void setupViewActions();
    void setupZoomActions();
    void setupHelpActions();
    void setupContextMenuActions();

    void updateZoomActionState();
    void updateResizeActionState();

    virtual bool setDropTarget(QPoint) = 0;
    virtual bool setDropTargetInView(QPoint) = 0;
    virtual int currentStep() = 0;
    virtual int stepNum() = 0;

    void setCustomSize(int);
    float currentSizeRatio();
    void changeSize(int, bool renderIt = true);
    int screenResolutionInDpi();

    virtual void loadStarted() {}
    virtual void loadFinished() {}

    virtual void writeSettings() = 0;
    virtual void readSettings() = 0;

    static Presentable* owner_;

    // Temporary directory name related to this session.
    // It can be used to store temporary files ,e.g. Layers icon editing.
    static std::string uPlotTempDir_;

    MvQMainWindow::MenuItemMap menuItems_;

    MvQPlotView* plotView_{nullptr};
    MgQPlotScene* plotScene_{nullptr};

    // Zoom
    MvQZoomStackWidget* zoomStackWidget_{nullptr};
    QAction* actionZoomUp_{nullptr};
    QAction* actionZoomDown_{nullptr};

    // Paste
    QAction* actionPaste_{nullptr};

    // Symbols
    QUndoStack* undoStack_{nullptr};
    QAction* actionRedo_{nullptr};
    QAction* actionUndo_{nullptr};

    // Context menu
    QAction* actionContextSelectScene_{nullptr};
    QAction* actionContextZoomUp_{nullptr};
    QAction* actionContextZoomDown_{nullptr};

    // Active scene
    MgQSceneItem* activeScene_{nullptr};
    std::string prevActiveSceneId_;

    // Size
    enum SizeOptions
    {
        FitToWindow = -1,
        FitToWidth = -2,
        FitToHeight = -3
    };
    QAction* actionSizeDown_{nullptr};
    QAction* actionSizeUp_{nullptr};
    QComboBox* sizeCombo_{nullptr};
    QList<int> predefSizeValues_;
    int sizeMinValue_;
    int sizeMaxValue_;
    int sizeValueStep_;
    int customSizeItemIndex_;
    float oriPlotWidthInCm_;
    float oriPlotHeightInCm_;

#ifdef METVIEW_WEATHER_ROOM
    // Weather room
    void uploadWeatherRoom(const std::string&);
    void outputDeviceWeatherRoom(MvRequest&);
    bool syncWeatherRoom()
    {
        return wroomSync_;
    }

    bool wroomSync_;           // flag indicating if a plot should be sent to the video wall
    int wroomCell_;            // cell number
    std::string wroomWall_;    // wall id
    std::string wroomFormat_;  // wall output graphics format
#endif

    MvRequest delayedExportDialogRequest_;

    // Progress Bar
    MvQProgressBarPanel* progressBar_{nullptr};

    // Export animated gif
    MvRequest setExportVariables(MvRequest*);
    // MvQProgressManager* pm_ {0};  // progress manager
    std::string export_format_;    // output format
    std::string export_fname_;     // output path+filename
    std::string export_tmp_path_;  // temporary path to store temporary files

    // Export the contents of the Display Window
    // false = call Magics to create the output file
    // true  = call Qt (if Display Window contains features/symbols)
    bool export_qt_{false};
};
