#pragma once
#include "node.h"
#include "node_button_custom.h"
#include "node_image.h"
#include "node_stroke_preview.h"
#include "brush.h"
#include "node_scroll.h"
#include "node_text.h"
#include "serializer.h"
#include "node_button.h"

namespace pp::app {
struct BrushTextureListPlan;
struct BrushPresetListPlan;
}
namespace pp::panopainter {
class LegacyBrushTextureListServices;
class LegacyBrushPanelUi;
class LegacyBrushPresetListServices;
class LegacyBrushPresetServices;
class LegacyBrushPresetPanelUi;
}

class NodeButtonBrush : public NodeButtonCustom, public Serializer::Type
{
public:
    bool m_selected = false;
    // whether the brush is a system default
    // or user imported so it can be deleted from file
    bool m_user_brush = false;
    std::string brush_name;
    std::string high_path;
    std::string thumb_path;
    NodeImage* img;
    virtual Node* clone_instantiate() const override;
    virtual void init() override;
    void set_icon(const char* path);
    virtual void draw() override;
    virtual bool read(BinaryStreamReader& r) override;
    virtual void write(BinaryStreamWriter& w) const override;
};

class NodePanelBrush : public Node
{
    friend class pp::panopainter::LegacyBrushTextureListServices;
    friend class pp::panopainter::LegacyBrushPanelUi;

    // brushes that are marked as deleted but file still exists
    std::vector<std::string> m_deleted;
    NodeButtonBrush* m_current = nullptr;
    NodeButtonCustom* m_btn_add;
    NodeButtonCustom* m_btn_up;
    NodeButtonCustom* m_btn_down;
    NodeButtonCustom* m_btn_remove;
    bool m_interacted = false;
    void execute_texture_list_plan(const pp::app::BrushTextureListPlan& plan);
public:
    NodeScroll* m_container;
    std::string m_dir_name;
    std::function<void(Node* target, int index)> on_brush_changed;
    std::function<void(Node* target)> on_popup_close;
    virtual Node* clone_instantiate() const override;
    virtual void init() override;
    virtual kEventResult handle_event(Event* e) override;
    virtual void added(Node* parent) override;
    void handle_click(Node* target);
    int find_brush(const std::string& name) const;
    std::string get_texture_path(int index) const;
    std::string get_thumb_path(int index) const;
    bool save();
    bool restore();
    void clear();
    void scan();
    void reload();
};

// -----------------------------------------------------------------------

class NodeBrushPresetItem : public NodeButtonCustom
{
public:
    std::shared_ptr<Brush> m_brush;
    std::string high_path;
    std::string thumb_path;
    bool m_selected = false;
    NodeStrokePreview* m_preview;
    NodeImage* m_thumb;
    NodeText* m_caption_size;
    virtual Node* clone_instantiate() const override;
    virtual void init() override;
    virtual void draw() override;
};

class NodePanelBrushPreset : public Node
{
    friend class pp::panopainter::LegacyBrushPresetPanelUi;
    friend class pp::panopainter::LegacyBrushPresetListServices;
    friend class pp::panopainter::LegacyBrushPresetServices;
    bool m_interacted = false;
    NodeBrushPresetItem* m_current = nullptr;
    NodeButtonCustom* m_btn_add;
    NodeButtonCustom* m_btn_up;
    NodeButtonCustom* m_btn_down;
    NodeButtonCustom* m_btn_delete;
    NodeButtonCustom* m_btn_save;
    NodeButtonCustom* m_btn_menu;
    NodeButton* m_btn_import;
    NodeButton* m_btn_download;
    Node* m_notification;
    void execute_preset_list_plan(const pp::app::BrushPresetListPlan& plan);
public:
    struct PPBRInfo
    {
        std::string author;
        std::string email;
        std::string url;
        std::string descr;
        std::shared_ptr<Image> header_image;
        bool export_data;
        std::string dest_path;
    };

    Node* m_container;
    std::function<void(Node* target, std::shared_ptr<Brush>& brush)> on_brush_changed;
    std::function<void(Node* target)> on_popup_close;
    
    NodePanelBrushPreset();
    ~NodePanelBrushPreset();
    
    virtual Node* clone_instantiate() const override;
    virtual void init() override;
    virtual kEventResult handle_event(Event* e) override;
    virtual void added(Node* parent) override;
    
    void handle_click(Node* target);
    bool save();
    bool restore();
    void add_brush(std::shared_ptr<Brush> brush);
    bool export_ppbr(const std::string& path, const PPBRInfo& info);
    bool import_ppbr(const std::string& path);
    bool import_abr(const std::string& path);
    bool import_brush(const std::string& path);
    void clear_brushes();
};

