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

 Copyright 2015 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 "Request.h"
//#include "PageView.h"

#include "MvQEditor.h"

class QComboBox;
class QLabel;
class QLineEdit;
class QToolButton;
class QSpinBox;
class QSplitter;
class QStakedWidget;
class QUndoStack;

class MvQPageItem;
class MvQPageView;

struct PaperRectangle;

class PaperSize
{
public:
    PaperSize(std::string n, float w, float h, std::string ori) :
        name_(n),
        width_(w),
        height_(h),
        orientation_(ori) {}
    std::string name() const { return name_; }
    double width() const { return width_; }
    double height() const { return height_; }
    void setWidth(double w) { width_ = w; }
    void setHeight(double h) { height_ = h; }
    std::string orientation() const { return orientation_; }

protected:
    std::string name_;
    double width_;
    double height_;
    std::string orientation_;
};

class PaperSizeHandler
{
public:
    PaperSizeHandler();

    void set(const Request&);
    void set(const std::string&, const std::string&, double, double);
    void save(Request&);
    PaperSize* current() { return current_; }
    double width();
    double height();
    bool isCustom() { return current_ == custom_; }
    std::string orientation() { return orientation_; }

    static const std::vector<PaperSize*>& stdSizes() { return std_; }

protected:
    std::string orientation_;

    PaperSize* current_;
    static std::vector<PaperSize*> std_;
    PaperSize* custom_;
};

class GridSnapHandler
{
public:
    GridSnapHandler();
    void setCurrent(int, int);
    void setCurrentValues(float, float);
    float x() const;
    float y() const;
    int xIndex() const { return xIndex_; }
    int yIndex() const { return yIndex_; }
    const std::string& units() const { return units_; }
    const std::vector<float>& values() const { return vals_; }


protected:
    std::vector<float> vals_;
    std::string units_;
    int xIndex_;
    int yIndex_;
};

class MvQPaperSizeWidget : public QWidget
{
    Q_OBJECT

public:
    MvQPaperSizeWidget(PaperSizeHandler*, QWidget* parent = nullptr);
    ~MvQPaperSizeWidget() override = default;
    void accept();

public slots:
    void slotSize(int);

protected:
    void updateState();

    PaperSizeHandler* paper_;
    QComboBox* sizeCb_;
    QLabel* oriLabel_;
    QComboBox* oriCb_;
    QLabel* widthLabel_;
    QLabel* heightLabel_;
    QLineEdit* widthEdit_;
    QLineEdit* heightEdit_;
};


class MvQGridSnapWidget : public QWidget
{
public:
    MvQGridSnapWidget(GridSnapHandler*, QWidget* parent = nullptr);
    ~MvQGridSnapWidget() override = default;
    void accept();

protected:
    GridSnapHandler* snap_;
    QComboBox* xCb_;
    QComboBox* yCb_;
};


class MvQPageSetupDialog : public QDialog
{
    Q_OBJECT

public:
    MvQPageSetupDialog(PaperSizeHandler*, GridSnapHandler*, QWidget* parent = nullptr);
    ~MvQPageSetupDialog() override = default;

public slots:
    void accept() override;

protected:
    MvQPaperSizeWidget* paper_;
    MvQGridSnapWidget* snap_;
};

class MvQGridSelector;

class MvQSplitDialog : public QDialog
{
    Q_OBJECT

public:
    MvQSplitDialog(QWidget* parent = nullptr);
    ~MvQSplitDialog() override = default;
    int row() const { return row_; }
    int column() const { return column_; }

public slots:
    void slotChangeMode(int);
    void slotRowChanged(int);
    void slotColumnChanged(int);
    void slotSelectionChanged(int, int);
    void accept() override;
    void reject() override;

protected:
    void closeEvent(QCloseEvent* event) override;
    void updateLabel();
    void readSettings();
    void writeSettings();

    int row_;
    int column_;
    int maxRow_;
    int maxColumn_;
    int maxGrRow_;
    int maxGrColumn_;
    QComboBox* modeCb_;
    QStackedWidget* stacked_;
    QLabel* label_;
    MvQGridSelector* selector_;
    QSpinBox* rowSpin_;
    QSpinBox* colSpin_;
};


class MvQGridSelector : public QWidget
{
    Q_OBJECT

public:
    MvQGridSelector(int, int, int, int, QWidget* parent = nullptr);
    ~MvQGridSelector() override = default;
    int row() const { return row_; }
    int column() const { return column_; }
    void setGridSize(int, int);
    void setSelection(int row, int col);

signals:
    void changed(int, int);

protected:
    void paintEvent(QPaintEvent* event) override;
    void resizeEvent(QResizeEvent* event) override;
    void mousePressEvent(QMouseEvent* event) override;
    void mouseMoveEvent(QMouseEvent* event) override;
    void mouseReleaseEvent(QMouseEvent* event) override;
    bool select(QPoint);

    int row_;
    int column_;
    int rowNum_;
    int columnNum_;
    int offset_;
    float dx_;
    float dy_;
    QColor rectColour_;
    QColor frameColour_;
    QColor selectedColour_;
};


class ViewEditor : public MvQEditor
{
    Q_OBJECT

public:
    ViewEditor(const IconClass&, const std::string&);
    ~ViewEditor() override;

    void setPaperSize(double, double);
    void getPaperSize(double&, double&);
    IconObject* defaultView();
    IconObject* makeIcon(Folder*, int, Request&);

public slots:
    void updateButtonStatus(int);
    void slotSnap(bool);
    void slotGrid(bool);
    void slotAddPage(bool);
    void slotDuplicateSelection(bool);
    void slotDeleteSelection(bool);
    void slotJoinSelection(bool);
    void slotSplitSelection(bool);
    void slotExpandSelection(bool);
    void slotSelectAll(bool);
    void slotConnectSelection(bool);
    void slotDisconnectSelection(bool);
    void slotSetupPage(bool);
    void slotViewChanged();

protected slots:
    void slotFilterItems(QString) override {}
    void slotShowDisabled(bool) override {}

protected:
    void readSettings(QSettings&) override;
    void writeSettings(QSettings&) override;

private:
    // No copy allowed
    ViewEditor(const ViewEditor&);
    ViewEditor& operator=(const ViewEditor&);

    void loadPages(IconObject*, const Request&);
    void loadSubPages(MvQPageItem*, IconObject*, const Request&);
    void loadPaperSize(const Request&);
    void savePaperSize(Request&);
    void savePages(IconObject*, Request&);
    void saveRectToRequest(QRectF, Request&);

    void apply() override;
    void reset() override;
    void close() override;
    void merge(IconObjectH) override;
    void replace(IconObjectH) override;
    std::string alternateEditor() override;

    Request request_;
    std::vector<IconObjectH> save_;

    // std::map<IconObjectH,PageViewH> cache_;

    QAction* snapAc_;
    QAction* gridAc_;
    PaperSizeHandler* paper_;
    GridSnapHandler* snap_;
    QUndoStack* undoStack_;
    MvQPageView* view_;
};

inline void destroy(ViewEditor**) {}
