#include "pch.h"
#include "legacy_app_dialog_services.h"

#include "app.h"
#include "legacy_ui_overlay_services.h"
#include "node_input_box.h"
#include "node_message_box.h"
#include "node_progress_bar.h"

namespace pp::panopainter {
namespace {

class LegacyAppProgressDialog final : public pp::app::AppProgressDialog {
public:
    explicit LegacyAppProgressDialog(std::shared_ptr<NodeProgressBar> node) noexcept
        : node_(std::move(node))
    {
    }

    [[nodiscard]] pp::app::AppDialogKind kind() const noexcept override
    {
        return pp::app::AppDialogKind::progress;
    }

    [[nodiscard]] std::shared_ptr<NodeProgressBar> node() const noexcept
    {
        return node_;
    }

private:
    std::shared_ptr<NodeProgressBar> node_;
};

class LegacyAppMessageDialog final : public pp::app::AppMessageDialog {
public:
    explicit LegacyAppMessageDialog(std::shared_ptr<NodeMessageBox> node) noexcept
        : node_(std::move(node))
    {
    }

    [[nodiscard]] pp::app::AppDialogKind kind() const noexcept override
    {
        return pp::app::AppDialogKind::message;
    }

    [[nodiscard]] std::shared_ptr<NodeMessageBox> node() const noexcept
    {
        return node_;
    }

private:
    std::shared_ptr<NodeMessageBox> node_;
};

class LegacyAppInputDialog final : public pp::app::AppInputDialog {
public:
    explicit LegacyAppInputDialog(std::shared_ptr<NodeInputBox> node) noexcept
        : node_(std::move(node))
    {
    }

    [[nodiscard]] pp::app::AppDialogKind kind() const noexcept override
    {
        return pp::app::AppDialogKind::input;
    }

    [[nodiscard]] std::shared_ptr<NodeInputBox> node() const noexcept
    {
        return node_;
    }

private:
    std::shared_ptr<NodeInputBox> node_;
};

class LegacyAppDialogFactory final : public pp::app::AppDialogFactory {
public:
    explicit LegacyAppDialogFactory(App& app) noexcept
        : app_(app)
    {
    }

    [[nodiscard]] std::shared_ptr<pp::app::AppProgressDialog> show_progress_dialog(
        const pp::app::AppProgressDialogPlan& plan) override
    {
        return std::make_shared<LegacyAppProgressDialog>(
            create_legacy_progress_dialog_overlay(app_, plan));
    }

    [[nodiscard]] std::shared_ptr<pp::app::AppMessageDialog> show_message_dialog(
        const pp::app::AppMessageDialogPlan& plan) override
    {
        return std::make_shared<LegacyAppMessageDialog>(
            create_legacy_message_dialog_overlay(app_, plan));
    }

    [[nodiscard]] std::shared_ptr<pp::app::AppInputDialog> show_input_dialog(
        const pp::app::AppInputDialogPlan& plan) override
    {
        return std::make_shared<LegacyAppInputDialog>(
            create_legacy_input_dialog_overlay(app_, plan));
    }

private:
    App& app_;
};

} // namespace

std::unique_ptr<pp::app::AppDialogFactory> make_legacy_app_dialog_factory(App& app)
{
    return std::make_unique<LegacyAppDialogFactory>(app);
}

std::shared_ptr<NodeProgressBar> create_legacy_app_progress_dialog(
    App& app,
    const pp::app::AppProgressDialogPlan& plan)
{
    return legacy_progress_dialog_node(make_legacy_app_dialog_factory(app)->show_progress_dialog(plan));
}

std::shared_ptr<NodeProgressBar> show_legacy_app_progress_dialog(
    App& app,
    const std::string& title,
    int total)
{
    return create_legacy_app_progress_dialog(app, pp::app::plan_app_progress_dialog(title, total));
}

std::shared_ptr<NodeMessageBox> create_legacy_app_message_dialog(
    App& app,
    const pp::app::AppMessageDialogPlan& plan)
{
    return legacy_message_dialog_node(make_legacy_app_dialog_factory(app)->show_message_dialog(plan));
}

std::shared_ptr<NodeMessageBox> show_legacy_app_message_dialog(
    App& app,
    const std::string& title,
    const std::string& text,
    bool cancel_button)
{
    return create_legacy_app_message_dialog(
        app,
        pp::app::plan_app_message_dialog(title, text, cancel_button));
}

std::shared_ptr<NodeInputBox> create_legacy_app_input_dialog(
    App& app,
    const pp::app::AppInputDialogPlan& plan)
{
    return legacy_input_dialog_node(make_legacy_app_dialog_factory(app)->show_input_dialog(plan));
}

std::shared_ptr<NodeInputBox> show_legacy_app_input_dialog(
    App& app,
    const std::string& title,
    const std::string& field_name,
    const std::string& ok_caption)
{
    const auto plan_result = pp::app::plan_app_input_dialog(title, field_name, ok_caption);
    if (!plan_result) {
        LOG("input dialog skipped: %s", plan_result.status().message);
        return nullptr;
    }

    return create_legacy_app_input_dialog(app, plan_result.value());
}

std::shared_ptr<NodeProgressBar> legacy_progress_dialog_node(
    const std::shared_ptr<pp::app::AppProgressDialog>& dialog) noexcept
{
    auto legacy = std::dynamic_pointer_cast<LegacyAppProgressDialog>(dialog);
    return legacy ? legacy->node() : nullptr;
}

std::shared_ptr<NodeMessageBox> legacy_message_dialog_node(
    const std::shared_ptr<pp::app::AppMessageDialog>& dialog) noexcept
{
    auto legacy = std::dynamic_pointer_cast<LegacyAppMessageDialog>(dialog);
    return legacy ? legacy->node() : nullptr;
}

std::shared_ptr<NodeInputBox> legacy_input_dialog_node(
    const std::shared_ptr<pp::app::AppInputDialog>& dialog) noexcept
{
    auto legacy = std::dynamic_pointer_cast<LegacyAppInputDialog>(dialog);
    return legacy ? legacy->node() : nullptr;
}

} // namespace pp::panopainter
