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

namespace ta::adapters::hooks::items
{
    mod_can_be_moved_sig o_mod_can_be_moved = nullptr;

    bool* hk_mod_can_be_moved(Il2CppObject* instance, Il2CppObject* container)
    {
        ta::application::runtime::CallbackGuard callback_guard;
        if (!o_mod_can_be_moved) return nullptr;
        bool* result = o_mod_can_be_moved(instance, container);
        if (result && no_limit_enabled()) *result = true;
        return result;
    }

    get_mod_raid_moddable_sig o_get_mod_raid_moddable = nullptr;

    bool hk_get_mod_raid_moddable(Il2CppObject* instance)
    {
        ta::application::runtime::CallbackGuard callback_guard;
        if (no_limit_enabled()) return true;
        return o_get_mod_raid_moddable ? o_get_mod_raid_moddable(instance) : false;
    }

    slot_check_conditions_sig o_slot_check_conditions = nullptr;

    PVOID hk_slot_check_conditions(PVOID instance, PVOID item, PVOID ignore_restrictions,
                                   PVOID ignore_malfunctions)
    {
        ta::application::runtime::CallbackGuard callback_guard;
        if (!o_slot_check_conditions) return nullptr;
        if (no_limit_enabled())
            return o_slot_check_conditions(instance, item, reinterpret_cast<PVOID>(1), reinterpret_cast<PVOID>(1));
        return o_slot_check_conditions(instance, item, ignore_restrictions, ignore_malfunctions);
    }

    is_mod_suitable_sig o_is_mod_suitable = nullptr;

    bool hk_is_mod_suitable(Il2CppObject* instance, Il2CppObject* mod)
    {
        ta::application::runtime::CallbackGuard callback_guard;
        if (no_limit_enabled()) return true;
        return o_is_mod_suitable ? o_is_mod_suitable(instance, mod) : false;
    }

    is_ammo_compatible_sig o_is_ammo_compatible = nullptr;

    bool hk_is_ammo_compatible(Il2CppObject* instance, Il2CppArray* chambers)
    {
        ta::application::runtime::CallbackGuard callback_guard;
        if (no_limit_enabled()) return true;
        return o_is_ammo_compatible ? o_is_ammo_compatible(instance, chambers) : false;
    }

    limited_at_address_sig o_limited_at_address_inventory = nullptr;
    limited_at_address_sig o_limited_at_address_item = nullptr;
    limited_at_address_sig o_limited_at_address_backend = nullptr;

    bool hk_limited_at_address_inventory(Il2CppObject* instance, Il2CppObject* item, Il2CppObject* address,
                                         int* limit)
    {
        ta::application::runtime::CallbackGuard callback_guard;
        if (no_limit_enabled()) return false;
        return o_limited_at_address_inventory ? o_limited_at_address_inventory(instance, item, address, limit) : false;
    }

    bool hk_limited_at_address_item(Il2CppObject* instance, Il2CppObject* item, Il2CppObject* address,
                                    int* limit)
    {
        ta::application::runtime::CallbackGuard callback_guard;
        if (no_limit_enabled()) return false;
        return o_limited_at_address_item ? o_limited_at_address_item(instance, item, address, limit) : false;
    }

    bool hk_limited_at_address_backend(Il2CppObject* instance, Il2CppObject* item, Il2CppObject* address,
                                       int* limit)
    {
        ta::application::runtime::CallbackGuard callback_guard;
        if (no_limit_enabled()) return false;
        return o_limited_at_address_backend ? o_limited_at_address_backend(instance, item, address, limit) : false;
    }

    check_compat_sig o_check_compat_stack_slot = nullptr;
    check_compat_sig o_check_compat_item_controller = nullptr;
    check_compat_sig o_check_compat_magazine = nullptr;
    check_compat_sig o_check_compat_virtual_container = nullptr;
    check_compat_sig o_check_compat_slot = nullptr;
    check_compat_sig o_check_compat_grid = nullptr;

    bool hk_check_compat_stack_slot(Il2CppObject* instance, Il2CppObject* item)
    {
        ta::application::runtime::CallbackGuard callback_guard;
        if (no_limit_enabled()) return true;
        return o_check_compat_stack_slot ? o_check_compat_stack_slot(instance, item) : false;
    }

    bool hk_check_compat_item_controller(Il2CppObject* instance, Il2CppObject* item)
    {
        ta::application::runtime::CallbackGuard callback_guard;
        if (no_limit_enabled()) return true;
        return o_check_compat_item_controller ? o_check_compat_item_controller(instance, item) : false;
    }

    bool hk_check_compat_magazine(Il2CppObject* instance, Il2CppObject* item)
    {
        ta::application::runtime::CallbackGuard callback_guard;
        if (no_limit_enabled()) return true;
        return o_check_compat_magazine ? o_check_compat_magazine(instance, item) : false;
    }

    bool hk_check_compat_virtual_container(Il2CppObject* instance, Il2CppObject* item)
    {
        ta::application::runtime::CallbackGuard callback_guard;
        if (no_limit_enabled()) return true;
        return o_check_compat_virtual_container ? o_check_compat_virtual_container(instance, item) : false;
    }

    bool hk_check_compat_slot(Il2CppObject* instance, Il2CppObject* item)
    {
        ta::application::runtime::CallbackGuard callback_guard;
        if (no_limit_enabled()) return true;
        return o_check_compat_slot ? o_check_compat_slot(instance, item) : false;
    }

    bool hk_check_compat_grid(Il2CppObject* instance, Il2CppObject* item)
    {
        ta::application::runtime::CallbackGuard callback_guard;
        if (no_limit_enabled()) return true;
        return o_check_compat_grid ? o_check_compat_grid(instance, item) : false;
    }

    check_restrictions_sig o_check_restrictions = nullptr;
    check_restrictions_sig o_check_special_slot = nullptr;
    check_restrictions_sig o_check_slot_restrictions = nullptr;

    bool hk_check_restrictions(Il2CppObject* instance, Il2CppObject* item, Il2CppObject* controller)
    {
        ta::application::runtime::CallbackGuard callback_guard;
        if (no_limit_enabled()) return false;
        return o_check_restrictions ? o_check_restrictions(instance, item, controller) : false;
    }

    bool hk_check_special_slot(Il2CppObject* instance, Il2CppObject* item, Il2CppObject* controller)
    {
        ta::application::runtime::CallbackGuard callback_guard;
        if (no_limit_enabled()) return false;
        return o_check_special_slot ? o_check_special_slot(instance, item, controller) : false;
    }

    bool hk_check_slot_restrictions(Il2CppObject* instance, Il2CppObject* item, Il2CppObject* controller)
    {
        ta::application::runtime::CallbackGuard callback_guard;
        if (no_limit_enabled()) return false;
        return o_check_slot_restrictions ? o_check_slot_restrictions(instance, item, controller) : false;
    }
}
