#include "pch.h"
#include "app.h"
#include "app_core/document_resize.h"
#include "legacy_document_canvas_services.h"
#include "legacy_document_session_services.h"
#include "legacy_ui_overlay_services.h"
#include "node_dialog_browse.h"
#include "node_dialog_open.h"
#include "node_dialog_resize.h"

namespace {

void wire_document_browse_dialog_actions(
    App& app,
    const std::shared_ptr<NodeDialogBrowse>& dialog,
    Node& overlay_anchor,
    pp::ui::NodeHandle overlay_handle)
{
    const auto close_dialog = [&overlay_anchor, overlay_handle]() {
        const auto close_status =
            pp::panopainter::close_legacy_overlay_node(overlay_anchor, overlay_handle);
        (void)close_status;
    };

    dialog->btn_ok->on_click = [&app, dialog, close_dialog](Node*)
    {
        if (dialog->is_selected())
        {
            app.open_document(dialog->selected_path);
            close_dialog();
        }
    };
    dialog->btn_cancel->on_click = [close_dialog](Node*)
    {
        close_dialog();
    };
}

void wire_document_save_dialog_buttons(
    App& app,
    const std::shared_ptr<NodeDialogSave>& dialog,
    std::function<void()> close_dialog)
{
    dialog->btn_ok->on_click = [&app, dialog](Node*)
    {
        std::string name = dialog->input->m_text;
        const auto plan = pp::app::plan_document_file_save(
            app.work_path,
            name,
            [](const std::string& path) {
                return Asset::exist(path);
            });
        if (!plan)
        {
            app.message_box("Warning", "You need to specify a name to file.");
            return;
        }

        const auto status =
            pp::panopainter::execute_legacy_document_file_save_plan(app, plan.value(), dialog);
        if (!status.ok())
            LOG("Document file save action failed: %s", status.message);
    };
    dialog->btn_cancel->on_click = [close_dialog](Node*)
    {
        close_dialog();
    };
}

void save_document_version(App& app)
{
    const auto target = pp::app::find_next_document_version_target(
        app.doc_dir,
        app.doc_name,
        [](const std::string& path) {
            return Asset::exist(path);
        });
    if (!target) {
        app.message_box("Saving Error", target.status().message);
        return;
    }

    const auto status = pp::panopainter::execute_legacy_document_version_save(app, target.value());
    if (!status.ok())
        LOG("Document version save action failed: %s", status.message);
}

} // namespace

void App::continue_document_workflow_after_optional_save(std::function<void()> action)
{
    const bool has_canvas = canvas != nullptr;
    const bool has_unsaved_changes = has_canvas && Canvas::I->m_unsaved;
    const auto decision = pp::app::plan_document_workflow(has_canvas, has_unsaved_changes);
    const auto status = pp::panopainter::execute_legacy_document_workflow_decision(
        *this,
        decision,
        std::move(action));
    if (!status.ok())
        LOG("Document workflow action failed: %s", status.message);
}

void App::dialog_newdoc()
{
    auto show_dialog = [this] {
        auto* overlay_anchor = layout[main_id];
        if (!overlay_anchor) {
            LOG("New document dialog open failed: main layout anchor is missing");
            return;
        }

        auto dialog = pp::panopainter::make_legacy_overlay_node<NodeDialogNewDoc>(*this);
        dialog->input->set_text("name");

        App::I->showKeyboard();

        const auto overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*overlay_anchor, dialog);
        if (!overlay) {
            App::I->hideKeyboard();
            LOG("New document dialog open failed: %s", overlay.status().message);
            return;
        }
        const auto overlay_handle = overlay.value();

        const auto close_dialog = [this, overlay_anchor, overlay_handle]() {
            const auto close_status =
                pp::panopainter::close_legacy_overlay_node(*overlay_anchor, overlay_handle);
            (void)close_status;
            App::I->hideKeyboard();
        };

        dialog->btn_ok->on_click = [this, dialog](Node*)
        {
            std::string name = dialog->input->m_text;
            const auto plan = pp::app::plan_new_document(
                work_path,
                name,
                dialog->m_resolution->m_current_index,
                [](const std::string& path) {
                    return Asset::exist(path);
                });
            if (!plan)
            {
                const bool missing_name =
                    plan.status().code == pp::foundation::StatusCode::invalid_argument;
                message_box(
                    "Warning",
                    missing_name ? "You need to specify a name to file." : plan.status().message);
                return;
            }

            const auto status =
                pp::panopainter::execute_legacy_new_document_plan(*this, plan.value(), dialog);
            if (!status.ok())
                LOG("New document action failed: %s", status.message);

        };
        dialog->btn_cancel->on_click = [close_dialog](Node*)
        {
            close_dialog();
        };
    };

    continue_document_workflow_after_optional_save(show_dialog);
}

