#include "adapters/hooks/HookCallbacks.h"

#include <atomic>

namespace ta::adapters::hooks
{
    namespace
    {
        RuntimeCallbacks callback_storage{};
        std::atomic<const RuntimeCallbacks*> active_callbacks{nullptr};
    }

    bool publish_runtime_callbacks(const RuntimeCallbacks& callbacks) noexcept
    {
        if (!callbacks.context || !callbacks.application_update || !callbacks.gameworld_update)
            return false;

        callback_storage = callbacks;
        active_callbacks.store(&callback_storage, std::memory_order_release);
        return true;
    }

    void clear_runtime_callbacks() noexcept
    {
        active_callbacks.store(nullptr, std::memory_order_release);
    }

    void dispatch_application_update() noexcept
    {
        const RuntimeCallbacks* callbacks = active_callbacks.load(std::memory_order_acquire);
        if (callbacks)
            callbacks->application_update(callbacks->context);
    }

    void dispatch_gameworld_update(const Il2CppClass* game_world_class,
                                   ta::adapters::il2cpp::Il2CppObjectInstance game_world_instance,
                                   ta::adapters::il2cpp::Il2CppObjectInstance main_player) noexcept
    {
        const RuntimeCallbacks* callbacks = active_callbacks.load(std::memory_order_acquire);
        if (callbacks)
            callbacks->gameworld_update(
                callbacks->context,
                game_world_class,
                game_world_instance,
                main_player);
    }
}
