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

#include <string>

#include "foundation/diagnostics/BuildOptions.h"
#include "foundation/diagnostics/CrashDiagnostics.h"
#include "foundation/diagnostics/Logger.h"

namespace ta::adapters::hooks::items
{
    get_grid_size_sig o_get_grid_size = nullptr;

    UINT64 hk_get_grid_size(Il2CppObject* instance, Il2CppString* profile_id)
    {
        ta::foundation::diagnostics::crash::CallbackScope diagnostic_scope(
            "hook.items.get-grid-size",
            reinterpret_cast<std::uintptr_t>(instance),
            reinterpret_cast<std::uintptr_t>(profile_id),
            reinterpret_cast<std::uintptr_t>(o_get_grid_size));
        ta::application::runtime::CallbackGuard callback_guard;
        const UINT64 result = o_get_grid_size ? o_get_grid_size(instance, profile_id) : 0;
        if (big_grid_enabled()) return 0xA0000000A;
        return result;
    }

    local_raid_ended_sig o_local_raid_ended = nullptr;

    Il2CppObject* hk_local_raid_ended(Il2CppObject* instance, Il2CppObject* settings, Il2CppObject* results,
                                      Il2CppArray* lost_insured_items,
                                      ta::adapters::unity::dict<Il2CppString*, Il2CppArray*>* transfer_items)
    {
        ta::foundation::diagnostics::crash::CallbackScope diagnostic_scope(
            "hook.items.local-raid-ended.enter",
            reinterpret_cast<std::uintptr_t>(instance),
            reinterpret_cast<std::uintptr_t>(results),
            reinterpret_cast<std::uintptr_t>(o_local_raid_ended));
        ta::application::raid_context::begin_teardown();
        ta::foundation::diagnostics::crash::set_in_raid(false);
        ta::foundation::diagnostics::crash::write_event(
            "local-raid-ended-hook",
            reinterpret_cast<std::uintptr_t>(lost_insured_items),
            reinterpret_cast<std::uintptr_t>(transfer_items),
            reinterpret_cast<std::uintptr_t>(settings));
        ta::application::runtime::CallbackGuard callback_guard;
        ta::foundation::diagnostics::crash::set_stage("hook.items.local-raid-ended.logging");
        if (ta::foundation::diagnostics::build_options::verbose && big_grid_enabled()) ta::foundation::logger::info("Local Raid Ended");
        if (ta::foundation::diagnostics::build_options::verbose && big_grid_enabled())
        {
            ta::foundation::logger::info("Insured Items: " + std::to_string(lost_insured_items ? lost_insured_items->max_length : 0));
            ta::foundation::logger::info("Transfer Items: " + std::to_string(transfer_items ? transfer_items->m_i_count : 0));
        }
        ta::foundation::diagnostics::crash::set_stage(
            "hook.items.local-raid-ended.original",
            reinterpret_cast<std::uintptr_t>(instance),
            reinterpret_cast<std::uintptr_t>(o_local_raid_ended));
        Il2CppObject* value = o_local_raid_ended
            ? o_local_raid_ended(instance, settings, results, lost_insured_items, transfer_items)
            : nullptr;
        ta::foundation::diagnostics::crash::set_stage(
            "hook.items.local-raid-ended.complete",
            reinterpret_cast<std::uintptr_t>(value));
        return value;
    }
}
