#pragma once

#include "node_border.h"
#include "node_scroll.h"
#include "node_text.h"
#include "node_checkbox.h"
#include "node_button_custom.h"
#include "node_combobox.h"

class Layer;

namespace pp::panopainter {
class LegacyDocumentAnimationServices;
}

namespace pp::app {
struct DocumentAnimationPanelState;
struct DocumentAnimationOperationPlan;
}

class NodeAnimationFrame : public NodeButtonCustom
{
public:
    std::function<void(NodeAnimationFrame* target)> on_selected;
    
    using this_class = NodeAnimationFrame;
    using parent = NodeButtonCustom;
    
    virtual Node* clone_instantiate() const override { return new this_class; }
};

//////////////////////////////////////////////////////////////////////////

class NodeAnimationTimeline : public NodeBorder
{
    bool m_dragging = false;
    glm::vec2 m_drag_start_pos = { 0, 0 };
    int m_drag_start_frame = 0;
public:
    using this_class = NodeAnimationTimeline;
    using parent = NodeBorder;

    std::function<void(NodeAnimationTimeline* target, int frame)> on_frame_changed;
    
    int m_frames_count = 1;
    int m_frame = 0;
    int m_onion_size = 1;
    glm::vec4 m_cursor_color = { 1, 0, 0, 1 };

    virtual Node* clone_instantiate() const override { return new this_class; }
    virtual void draw() override;
    virtual kEventResult handle_event(Event* e) override;
};

//////////////////////////////////////////////////////////////////////////

class NodePanelAnimation : public Node
{
    friend class pp::panopainter::LegacyDocumentAnimationServices;

    NodeButtonCustom* btn_next = nullptr;
    NodeButtonCustom* btn_prev = nullptr;
    NodeButtonCustom* btn_play = nullptr;
    NodeButtonCustom* btn_add = nullptr;
    NodeButtonCustom* btn_remove = nullptr;
    NodeButtonCustom* btn_up = nullptr;
    NodeButtonCustom* btn_down = nullptr;
    NodeButtonCustom* btn_left = nullptr;
    NodeButtonCustom* btn_right = nullptr;
    NodeButtonCustom* btn_duplicate = nullptr;
    Node* m_layers_container = nullptr;
    Node* m_frames_container = nullptr;
    NodeAnimationFrame* m_selected_frame = nullptr;
    NodeAnimationTimeline* m_timeline = nullptr;
    NodeComboBox* m_fps = nullptr;
    NodeComboBox* m_onion = nullptr;
    NodeText* m_frame_label = nullptr;
    int m_selected_frame_index = -1;
    uint32_t m_selected_frame_layer_id = 0;
    float m_playback_timer = 0;

    void execute_animation_plan(const pp::app::DocumentAnimationOperationPlan& plan, Layer* layer = nullptr);
    [[nodiscard]] pp::app::DocumentAnimationPanelState animation_panel_state() const;
public:
    using this_class = NodePanelAnimation;
    using parent = Node;

    virtual Node* clone_instantiate() const override;
    virtual void clone_finalize(Node* dest) const override;
    virtual void init() override;
    virtual void added(Node* parent) override;
    virtual void on_tick(float dt) override;

    void init_controls();
    void load_layers();
    void update_frames();
    int get_onion_size() const noexcept { return m_onion->get_int(); }
    int get_fps() const noexcept { return m_fps->get_int(); }
};

//////////////////////////////////////////////////////////////////////////

class NodeAnimationFilm : public NodeBorder
{
public:
    using this_class = NodeAnimationFilm;
    using parent = NodeBorder;

    virtual Node* clone_instantiate() const override { return new this_class; }
    virtual void init() override 
    {
        parent::init();
        init_template_file("data/dialogs/panel-animation.xml", "tpl-film");
    }

    std::shared_ptr<NodeAnimationFrame> add_frame(int duration)
    {
        auto b = add_child_ref<NodeAnimationFrame>();
        b->SetWidth(30 * duration + 5 * (duration - 1));
        //b->SetFlexGrow(duration);
        b->SetHeightP(100);
        b->SetMargin(0, 5, 0, 0);
        return b;
    }
};

//////////////////////////////////////////////////////////////////////////

class NodeAnimationLayer : public NodeBorder
{
    bool m_selected = false;
    glm::vec4 m_color_normal = glm::vec4(.4, .4, .4, 1);
    glm::vec4 m_color_selected = glm::vec4(.3, .3, .3, 1);
    glm::vec4 m_color_hover = glm::vec4(.5, .5, .5, 1);
    NodeText* m_label = nullptr;
    NodeCheckBox* m_visibility = nullptr;
public:
    std::function<void(NodeAnimationLayer* target)> on_selected;
    std::function<void(NodeAnimationLayer* target, bool visible)> on_visibility_changed;
    std::function<void(NodeAnimationLayer* target, bool highlight)> on_highlight;
    
    using this_class = NodeAnimationLayer;
    using parent = NodeBorder;
    
    virtual Node* clone_instantiate() const override;
    virtual void clone_finalize(Node* dest) const override;
    virtual void init() override;
    virtual void draw() override;
    
    void init_controls();
    void set_text(const std::string& text) { m_label->set_text(text.c_str()); }
    void set_selected(bool selected) { m_selected = selected; }
    void set_chekcbox(bool checked) { m_visibility->set_value(checked); }
};
