#include "pch.h"
#include "app.h"
#include "app_core/about_menu.h"
#include "app_core/document_layer.h"
#include "legacy_app_shell_services.h"
#include "legacy_document_layer_services.h"
#include "legacy_ui_overlay_services.h"
#include "node_button_custom.h"
#include "node_popup_menu.h"
#include "node_text.h"

namespace {

std::shared_ptr<NodePopupMenu> add_menu_popup(
    App& app,
    const char* template_id,
    glm::vec2 position,
    float rtl_anchor_width)
{
    const auto popup = pp::panopainter::add_legacy_popup_menu(
        app,
        template_id,
        position.x,
        position.y,
        rtl_anchor_width);
    if (!popup) {
        LOG("Popup menu '%s' failed: %s", template_id ? template_id : "<null>", popup.status().message);
        return nullptr;
    }
    return popup.value();
}

void close_legacy_overlay_handle_ignoring_status(
    Node& anchor,
    pp::ui::NodeHandle overlay) noexcept
{
    (void)pp::panopainter::close_legacy_overlay_node(anchor, overlay);
}

pp::app::DocumentLayerMenuPlan make_layer_menu_plan(
    pp::app::DocumentLayerMenuCommand command,
    App& app)
{
    const bool has_current_layer = app.layers && app.layers->m_current_layer;
    const int current_index = app.canvas && app.canvas->m_canvas
        ? app.canvas->m_canvas->m_current_layer_idx
        : 0;
    const int animation_duration = Canvas::I
        ? Canvas::I->anim_duration()
        : 0;
    const std::string current_name = has_current_layer
        ? app.layers->m_current_layer->m_label_text
        : std::string {};
    std::string lower_name;
    if (app.canvas && app.canvas->m_canvas && current_index > 0
        && current_index - 1 < static_cast<int>(app.canvas->m_canvas->m_layers.size()))
    {
        lower_name = app.canvas->m_canvas->m_layers[current_index - 1]->m_name;
    }

    const auto plan = pp::app::plan_document_layer_menu(
        command,
        has_current_layer,
        current_index,
        animation_duration,
        current_name,
        lower_name);
    if (plan)
        return plan.value();
    return {};
}

void execute_about_menu_plan(App& app, const pp::app::AboutMenuPlan& plan)
{
    pp::panopainter::execute_legacy_about_menu_plan(app, plan);
}

void execute_document_layer_menu_plan(App& app, const pp::app::DocumentLayerMenuPlan& plan)
{
    const auto status = pp::panopainter::execute_legacy_document_layer_menu_plan(app, plan);
    if (!status.ok())
        LOG("Layer menu action failed: %s", status.message);
}

} // namespace

