#pragma once

#include "foundation/result.h"

#include <string>

namespace pp::app {

enum class AboutMenuCommand {
    help_guide,
    about_app,
    whats_new,
    induce_crash,
    performance_test,
};

enum class AboutMenuAction {
    show_user_manual,
    show_about_dialog,
    show_whats_new_dialog,
    trigger_crash_test,
    run_performance_test,
    no_op_unavailable,
};

struct AboutMenuPlan {
    AboutMenuCommand command = AboutMenuCommand::help_guide;
    AboutMenuAction action = AboutMenuAction::show_user_manual;
    std::string label;
    bool closes_root_popup = true;
    bool requires_canvas = false;
    int performance_iterations = 0;
    int performance_updates_per_iteration = 0;
};

class AboutMenuServices {
public:
    virtual ~AboutMenuServices() = default;

    virtual void show_user_manual() = 0;
    virtual void show_about_dialog() = 0;
    virtual void show_whats_new_dialog() = 0;
    virtual void trigger_crash_test() = 0;
    virtual void run_performance_test(const AboutMenuPlan& plan) = 0;
};

[[nodiscard]] inline AboutMenuPlan plan_about_menu_command(
    AboutMenuCommand command,
    int version_major,
    int version_minor,
    int version_fix,
    bool diagnostics_available = true,
    bool has_canvas = true)
{
    AboutMenuPlan plan;
    plan.command = command;

    switch (command) {
    case AboutMenuCommand::help_guide:
        plan.action = AboutMenuAction::show_user_manual;
        plan.label = "Help Guide";
        break;
    case AboutMenuCommand::about_app:
        plan.action = AboutMenuAction::show_about_dialog;
        plan.label = "About PanoPainter";
        break;
    case AboutMenuCommand::whats_new:
        plan.action = AboutMenuAction::show_whats_new_dialog;
        plan.label = "What's new in "
            + std::to_string(version_major)
            + "."
            + std::to_string(version_minor)
            + "."
            + std::to_string(version_fix)
            + "?";
        break;
    case AboutMenuCommand::induce_crash:
        plan.label = "Induce crash";
        plan.action = diagnostics_available
            ? AboutMenuAction::trigger_crash_test
            : AboutMenuAction::no_op_unavailable;
        plan.closes_root_popup = diagnostics_available;
        break;
    case AboutMenuCommand::performance_test:
        plan.label = has_canvas ? "Performance test" : "Performance test (No canvas)";
        plan.requires_canvas = true;
        plan.performance_iterations = 100;
        plan.performance_updates_per_iteration = 10;
        plan.action = has_canvas
            ? AboutMenuAction::run_performance_test
            : AboutMenuAction::no_op_unavailable;
        plan.closes_root_popup = has_canvas;
        break;
    }

    return plan;
}

[[nodiscard]] inline pp::foundation::Status execute_about_menu_plan(
    const AboutMenuPlan& plan,
    AboutMenuServices& services)
{
    switch (plan.action) {
    case AboutMenuAction::show_user_manual:
        services.show_user_manual();
        return pp::foundation::Status::success();
    case AboutMenuAction::show_about_dialog:
        services.show_about_dialog();
        return pp::foundation::Status::success();
    case AboutMenuAction::show_whats_new_dialog:
        services.show_whats_new_dialog();
        return pp::foundation::Status::success();
    case AboutMenuAction::trigger_crash_test:
        services.trigger_crash_test();
        return pp::foundation::Status::success();
    case AboutMenuAction::run_performance_test:
        services.run_performance_test(plan);
        return pp::foundation::Status::success();
    case AboutMenuAction::no_op_unavailable:
        return pp::foundation::Status::success();
    }

    return pp::foundation::Status::invalid_argument("unknown about menu action");
}

}
