#include "pch.h"

#include "legacy_brush_preset_panel_ui.h"

#include "app.h"
#include "app_core/brush_ui.h"
#include "asset.h"
#include "canvas.h"
#include "legacy_brush_preset_list_services.h"
#include "legacy_ui_overlay_services.h"
#include "node_message_box.h"
#include "node_popup_menu.h"

NodePanelBrushPreset::NodePanelBrushPreset()
{
    pp::panopainter::register_legacy_brush_preset_panel(*this);
}

NodePanelBrushPreset::~NodePanelBrushPreset()
{
    pp::panopainter::unregister_legacy_brush_preset_panel(*this);
}

Node* NodePanelBrushPreset::clone_instantiate() const
{
    return new NodePanelBrushPreset();
}

void NodePanelBrushPreset::init()
{
    pp::panopainter::LegacyBrushPresetPanelUi::init(*this);
}

kEventResult NodePanelBrushPreset::handle_event(Event* e)
{
    return pp::panopainter::LegacyBrushPresetPanelUi::handle_event(*this, e);
}

void NodePanelBrushPreset::handle_click(Node* target)
{
    pp::panopainter::LegacyBrushPresetPanelUi::handle_click(*this, target);
}

void NodePanelBrushPreset::add_brush(std::shared_ptr<Brush> brush)
{
    pp::panopainter::LegacyBrushPresetPanelUi::add_brush(*this, std::move(brush));
}

void NodePanelBrushPreset::added(Node* parent)
{
    (void)parent;
    pp::panopainter::LegacyBrushPresetPanelUi::added(*this);
}