namespace pp::panopainter {

void bind_legacy_about_menu(App& app)
{
    auto main = app.layout[app.main_id];

    if (auto* menu_file = main->find<NodeButtonCustom>("menu-about"))
    {
        menu_file->on_click = [&app, menu_file](Node*) {
            auto* popup_root = app.layout[app.main_id];
            if (!popup_root) {
                return;
            }
            glm::vec2 pos = menu_file->m_pos + glm::vec2(0, menu_file->m_size.y);
            auto popup = add_menu_popup(app, "about-menu", pos, menu_file->m_size.x);
            if (!popup)
                return;
            pp::panopainter::detach_legacy_node_from_parent(*popup);
            auto popup_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*popup_root, popup);
            if (!popup_overlay) {
                pp::panopainter::destroy_legacy_node(*popup);
                return;
            }
            auto popup_handle = popup_overlay.value();

            popup->find<NodeButtonCustom>("about-app")->on_click = [&app, popup_root, popup_handle](Node*) {
                const auto plan = pp::app::plan_about_menu_command(
                    pp::app::AboutMenuCommand::about_app,
                    g_version_major,
                    g_version_minor,
                    g_version_fix);
                execute_about_menu_plan(app, plan);
                if (plan.closes_root_popup)
                {
                    close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
                }
            };

            popup->find<NodeButtonCustom>("about-doc")->on_click = [&app, popup_root, popup_handle](Node*) {
//                 auto path = Asset::absolute("data/doc/test.pdf");
//                 display_file(path);
                const auto plan = pp::app::plan_about_menu_command(
                    pp::app::AboutMenuCommand::help_guide,
                    g_version_major,
                    g_version_minor,
                    g_version_fix);
                execute_about_menu_plan(app, plan);
                if (plan.closes_root_popup)
                {
                    close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
                }
            };

            if (auto item = popup->find<NodeButtonCustom>("about-news"))
            {
                if (auto text = item->find<NodeText>("menu-label"))
                {
                    const auto plan = pp::app::plan_about_menu_command(
                        pp::app::AboutMenuCommand::whats_new,
                        g_version_major,
                        g_version_minor,
                        g_version_fix);
                    text->set_text(plan.label.c_str());
                }
                item->on_click = [&app, popup_root, popup_handle](Node*) {
                    const auto plan = pp::app::plan_about_menu_command(
                        pp::app::AboutMenuCommand::whats_new,
                        g_version_major,
                        g_version_minor,
                        g_version_fix);
                    execute_about_menu_plan(app, plan);
                    if (plan.closes_root_popup)
                    {
                        close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
                    }
                };
            }

            if (auto b = popup->find<NodeButtonCustom>("about-crash"))
            {
                b->on_click = [&app, popup_root, popup_handle](Node*) {
                    const auto plan = pp::app::plan_about_menu_command(
                        pp::app::AboutMenuCommand::induce_crash,
                        g_version_major,
                        g_version_minor,
                        g_version_fix);
                    execute_about_menu_plan(app, plan);
                    if (plan.closes_root_popup)
                    {
                        close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
                    }
                };
            }

            if (auto b = popup->find<NodeButtonCustom>("about-perf"))
            {
                b->on_click = [&app, popup_root, popup_handle](Node*) {
                    const auto plan = pp::app::plan_about_menu_command(
                        pp::app::AboutMenuCommand::performance_test,
                        g_version_major,
                        g_version_minor,
                        g_version_fix,
                        true,
                        Canvas::I != nullptr);
                    execute_about_menu_plan(app, plan);
                    if (plan.closes_root_popup)
                    {
                        close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
                    }
                };
            }
        };
    }
}

void bind_legacy_layer_menu(App& app)
{
    auto main = app.layout[app.main_id];

    if (auto* menu_file = main->find<NodeButtonCustom>("menu-layers"))
    {
        menu_file->on_click = [&app, menu_file](Node*) {
            auto* popup_root = app.layout[app.main_id];
            if (!popup_root) {
                return;
            }
            glm::vec2 pos = menu_file->m_pos + glm::vec2(0, menu_file->m_size.y);
            auto popup = add_menu_popup(app, "layers-menu", pos, menu_file->m_size.x);
            if (!popup)
                return;
            pp::panopainter::detach_legacy_node_from_parent(*popup);
            auto popup_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*popup_root, popup);
            if (!popup_overlay) {
                pp::panopainter::destroy_legacy_node(*popup);
                return;
            }
            auto popup_handle = popup_overlay.value();

            popup->find<NodeButtonCustom>("layer-clear")->on_click = [&app, popup_root, popup_handle](Node*) {
                const auto plan = make_layer_menu_plan(pp::app::DocumentLayerMenuCommand::clear, app);
                execute_document_layer_menu_plan(app, plan);
                close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
            };
            {
                const auto plan = make_layer_menu_plan(pp::app::DocumentLayerMenuCommand::clear, app);
                popup->find<NodeButtonCustom>("layer-clear")->
                    find<NodeText>("menu-label")->
                    set_text(plan.label.c_str());
            }

            popup->find<NodeButtonCustom>("layer-rename")->on_click = [&app, popup_root, popup_handle](Node*) {
                const auto plan = make_layer_menu_plan(pp::app::DocumentLayerMenuCommand::rename, app);
                execute_document_layer_menu_plan(app, plan);
                close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
            };
            {
                const auto plan = make_layer_menu_plan(pp::app::DocumentLayerMenuCommand::rename, app);
                popup->find<NodeButtonCustom>("layer-rename")->
                    find<NodeText>("menu-label")->
                    set_text(plan.label.c_str());
            }

            popup->find<NodeButtonCustom>("layer-merge")->on_click = [&app, popup_root, popup_handle](Node*) {
                const auto plan = make_layer_menu_plan(pp::app::DocumentLayerMenuCommand::merge_down, app);
                execute_document_layer_menu_plan(app, plan);
                close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
            };
            {
                const auto plan = make_layer_menu_plan(pp::app::DocumentLayerMenuCommand::merge_down, app);
                popup->find<NodeButtonCustom>("layer-merge")->
                    find<NodeText>("menu-label")->
                    set_text(plan.label.c_str());
            }
        };
    }
}

} // namespace pp::panopainter
