#include "adapters/hooks/items/ItemHookBindings.h"
#include "adapters/hooks/Il2CppMethodHook.h"
#include "application/lifecycle/CallbackBarrier.h"

#include <string>

#include "adapters/il2cpp/Il2CppObjectInstance.h"
#include "adapters/il2cpp/Il2CppResolver.h"
#include "adapters/il2cpp/Il2CppObjectAccess.h"
#include "adapters/il2cpp/Il2CppString.h"
#include "foundation/diagnostics/BuildOptions.h"
#include "foundation/diagnostics/Logger.h"
#include "adapters/hooks/items/ItemHookState.h"
#include "adapters/hooks/items/ItemHookDiagnostics.h"
#include "application/lifecycle/RuntimeState.h"

namespace ta::adapters::hooks::items
{
    init_level_sig o_init_level = nullptr;

    Il2CppObject* hk_init_level(Il2CppObject* instance, Il2CppObject* item_factory_, Il2CppObject* config,
                                const bool load_bundles_and_create_pools, Il2CppObject* resources,
                                Il2CppObject* progress, Il2CppObject* ct)
    {
        ta::application::runtime::CallbackGuard callback_guard;
        ta::adapters::hooks::items::diagnostics::mark_factory_hit();
        if (ta::application::runtime::should_accept_callbacks())
        {
            ta::adapters::hooks::items::diagnostics::set_factory_captured(item_factory_ != nullptr);
            ta::adapters::hooks::items::set_item_factory(item_factory_);
            if (ta::foundation::diagnostics::build_options::verbose) ta::foundation::logger::info("Captured Item Factory");
        }

        if (!o_init_level)
            return nullptr;

        return o_init_level(instance, item_factory_, config, load_bundles_and_create_pools, resources, progress, ct);
    }

    bool install_factory_hook()
    {
        if (o_init_level) return true;

        const Il2CppImage* assembly = ta::adapters::il2cpp::resolve_image("Assembly-CSharp.dll");
        if (!assembly)
        {
            ta::foundation::logger::warn("Item factory hook install failed: Assembly-CSharp.dll was not found");
            return false;
        }

        const Il2CppClass* game_world_class = ta::adapters::il2cpp::resolve_class(assembly, "EFT", "GameWorld");
        if (!game_world_class)
        {
            ta::foundation::logger::warn("Item factory hook install failed: EFT.GameWorld was not found");
            return false;
        }

        const bool ok = ta::adapters::il2cpp::hook_method(game_world_class, "InitLevel", 6, hk_init_level, &o_init_level);
        if (ok)
            ta::foundation::logger::trace("HOOK", "item factory hook installed");
        else
            ta::foundation::logger::error("Item factory hook install failed: EFT.GameWorld.InitLevel");
        return ok;
    }

}
