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

 Copyright 2013 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 <QtGlobal>
#include <QDialog>
#include <QLabel>
#include <QSettings>

#include "Editor.h"

class QAbstractButton;
class QAction;
class QActionGroup;
class QDialogButtonBox;
class QDrag;
class QHBoxLayout;
class QLabel;
class QLineEdit;
class QPlainTextEdit;
class QPushButton;
class QStackedLayout;
class QStackedWidget;
class QToolBar;
class QToolButton;
class QVBoxLayout;

class MvQDrawerPanel;
class MvQFolderModel;
class MvQIconTemplateView;
class MvQEditor;
class MessageLabel;
class MvQEditorState;

class MvQEditorDragLabel : public QLabel
{
    Q_OBJECT
public:
    MvQEditorDragLabel(QPixmap, int, QWidget* parent = nullptr);
    void setIconObject(IconObject*);

signals:
    void dragStarted();

protected:
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
    void enterEvent(QEnterEvent*) override;
#else
    void enterEvent(QEvent*);
#endif
    void leaveEvent(QEvent*) override;
    void mousePressEvent(QMouseEvent*) override;
    void mouseMoveEvent(QMouseEvent*) override;
    void performDrag(Qt::DropAction, QPoint);
    QDrag* buildDrag(IconObject* dragObj, QPoint dragPos);

    IconObject* obj_{nullptr};
    bool canDrag_{false};
    QPoint startPos_;
    QPixmap oriPix_;
    QPixmap highlightPix_;
};

class MvQEditorHeader : public QWidget
{
    Q_OBJECT

public:
    MvQEditorHeader(MvQEditor*, QPixmap);
    void updateLabel(IconObject*);
    void lock(bool);

public slots:
    void slotStartEdit(bool);
    void slotAcceptEdit(bool);
    void slotCancelEdit(bool);

protected:
    void paintEvent(QPaintEvent*) override;

    MvQEditor* owner_{nullptr};
    QStackedLayout* stackLayout_{nullptr};
    QLabel* label_{nullptr};
    QToolButton* renameTb_{nullptr};
    QLineEdit* edit_{nullptr};
    IconObject* obj_{nullptr};
    MvQEditorDragLabel* pixLabel_{nullptr};
};

class MvQEditorTextPanel : public QWidget
{
    Q_OBJECT

public:
    MvQEditorTextPanel(const IconClass&, Editor*, QWidget*);
    bool check(bool fromSave = true);
    void setObject(IconObject*);
    void save();
    void load();

public slots:
    void slotTextChanged();

protected slots:
    void doNotShowWarningAgain();

private:
    void loadRequestFile();
    void readSettings();
    void writeSettings();

    static bool showEditWarning_;
    const IconClass& class_;
    Editor* owner_{nullptr};
    IconObject* current_{nullptr};
    QPlainTextEdit* te_{nullptr};
    MessageLabel* infoLabel_{nullptr};
    MessageLabel* warnLabel_{nullptr};
    MessageLabel* msgLabel_{nullptr};
    bool correct_{true};
    bool beingLoaded_{false};
};

class MvQEditorPythonPanel : public QWidget
{
public:
    MvQEditorPythonPanel(const IconClass&, Editor*, QWidget*);

//    bool check(bool fromSave = true);
    void setObject(IconObject*);
//    void save();
    void load();

//public slots:
//    void slotTextChanged();

protected:
//    void loadRequestFile();

    const IconClass& class_;
    Editor* owner_{nullptr};
    IconObject* current_{nullptr};
    QPlainTextEdit* te_{nullptr};
    MessageLabel* warnLabel_{nullptr};
    MessageLabel* msgLabel_{nullptr};
    bool correct_{true};
    bool beingLoaded_{false};
};


class MvQEditor : public QDialog, public Editor
{
    Q_OBJECT

    friend class MvQEditorState;
    friend class MvQEditorGuiState;
    friend class MvQEditorTextState;
    friend class MvQEditorPythonState;

public:
    MvQEditor(const IconClass& name, const std::string& kind, QWidget* parent = nullptr);
    ~MvQEditor() override;

    void changed() override;
    virtual void merge(IconObjectH) = 0;
    virtual void replace(IconObjectH) = 0;
    void rename(QString);

    // Observer method
    void iconChanged(IconObject*) override;

public slots:
    void slotChangeView(QAction*);
    void slotButtonClicked(QAbstractButton*);
//    void accept() override;
//    void reject() override;
    void slotTextChanged();

protected slots:
    virtual void slotFilterItems(QString) = 0;
    virtual void slotShowDisabled(bool) = 0;
    void slotWebDoc();
    void pixLabelDragStarted();

protected:
    enum ViewMode
    {
        LineViewMode = 0,
        TextViewMode = 1,
        PythonViewMode = 2
    };

    bool eventFilter(QObject* obj, QEvent* event) override;
    void setupShowDisabledActions();
    void setupLineFilter();
    void updateFilterCountLabel();
    virtual int filterNonMatchCount() { return 0; }
    bool showDisabled() const;

    void addToToolBar(QList<QAction*>);
    void raiseIt() override;
    void showIt() override;
    void closeIt() override;
    virtual void apply() = 0;
    virtual void reset() = 0;
    virtual void close() = 0;
    void edit() override;
    void temporary() override;
    void concludeAccept();
    void concludeReject();
    void closeEvent(QCloseEvent*) override;
    void readSettings();
    void writeSettings();
    virtual void readSettings(QSettings&) = 0;
    virtual void writeSettings(QSettings&) = 0;

//    bool isTextMode() const;
    void transitionTo(MvQEditorState* state);

    QLabel* headerLabel_{nullptr};
    QLineEdit* headerEdit_{nullptr};
    MvQEditorHeader* headerPanel_{nullptr};
    QAction* showDisabledAc_{nullptr};
    QLineEdit* filterLe_{nullptr};
    QLabel* filterCountLabel_{nullptr};
    QAction* sepAc_{nullptr};
    QAction* guiAc_{nullptr};
    QAction* textAc_{nullptr};
    QAction* pyAc_{nullptr};
    QActionGroup* viewAg_{nullptr};
    QAction* webAc_{nullptr};

    QVBoxLayout* centralLayout_{nullptr};

    QDialogButtonBox* buttonBox_{nullptr};
    QPushButton* savePb_{nullptr};
    QPushButton* okPb_{nullptr};
    QPushButton* cancelPb_{nullptr};
    QPushButton* resetPb_{nullptr};

    QStackedWidget* viewSw_{nullptr};
    MvQDrawerPanel* drawerPanel_{nullptr};
    bool drawerFilled_{false};
    QToolBar* toolbarLeft_{nullptr};
    QToolBar* toolbarRight_{nullptr};
    MvQEditorTextPanel* textPanel_{nullptr};
    MvQEditorPythonPanel* pyPanel_{nullptr};

private:
    void updateWindowTitle();

    QHBoxLayout* toolBarLayout_{nullptr};
    bool ignoreChange_{false};
    MvQEditorState* state_{nullptr};
};