// DEPRECATED
void App::dialog_open()
{
    auto show_dialog = [this] {
        // load thumbnail test
        auto* overlay_anchor = layout[main_id];
        if (!overlay_anchor) {
            LOG("Open document dialog open failed: main layout anchor is missing");
            return;
        }

        auto dialog = pp::panopainter::make_legacy_overlay_node<NodeDialogOpen>(*this);

        const auto overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*overlay_anchor, dialog);
        if (!overlay) {
            LOG("Open document dialog open failed: %s", overlay.status().message);
            return;
        }
        const auto overlay_handle = overlay.value();

        const auto close_dialog = [overlay_anchor, overlay_handle]() {
            const auto close_status =
                pp::panopainter::close_legacy_overlay_node(*overlay_anchor, overlay_handle);
            (void)close_status;
        };

        dialog->btn_ok->on_click = [this, dialog](Node*)
        {
//            canvas->reset_camera();
//            layers->clear();
//            doc_name = dialog->selected_name;
//            canvas->m_canvas->project_open(dialog->selected_path, [this](bool success) {
//                // on complete
//                async_start();
//                title_update();
//                for (auto& i : canvas->m_canvas->m_order)
//                    layers->add_layer(canvas->m_canvas->m_layers[i]->m_name.c_str());
//                async_end();
//            });
//            dialog->destroy();
//            ActionManager::clear();
        };
        dialog->btn_cancel->on_click = [close_dialog](Node*)
        {
            close_dialog();
        };
    };

    continue_document_workflow_after_optional_save(show_dialog);
}

void App::dialog_browse()
{
    auto show_dialog = [this] {
        auto* overlay_anchor = layout[main_id];
        if (!overlay_anchor) {
            LOG("Browse document dialog open failed: main layout anchor is missing");
            return;
        }

        auto dialog = pp::panopainter::make_legacy_overlay_node<NodeDialogBrowse>(*this);
        dialog->search_paths = document_browse_roots();

        const auto overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*overlay_anchor, dialog);
        if (!overlay) {
            LOG("Browse document dialog open failed: %s", overlay.status().message);
            return;
        }
        const auto overlay_handle = overlay.value();
        wire_document_browse_dialog_actions(*this, dialog, *overlay_anchor, overlay_handle);
    };

    continue_document_workflow_after_optional_save(show_dialog);
}

void App::dialog_save_ver()
{
    if (!check_license())
    {
        message_box("License", "This function is disabled in demo mode.");
        return;
    }

    save_document_version(*this);
}

void App::save_document(pp::app::DocumentSaveIntent intent)
{
    const auto decision = pp::app::plan_document_save(
        Canvas::I->m_newdoc,
        Canvas::I->m_unsaved,
        intent);
    const auto status = pp::panopainter::execute_legacy_document_save_decision(*this, decision);
    if (!status.ok())
        LOG("Document save action failed: %s", status.message);
}

void App::dialog_save()
{
    if (!check_license())
    {
        message_box("License", "This function is disabled in demo mode.");
        return;
    }
    
    if (canvas)
    {
        auto* overlay_anchor = layout[main_id];
        if (!overlay_anchor) {
            LOG("Save document dialog open failed: main layout anchor is missing");
            return;
        }

        auto dialog = pp::panopainter::make_legacy_overlay_node<NodeDialogSave>(*this);
        dialog->input->set_text(doc_name);

        App::I->showKeyboard();

        const auto overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*overlay_anchor, dialog);
        if (!overlay) {
            App::I->hideKeyboard();
            LOG("Save document dialog open failed: %s", overlay.status().message);
            return;
        }
        const auto overlay_handle = overlay.value();

        const auto close_dialog = [this, overlay_anchor, overlay_handle]() {
            const auto close_status =
                pp::panopainter::close_legacy_overlay_node(*overlay_anchor, overlay_handle);
            (void)close_status;
            App::I->hideKeyboard();
        };

        wire_document_save_dialog_buttons(*this, dialog, close_dialog);
    }
}

void App::dialog_resize()
{
    auto* overlay_anchor = layout[main_id];
    if (!overlay_anchor) {
        LOG("Resize dialog open failed: main layout anchor is missing");
        return;
    }

    auto dialog = pp::panopainter::make_legacy_overlay_node<NodeDialogResize>(*this);
    const auto overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*overlay_anchor, dialog);
    if (!overlay) {
        LOG("Resize dialog open failed: %s", overlay.status().message);
        return;
    }
    const auto overlay_handle = overlay.value();

    const auto close_dialog = [overlay_anchor, overlay_handle]() {
        const auto close_status =
            pp::panopainter::close_legacy_overlay_node(*overlay_anchor, overlay_handle);
        (void)close_status;
    };

    dialog->btn_ok->on_click = [this, dialog, close_dialog](Node*)
    {
        const auto plan = pp::app::plan_document_resize(
            dialog->combo ? dialog->combo->m_current_index : 0);
        if (!plan)
        {
            close_dialog();
            return;
        }
        const auto status = pp::panopainter::execute_legacy_document_resize_plan(*this, plan.value());
        if (!status.ok())
            LOG("Document resize failed: %s", status.message);
        close_dialog();
    };
    dialog->btn_cancel->on_click = [close_dialog](Node*) {
        close_dialog();
    };
}
