/*
 *  SPDX-FileCopyrightText: 2014 Boudewijn Rempt <boud@valdyas.org>
 *
 *  SPDX-License-Identifier: GPL-2.0-or-later
 */
#ifndef KIS_DLG_LAYER_STYLE_H
#define KIS_DLG_LAYER_STYLE_H

#include <QUuid>

#include <KoDialog.h>

#include "kis_types.h"

#include "ui_wdglayerstyles.h"
#include "ui_wdgBevelAndEmboss.h"
#include "ui_wdgblendingoptions.h"
#include "ui_WdgColorOverlay.h"
#include "ui_wdgContour.h"
#include "ui_wdgdropshadow.h"
#include "ui_WdgGradientOverlay.h"
#include "ui_wdgInnerGlow.h"
#include "ui_WdgPatternOverlay.h"
#include "ui_WdgSatin.h"
#include "ui_WdgStroke.h"
#include "ui_wdgstylesselector.h"
#include "ui_wdgTexture.h"


#include <QSortFilterProxyModel>

#include <kis_psd_layer_style.h>
#include <KisTemporaryResourceStorageLock.h>


class QListWidgetItem;
class KisSignalCompressor;
class KisCanvasResourceProvider;
class KisLocalStrokeResources;

class Contour : public QWidget {
    Q_OBJECT
public:
    Contour(QWidget *parent);
    Ui::WdgContour ui;
};


class Texture : public QWidget {
    Q_OBJECT
public:
    Texture(QWidget *parent);
    Ui::WdgTexture ui;
};


class BevelAndEmboss : public QWidget {
    Q_OBJECT
public:
    BevelAndEmboss(Contour *contour, Texture *texture, QWidget *parent);
    void setBevelAndEmboss(const psd_layer_effects_bevel_emboss *bevelAndEmboss, KisResourcesInterfaceSP resourcesInterface);
    void fetchBevelAndEmboss(psd_layer_effects_bevel_emboss *bevelAndEmboss, QSharedPointer<KisLocalStrokeResources> uploadResourcesInterface) const;

Q_SIGNALS:
    void configChanged();
    void globalAngleChanged(int value);

private:
    Contour *m_contour;
    Texture *m_texture;
    Ui::WdgBevelAndEmboss ui;
};

class BlendingOptions : public QWidget {
    Q_OBJECT
public:
    BlendingOptions(QWidget *parent);
Q_SIGNALS:
    void configChanged();

private:
    Ui::WdgBlendingOptions ui;
};


class ColorOverlay : public QWidget {
    Q_OBJECT
public:
    ColorOverlay(QWidget *parent);
    void setColorOverlay(const psd_layer_effects_color_overlay *colorOverlay);
    void fetchColorOverlay(psd_layer_effects_color_overlay *colorOverlay) const;

Q_SIGNALS:
    void configChanged();

private:
    Ui::WdgColorOverlay ui;
};


class DropShadow : public QWidget {
    Q_OBJECT

public:
    enum Mode {
        DropShadowMode,
        InnerShadowMode
    };

public:
    DropShadow(Mode mode, QWidget *parent);
    void setShadow(const psd_layer_effects_shadow_common *shadow);
    void fetchShadow(psd_layer_effects_shadow_common *shadow) const;

Q_SIGNALS:
    void configChanged();
    void globalAngleChanged(int value);

private:
    Ui::WdgDropShadow ui;
    Mode m_mode;
};

class GradientOverlay : public QWidget {
    Q_OBJECT
public:
    GradientOverlay(KisCanvasResourceProvider *resourceProvider, QWidget *parent);
    void setGradientOverlay(const psd_layer_effects_gradient_overlay *gradient, KisResourcesInterfaceSP resourcesInterface);
    void fetchGradientOverlay(psd_layer_effects_gradient_overlay *gradient, QSharedPointer<KisLocalStrokeResources> uploadResourcesInterface) const;

Q_SIGNALS:
    void configChanged();

private:
    Ui::WdgGradientOverlay ui;
};

class InnerGlow : public QWidget {
    Q_OBJECT
public:
    enum Mode {
        InnerGlowMode = 0,
        OuterGlowMode
    };

public:
    InnerGlow(Mode mode, KisCanvasResourceProvider *resourceProvider, QWidget *parent);
    void setConfig(const psd_layer_effects_glow_common *innerGlow, KisResourcesInterfaceSP resourcesInterface);
    void fetchConfig(psd_layer_effects_glow_common *innerGlow, QSharedPointer<KisLocalStrokeResources> uploadResourcesInterface) const;

Q_SIGNALS:
    void configChanged();

private:
    Ui::WdgInnerGlow ui;
    Mode m_mode;
};

