#pragma once

#include <Windows.h>

#include "adapters/unity/bindings/UnityTypes.h"
#include "adapters/il2cpp/Il2CppCollections.h"
#include "adapters/unity/bindings/UnityApi.h"
#include "external/il2cpp/il2cpp-api-types.h"

namespace ta::adapters::hooks::items
{
    bool no_limit_enabled();
    bool big_grid_enabled();

    using init_level_sig = Il2CppObject*(*)(Il2CppObject*, Il2CppObject*, Il2CppObject*, bool, Il2CppObject*,
                                            Il2CppObject*, Il2CppObject*);
    extern init_level_sig o_init_level;
    Il2CppObject* hk_init_level(Il2CppObject* instance, Il2CppObject* item_factory_, Il2CppObject* config,
                                bool load_bundles_and_create_pools, Il2CppObject* resources,
                                Il2CppObject* progress, Il2CppObject* ct);
    bool install_factory_hook();

    using mod_can_be_moved_sig = bool*(*)(Il2CppObject*, Il2CppObject*);
    extern mod_can_be_moved_sig o_mod_can_be_moved;
    bool* hk_mod_can_be_moved(Il2CppObject* instance, Il2CppObject* container);

    using get_mod_raid_moddable_sig = bool(*)(Il2CppObject*);
    extern get_mod_raid_moddable_sig o_get_mod_raid_moddable;
    bool hk_get_mod_raid_moddable(Il2CppObject* instance);

    using slot_check_conditions_sig = PVOID(*)(PVOID, PVOID, PVOID, PVOID);
    extern slot_check_conditions_sig o_slot_check_conditions;
    PVOID hk_slot_check_conditions(PVOID instance, PVOID item, PVOID ignore_restrictions, PVOID ignore_malfunctions);

    using is_mod_suitable_sig = bool(*)(Il2CppObject*, Il2CppObject*);
    extern is_mod_suitable_sig o_is_mod_suitable;
    bool hk_is_mod_suitable(Il2CppObject* instance, Il2CppObject* mod);

    using is_ammo_compatible_sig = bool(*)(Il2CppObject*, Il2CppArray*);
    extern is_ammo_compatible_sig o_is_ammo_compatible;
    bool hk_is_ammo_compatible(Il2CppObject* instance, Il2CppArray* chambers);

    using limited_at_address_sig = bool(*)(Il2CppObject*, Il2CppObject*, Il2CppObject*, int*);
    extern limited_at_address_sig o_limited_at_address_inventory;
    extern limited_at_address_sig o_limited_at_address_item;
    extern limited_at_address_sig o_limited_at_address_backend;
    bool hk_limited_at_address_inventory(Il2CppObject* instance, Il2CppObject* item, Il2CppObject* address, int* limit);
    bool hk_limited_at_address_item(Il2CppObject* instance, Il2CppObject* item, Il2CppObject* address, int* limit);
    bool hk_limited_at_address_backend(Il2CppObject* instance, Il2CppObject* item, Il2CppObject* address, int* limit);

    using check_compat_sig = bool(*)(Il2CppObject*, Il2CppObject*);
    extern check_compat_sig o_check_compat_stack_slot;
    extern check_compat_sig o_check_compat_item_controller;
    extern check_compat_sig o_check_compat_magazine;
    extern check_compat_sig o_check_compat_virtual_container;
    extern check_compat_sig o_check_compat_slot;
    extern check_compat_sig o_check_compat_grid;
    bool hk_check_compat_stack_slot(Il2CppObject* instance, Il2CppObject* item);
    bool hk_check_compat_item_controller(Il2CppObject* instance, Il2CppObject* item);
    bool hk_check_compat_magazine(Il2CppObject* instance, Il2CppObject* item);
    bool hk_check_compat_virtual_container(Il2CppObject* instance, Il2CppObject* item);
    bool hk_check_compat_slot(Il2CppObject* instance, Il2CppObject* item);
    bool hk_check_compat_grid(Il2CppObject* instance, Il2CppObject* item);

    using check_restrictions_sig = bool(*)(Il2CppObject*, Il2CppObject*, Il2CppObject*);
    extern check_restrictions_sig o_check_restrictions;
    extern check_restrictions_sig o_check_special_slot;
    extern check_restrictions_sig o_check_slot_restrictions;
    bool hk_check_restrictions(Il2CppObject* instance, Il2CppObject* item, Il2CppObject* controller);
    bool hk_check_special_slot(Il2CppObject* instance, Il2CppObject* item, Il2CppObject* controller);
    bool hk_check_slot_restrictions(Il2CppObject* instance, Il2CppObject* item, Il2CppObject* controller);

    using get_grid_size_sig = UINT64(*)(Il2CppObject*, Il2CppString*);
    extern get_grid_size_sig o_get_grid_size;
    UINT64 hk_get_grid_size(Il2CppObject* instance, Il2CppString* profile_id);

    using local_raid_ended_sig = Il2CppObject*(*)(Il2CppObject*, Il2CppObject*, Il2CppObject*, Il2CppArray*,
                                                  ta::adapters::unity::dict<Il2CppString*, Il2CppArray*>*);
    extern local_raid_ended_sig o_local_raid_ended;
    Il2CppObject* hk_local_raid_ended(Il2CppObject* instance, Il2CppObject* settings, Il2CppObject* results,
                                      Il2CppArray* lost_insured_items,
                                      ta::adapters::unity::dict<Il2CppString*, Il2CppArray*>* transfer_items);
}
