#include "pch.h"

#include "platform_windows/windows_runtime_state.h"

#include "app.h"
#include "app_runtime.h"
#include "wacom.h"

namespace pp::platform::windows {
namespace {

struct RetainedWindowsRuntimeState final {
    std::unique_ptr<App> owned_app;
    App* app = nullptr;
    AppRuntime* runtime = nullptr;
    WacomTablet tablet;
};

[[nodiscard]] RetainedWindowsRuntimeState& retained_runtime_state() noexcept
{
    static RetainedWindowsRuntimeState state;
    return state;
}

}

App& initialize_bound_app_runtime()
{
    auto& owned_app = retained_owned_app();
    owned_app = std::make_unique<App>();
    auto& app = *owned_app;
    bind_app(&app);
    bind_runtime(&app.runtime());
    return app;
}

void bind_app(App* app) noexcept
{
    auto& state = retained_runtime_state();
    state.app = app;
    App::I = app;
}

App* bound_app() noexcept
{
    return retained_runtime_state().app;
}

void release_bound_app() noexcept
{
    bind_app(nullptr);
    bind_runtime(nullptr);
    retained_owned_app().reset();
}

void shutdown_bound_app_runtime() noexcept
{
    if (auto* runtime = retained_bound_runtime())
    {
        runtime->ui_thread_stop();
        runtime->render_thread_stop();
    }

    if (auto* app = bound_app())
        app->terminate();

    release_bound_app();
}

WacomTablet* bound_wacom_tablet() noexcept
{
    return &retained_wacom_tablet();
}

std::unique_ptr<App>& retained_owned_app() noexcept
{
    return retained_runtime_state().owned_app;
}

WacomTablet& retained_wacom_tablet() noexcept
{
    return retained_runtime_state().tablet;
}

AppRuntime* retained_bound_runtime() noexcept
{
    return retained_runtime_state().runtime;
}

void bind_runtime(AppRuntime* runtime) noexcept
{
    retained_runtime_state().runtime = runtime;
}

}