class PatternOverlay : public QWidget {
    Q_OBJECT
public:
    PatternOverlay(QWidget *parent);
    void setPatternOverlay(const psd_layer_effects_pattern_overlay *pattern, KisResourcesInterfaceSP resourcesInterface);
    void fetchPatternOverlay(psd_layer_effects_pattern_overlay *pattern, QSharedPointer<KisLocalStrokeResources> uploadResourcesInterface) const;

Q_SIGNALS:
    void configChanged();

private:
    Ui::WdgPatternOverlay ui;
};

class Satin : public QWidget {
    Q_OBJECT
public:
    Satin(QWidget *parent);
    void setSatin(const psd_layer_effects_satin *satin);
    void fetchSatin(psd_layer_effects_satin *satin) const;

Q_SIGNALS:
    void configChanged();

private:
    Ui::WdgSatin ui;
};

class Stroke : public QWidget {
    Q_OBJECT
public:
    Stroke(KisCanvasResourceProvider *resourceProvider, QWidget *parent);
    void setStroke(const psd_layer_effects_stroke *stroke, KisResourcesInterfaceSP resourcesInterface);
    void fetchStroke(psd_layer_effects_stroke *stroke, QSharedPointer<KisLocalStrokeResources> uploadResourcesInterface) const;

Q_SIGNALS:
    void configChanged();

private:
    Ui::WdgStroke ui;
};


class KisResourceModel;
class StylesSelector : public QWidget {
    Q_OBJECT

protected:
    class LocationProxyModel : public QSortFilterProxyModel
    {
    public:
        LocationProxyModel(QObject* parent);

        void setEnableFiltering(bool enableFiltering);
        void setLocationToFilterBy(QString location);

    private:
        QString m_locationToFilter;
        bool m_enableFiltering {false};


        // QSortFilterProxyModel interface
    protected:
        bool filterAcceptsRow(int source_row,
                              const QModelIndex &source_parent) const override;
    };


public:
    StylesSelector(QWidget *parent);

    void notifyExternalStyleChanged(const QString &name, const QUuid &uuid);

    void addNewStyle(const QString &location, const KisPSDLayerStyleSP style);
    void loadCollection(const QString &fileName);

    void refillCollections();

private Q_SLOTS:

    void slotResourceModelReset();

    void loadStyles(const QString &name);
    void selectStyle(QModelIndex current);
Q_SIGNALS:
    void styleSelected(KisPSDLayerStyleSP style);




private:
    Ui::WdgStylesSelector ui;
    LocationProxyModel* m_locationsProxyModel;
    KisResourceModel* m_resourceModel;
};

class KisDlgLayerStyle : public KoDialog
{
    Q_OBJECT
public:
    explicit KisDlgLayerStyle(KisPSDLayerStyleSP layerStyle, KisCanvasResourceProvider *resourceProvider, QWidget *parent = 0);
    ~KisDlgLayerStyle() override;

    KisPSDLayerStyleSP style() const;

Q_SIGNALS:
    void configChanged();

public Q_SLOTS:
    void slotMasterFxSwitchChanged(bool value);
    void syncGlobalAngle(int angle);

    void notifyGuiConfigChanged();
    void notifyPredefinedStyleSelected(KisPSDLayerStyleSP style);

    void slotBevelAndEmbossChanged(QListWidgetItem*);

    void changePage(QListWidgetItem *, QListWidgetItem*);

    void slotNotifyOnAccept();
    void slotNotifyOnReject();

    // Sets all the widgets to the contents of the given style
    void setStyle(KisPSDLayerStyleSP style);

    void slotLoadStyle();
    void slotSaveStyle();
    void slotNewStyle();

private:

    KisPSDLayerStyleSP m_layerStyle;
    KisPSDLayerStyleSP m_initialLayerStyle;

    Ui::WdgStylesDialog wdgLayerStyles;

    BevelAndEmboss *m_bevelAndEmboss;
    BlendingOptions *m_blendingOptions;
    ColorOverlay *m_colorOverlay;
    Contour *m_contour;
    DropShadow *m_dropShadow;
    GradientOverlay *m_gradientOverlay;
    InnerGlow *m_innerGlow;
    DropShadow *m_innerShadow;
    InnerGlow *m_outerGlow;
    PatternOverlay * m_patternOverlay;
    Satin *m_satin;
    Stroke *m_stroke;
    StylesSelector *m_stylesSelector;
    Texture *m_texture;

    KisSignalCompressor *m_configChangedCompressor;
    bool m_isSwitchingPredefinedStyle;

    /**
     * Used for debugging purposes only to track if m_layerStyle is in
     * sync with what is stored in the GUI
     */
    mutable bool m_sanityLayerStyleDirty;

    KisTemporaryResourceStorageLock m_temporaryStorageLock;
};

#endif // KIS_DLG_LAYER_STYLE_H