namespace pp::panopainter {

void LegacyBrushPresetPanelUi::init(NodePanelBrushPreset& owner)
{
    owner.init_template_file("data/dialogs/panel-brushes.xml", "tpl-panel-brush-preset");
    owner.m_container = owner.find<Node>("brushes");

    owner.m_btn_add = owner.find<NodeButtonCustom>("btn-add");
    owner.m_btn_add->on_click = [&owner](Node*) {
        const auto plan = pp::app::plan_brush_preset_list_add(
            static_cast<int>(owner.m_container->m_children.size()),
            Canvas::I && Canvas::I->m_current_brush);
        if (plan) {
            owner.execute_preset_list_plan(plan.value());
        }
    };

    owner.m_btn_up = owner.find<NodeButtonCustom>("btn-up");
    owner.m_btn_up->on_click = [&owner](Node*) {
        if (owner.m_current)
        {
            const int idx = owner.m_container->get_child_index(owner.m_current);
            const auto plan = pp::app::plan_brush_preset_list_move(
                static_cast<int>(owner.m_container->m_children.size()),
                idx,
                -1);
            if (plan) {
                owner.execute_preset_list_plan(plan.value());
            }
        }
    };

    owner.m_btn_down = owner.find<NodeButtonCustom>("btn-down");
    owner.m_btn_down->on_click = [&owner](Node*) {
        if (owner.m_current)
        {
            const int idx = owner.m_container->get_child_index(owner.m_current);
            const auto plan = pp::app::plan_brush_preset_list_move(
                static_cast<int>(owner.m_container->m_children.size()),
                idx,
                1);
            if (plan) {
                owner.execute_preset_list_plan(plan.value());
            }
        }
    };

    /*
        owner.m_btn_save = owner.find<NodeButtonCustom>("btn-save");
        owner.m_btn_save->on_click = [this](Node*) {
            if (m_current)
            {
                *m_current->m_brush = *Canvas::I->m_current_brush;
                m_current->m_preview->draw_stroke();
                m_current->m_thumb->set_image(m_current->m_brush->m_brush_thumb_path);
                save();
            }
        };
    */

    owner.m_btn_delete = owner.find<NodeButtonCustom>("btn-remove");
    owner.m_btn_delete->on_click = [&owner](Node*) {
        if (!owner.m_current)
            return;

        const int index = owner.m_container->get_child_index(owner.m_current);
        const auto plan = pp::app::plan_brush_preset_list_remove(
            static_cast<int>(owner.m_container->m_children.size()),
            index);
        if (plan) {
            owner.execute_preset_list_plan(plan.value());
        }
    };

    owner.m_btn_menu = owner.find<NodeButtonCustom>("btn-menu");
    owner.m_btn_menu->on_click = [&owner](Node* b) {
        open_menu(owner, b);
    };

    owner.m_btn_import = owner.find<NodeButton>("import");
    owner.m_btn_import->on_click = [&owner](Node*) {
        App::I->pick_file({ "abr", "ppbr" }, [presets = std::static_pointer_cast<NodePanelBrushPreset>(owner.shared_from_this())](std::string path) {
            presets->import_brush(path);
        });
    };

    owner.m_btn_download = owner.find<NodeButton>("download");
    owner.m_btn_download->on_click = [](Node*) {
        App::I->dialog_preset_download();
    };

    owner.m_notification = owner.find("notification");

    if (Asset::exist(App::I->data_path + "/settings/presets.bin") && !owner.restore())
    {
        auto mb = App::I->message_box("Presets", "Could not read brush presets file, it will be deleted.", true);
        mb->btn_ok->on_click = [mb](Node*) {
            Asset::delete_file(App::I->data_path + "/settings/presets.bin");
            pp::panopainter::close_legacy_dialog_node(*mb);
        };
        mb->btn_cancel->on_click = [mb](Node*) {
            pp::panopainter::close_legacy_dialog_node(*mb);
        };
    }

    owner.m_notification->SetVisibility(owner.m_container->m_children.size() == 0);
}

kEventResult LegacyBrushPresetPanelUi::handle_event(NodePanelBrushPreset& owner, Event* event)
{
    switch (event->m_type)
    {
    case kEventType::MouseLeave:
        if (!owner.m_interacted)
            break;
        // else fall through
    case kEventType::MouseUpL:
        if (!owner.m_mouse_inside)
        {
            pp::panopainter::release_legacy_mouse_capture(owner);
            if (owner.m_parent)
            {
                pp::panopainter::detach_legacy_node_from_parent(owner);
            }
            if (owner.on_popup_close)
            {
                owner.on_popup_close(&owner);
            }
        }
        break;
    default:
        return kEventResult::Available;
    }
    return kEventResult::Consumed;
}

void LegacyBrushPresetPanelUi::handle_click(NodePanelBrushPreset& owner, Node* target)
{
    const int idx = owner.m_container->get_child_index(target);
    const auto plan = pp::app::plan_brush_preset_list_select(
        static_cast<int>(owner.m_container->m_children.size()),
        idx);
    if (plan) {
        owner.execute_preset_list_plan(plan.value());
    }
}

void LegacyBrushPresetPanelUi::add_brush(NodePanelBrushPreset& owner, std::shared_ptr<Brush> brush)
{
    NodeBrushPresetItem* b = new NodeBrushPresetItem;
    owner.m_container->add_child(b);
    b->init();
    b->create();
    b->loaded();
    b->thumb_path = brush->m_brush_thumb_path;
    b->high_path = brush->m_brush_path;
    b->m_brush = brush;
    b->m_preview->m_brush = brush;
    b->m_preview->draw_stroke();
    b->m_thumb->m_use_mipmaps = true;
    b->m_thumb->set_image(brush->m_brush_thumb_path);
    b->m_caption_size->set_text_format("%d", (int)brush->m_tip_size);
    b->on_click = std::bind(&NodePanelBrushPreset::handle_click, &owner, std::placeholders::_1);
    owner.m_notification->SetVisibility(owner.m_container->m_children.size() == 0);
}

void LegacyBrushPresetPanelUi::added(NodePanelBrushPreset& owner)
{
    owner.m_interacted = false;
    owner.m_notification->SetVisibility(owner.m_container->m_children.size() == 0);
}

void LegacyBrushPresetPanelUi::open_menu(NodePanelBrushPreset& owner, Node* b)
{
    auto popup = std::dynamic_pointer_cast<NodePopupMenu>(
        owner.load_template("data/dialogs/panel-brushes.xml", "tpl-brush-popup"));
    if (!popup)
        return;

    popup->SetPosition(b->m_pos.x + b->m_size.x, b->m_pos.y);
    const auto popup_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(owner, popup);
    if (!popup_overlay) {
        return;
    }

    const auto popup_handle = popup_overlay.value();
    owner.root()->update();
    auto bounds = owner.root()->GetSize() - zw(popup->get_children_rect());
    popup->SetPosition(glm::clamp(popup->m_pos, { 0, 0 }, bounds));
    popup->on_select = [&owner, popup_handle](Node* target, int index) {
        switch (index)
        {
            case 0: // import file
                App::I->pick_file({"abr", "ppbr"}, [presets = std::static_pointer_cast<NodePanelBrushPreset>(owner.shared_from_this())](std::string path) {
                    presets->import_brush(path);
                });
                break;
            case 1: // export file
                App::I->dialog_ppbr_export();
                break;
            case 2: // download
                break;
            case 3: // upload
                break;
            case 4: // clear presets
                show_clear_presets_confirmation(owner);
                break;
        }
        (void)target;
        (void)pp::panopainter::close_legacy_overlay_node(owner, popup_handle);
    };
}

void LegacyBrushPresetPanelUi::show_clear_presets_confirmation(NodePanelBrushPreset& owner)
{
    auto mb = App::I->message_box("Clear Presets", "Do you want to remove all the Brush Presets?", true);
    mb->btn_ok->m_text->set_text("Yes");
    mb->btn_cancel->m_text->set_text("No");
    mb->btn_ok->on_click = mb->on_submit = [&owner, mb](Node*) {
        const auto plan = pp::app::plan_brush_preset_list_clear(
            static_cast<int>(owner.m_container->m_children.size()));
        if (plan) {
            owner.execute_preset_list_plan(plan.value());
        }
        pp::panopainter::close_legacy_dialog_node(*mb);
    };
}

} // namespace pp::panopainter
