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

 Copyright 2019 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 <QAbstractItemModel>
#include <QSettings>
#include <QWidget>

#include <vector>
#include <map>

class LanguageHelper;
class VerbFunctionHelpFunction;
class VerbFunctionHelpParam;
class VerbFunctionHelp;
class VerbFunctionHelpValueModel;
class EditorTheme;
class QTreeView;
class MvQTreeView;
class MvQColourWidget;

class ParamValueEditor : public QObject
{
    Q_OBJECT
public:
    ParamValueEditor(QString id, int index, QWidget* parent);
    virtual QString value() = 0;
    virtual void setParam(VerbFunctionHelpParam*) = 0;
    virtual QWidget* realWidget() = 0;
    virtual void clear() = 0;
    virtual void fontSizeUp() = 0;
    virtual void fontSizeDown() = 0;

signals:
    void valueChanged(QString);

protected:
    void broadcastChange();

    QString id_;
    int index_;
    VerbFunctionHelpParam* param_;
};

class ParamColourValueEditor : public ParamValueEditor
{
public:
    ParamColourValueEditor(QString id, int index, QWidget* parent);
    QString value();
    void setParam(VerbFunctionHelpParam*);
    QWidget* realWidget();
    void clear();
    void fontSizeUp() {}
    void fontSizeDown() {}

protected:
    MvQColourWidget* colW_;
};

class ParamListValueEditor : public ParamValueEditor
{
    Q_OBJECT
public:
    ParamListValueEditor(QString id, int index, QWidget* parent);
    QString value();
    void setParam(VerbFunctionHelpParam*);
    QWidget* realWidget();
    void clear();
    void fontSizeUp();
    void fontSizeDown();

protected slots:
    void slotValueSelected(const QModelIndex&);

protected:
    QTreeView* valueTree_;
    VerbFunctionHelpValueModel* valueModel_;
};

class VerbFunctionHelpParamModel : public QAbstractItemModel
{
public:
    VerbFunctionHelpParamModel(QObject* parent);

    int columnCount(const QModelIndex& parent = QModelIndex()) const;
    int rowCount(const QModelIndex& parent = QModelIndex()) const;
    QVariant data(const QModelIndex&, int role = Qt::DisplayRole) const;
    QVariant headerData(int, Qt::Orientation, int role = Qt::DisplayRole) const;
    Qt::ItemFlags flags(const QModelIndex& index) const;
    QModelIndex index(int, int, const QModelIndex& parent = QModelIndex()) const;
    QModelIndex parent(const QModelIndex&) const;

    VerbFunctionHelpFunction* helpData() const { return data_; }
    void setHelpData(VerbFunctionHelpFunction*);
    QModelIndex paramToIndex(VerbFunctionHelpParam* param) const;
    void clear();

private:
    bool hasData() const;

    VerbFunctionHelpFunction* data_;
};

class VerbFunctionHelpValueModel : public QAbstractItemModel
{
public:
    VerbFunctionHelpValueModel(QObject* parent);

    int columnCount(const QModelIndex& parent = QModelIndex()) const;
    int rowCount(const QModelIndex& parent = QModelIndex()) const;
    QVariant data(const QModelIndex&, int role = Qt::DisplayRole) const;
    QVariant headerData(int, Qt::Orientation, int role = Qt::DisplayRole) const;
    Qt::ItemFlags flags(const QModelIndex& index) const;
    QModelIndex index(int, int, const QModelIndex& parent = QModelIndex()) const;
    QModelIndex parent(const QModelIndex&) const;

    void setHelpData(VerbFunctionHelpParam*);
    void clear();

private:
    bool hasData() const;

    VerbFunctionHelpParam* data_;
};


namespace Ui
{
class VerbFunctionHelpWidget;
}

class VerbFunctionHelpWidget : public QWidget
{
    Q_OBJECT

public:
    explicit VerbFunctionHelpWidget(QWidget* parent = nullptr);
    ~VerbFunctionHelpWidget() {}

    void setLanguage(LanguageHelper*);
    void setCodeEditorTheme(EditorTheme*, QFont);
    VerbFunctionHelpFunction* function(QString name) const;
    bool showFunction(QString functionName);
    void showFunction(VerbFunctionHelpFunction* function);
    void showParam(QString functionName);
    void showParam(VerbFunctionHelpFunction* function,
                   VerbFunctionHelpParam* param);

    QString selection(bool highlightValue = false) const;
    bool hasData() const;

    void writeSettings(QSettings&);
    void readSettings(QSettings&);

signals:
    void sendTextToBeInsertedIntoFunctionCall(QString text);
    void insertRequested(QString);
    void functionListRequested();

protected slots:
    void slotParamSelected(const QModelIndex& idx, const QModelIndex& idxPrev);
    void slotEditorValueChanged(QString);
    void slotInsert();
    void slotCopy();
    void slotWebDoc();
    void slotExtendSelection(int);
    void slotFontSizeDown();
    void slotFontSizeUp();

private:
    void showParamCore(VerbFunctionHelpFunction* function,
                       VerbFunctionHelpParam* param);
    void updateSelectionLabel();
    void updateFunctionLabel(VerbFunctionHelpFunction* function);
    void updateButtonStatus();
    int currentTreeFontSize() const;

    Ui::VerbFunctionHelpWidget* ui_;
    VerbFunctionHelpParamModel* paramModel_;
    QTreeView* valueTree_;
    EditorTheme* editorTheme_;
    LanguageHelper* language_;
    QMap<QString, ParamValueEditor*> editors_;
    ParamValueEditor* currentEditor_;
    bool extendSelection_;
};
