-- luacheck: globals MyModGlobal
-- luacheck: read_globals Character SERVER Keys LuaUserData Hook Descriptors PlayerInput Timer
-- luacheck: max line length 420
-- Docs: https://evilfactory.github.io/LuaCsForBarotrauma/lua-docs/manual/common-questions/

if SERVER then
    require("Cyka.xpticker")
else
    require("Cyka.xpticker")
    ---@class MyModGlobal
    ---@field CONFIG {QUICKSTACK_KEYS: Keys, FABRICATOR_KEY: Keys, MAX_BUY: Keys, NESTED_CONTAINERS: boolean, DEBUG_MODE: boolean}
    ---@field MOD_NAME string
    ---@field MOD_VERSION string
    ---@field DumpTable fun(table: table, depth?: number)
    ---@field debugPrint fun(message: string)
    MyModGlobal = {
        CONFIG = {
            QUICKSTACK_KEYS = Keys.F,
            FABRICATOR_KEY = Keys.V,
            MAX_BUY = Keys.B,
            FIX = Keys.R,
            UNLOAD = Keys.E,
            RELOAD = Keys.R,
            STACK_TO_CURSOR = Keys.G,
            LOOT = Keys.L,
            SONAR = Keys.X,
            AOEPICKUP = Keys.Y,
            QICK_FABRICATOR = Keys.K,
            QICK_DECONSTRUCTOR = Keys.J,
            QICK_MEDICAL_FABRICATOR = Keys.M,
            NESTED_CONTAINERS = true,
            DEBUG_MODE = true,
        },
        MOD_NAME = "Cyka Quick",
        MOD_VERSION = "1.1.0",
        BAG_SLOT = 8,
    }

    ---@param table table
    ---@param depth number?
    MyModGlobal.DumpTable = function(table, depth)
        if depth == nil then
            depth = 0
        end
        if (depth > 200) then
            print("Error: Depth > 200 in dumpTable()")
            return
        end
        for k, v in pairs(table) do
            if (type(v) == "table") then
                print(string.rep("  ", depth) .. k .. ":")
                MyModGlobal.DumpTable(v, depth + 1)
            else
                print(string.rep("  ", depth) .. k .. ": ", v)
            end
        end
    end

    -- Debugging helper function
    MyModGlobal.debugPrint = function(message)
        if MyModGlobal.CONFIG.DEBUG_MODE then
            print("[" .. MyModGlobal.MOD_NAME .. "] " .. message)
        end
    end

    local quickstack = require("Cyka.quickstack")
    local fabricatorstack = require("Cyka.fabricatorstack")
    local quickbuy = require("Cyka.quickbuy")
    local hotkeyrepair = require("Cyka.hotkeyrepair")
    local cursormacroer = require("Cyka.cursormacroer")
    local quickunload = require("Cyka.quickunload")
    local quickreload = require("Cyka.quickreload")
    local quickloot = require("Cyka.quickloot")
    local sonarpinger = require("Cyka.sonarpinger")
    local aoepickup = require("Cyka.aoepickup")
    local quickaccess = require("Cyka.quickaccess")
    require("Cyka.zoom")

    -- TODO: Keybind fabricator / medical fabricator / deconstructor on the sub

    print(MyModGlobal.MOD_NAME .. " v" .. MyModGlobal.MOD_VERSION .. " loaded!")

    -- Register necessary types and make fields accessible
    LuaUserData.RegisterType("Barotrauma.Items.Components.ItemContainer+SlotRestrictions")
    LuaUserData.RegisterType(
        'System.Collections.Immutable.ImmutableArray`1[[Barotrauma.Items.Components.ItemContainer+SlotRestrictions, Barotrauma]]')
    LuaUserData.MakeFieldAccessible(Descriptors['Barotrauma.Items.Components.ItemContainer'], 'slotRestrictions')
    LuaUserData.MakeFieldAccessible(Descriptors['Barotrauma.ItemInventory'], 'slots')
    LuaUserData.MakeFieldAccessible(Descriptors['Barotrauma.ItemInventory'], 'slotsPerRow')
    LuaUserData.MakeFieldAccessible(Descriptors["Barotrauma.CharacterInventory"], "slots")
    LuaUserData.RegisterType("Barotrauma.Store")
    LuaUserData.RegisterType("Barotrauma.GUIComponent")
    LuaUserData.RegisterType("Barotrauma.PurchasedItem")
    LuaUserData.RegisterType("Barotrauma.ItemPrefab")
    LuaUserData.RegisterType("Barotrauma.Location+StoreInfo")
    LuaUserData.MakeMethodAccessible(Descriptors["Barotrauma.CargoManager"], "GetConfirmedSoldEntities")
    LuaUserData.RegisterType("Barotrauma.Items.Components.Repairable")
    LuaUserData.RegisterType("Barotrauma.VisualSlot")

    -- Hook.Patch("Barotrauma.Character", "ControlLocalPlayer", function(instance, ptable)
    --     if not PlayerInput.KeyHit(MyModGlobal.CONFIG.QUICKSTACK_KEYS) then return end
    --     quickstack.quickStackItems(instance)
    -- end, Hook.HookMethodType.After)

    -- Hook.Patch("Barotrauma.Character", "ControlLocalPlayer", function(instance, ptable)
    --     if not PlayerInput.KeyHit(MyModGlobal.CONFIG.STACK_TO_CURSOR) then return end
    --     if not PlayerInput.IsShiftDown() then
    --         quickstack.stackToCursor()
    --     else
    --         quickstack.stackAllToCursor()
    --     end
    -- end, Hook.HookMethodType.After)

    -- Hook.Patch("Barotrauma.Character", "ControlLocalPlayer", function(instance, ptable)
    --     if not PlayerInput.KeyHit(MyModGlobal.CONFIG.FABRICATOR_KEY) then return end
    --     fabricatorstack.tryStackFabricator(instance)
    -- end, Hook.HookMethodType.After)

    -- Hook.Patch("Barotrauma.Character", "ControlLocalPlayer", function(instance, ptable)
    --     if not PlayerInput.KeyHit(MyModGlobal.CONFIG.FIX) then return end
    --     hotkeyrepair.tryRepair()
    -- end, Hook.HookMethodType.After)

    -- Hook.Patch("Barotrauma.Character", "ControlLocalPlayer", function(instance, ptable)
    --     if not PlayerInput.KeyHit(MyModGlobal.CONFIG.MAX_BUY) then return end
    --     quickbuy.tryBuy()
    -- end, Hook.HookMethodType.After)

    -- local throttle = 0.1
    -- local throttleTimer = 0
    -- Hook.Patch("Barotrauma.Character", "ControlLocalPlayer", function(instance, ptable)
    --     if PlayerInput.Mouse4ButtonClicked() then
    --         cursormacroer.setTargetInventory()
    --     end
    --     if not PlayerInput.IsAltDown() then return end
    --     if Timer.GetTime() < throttleTimer then return end
    --     throttleTimer = Timer.GetTime() + throttle
    --     -- We can not use shift because holding shift means we're moving half a stack
    --     -- Fuck me sideways
    --     -- if not PlayerInput.IsShiftDown() then return end
    --     -- if not PlayerInput.PrimaryMouseButtonClicked() then return end
    --     cursormacroer.tryStackCursorItem()
    -- end, Hook.HookMethodType.After)

    -- Hook.Patch("Barotrauma.Character", "ControlLocalPlayer", function(instance, ptable)
    --     if not PlayerInput.KeyHit(MyModGlobal.CONFIG.UNLOAD) then return end
    --     quickunload.tryUnloadCursorItem()
    -- end, Hook.HookMethodType.After)

    -- Hook.Patch("Barotrauma.Character", "ControlLocalPlayer", function(instance, ptable)
    --     if not PlayerInput.KeyHit(MyModGlobal.CONFIG.RELOAD) then return end
    --     quickreload.tryReloadCursorItem(PlayerInput.IsShiftDown())
    -- end, Hook.HookMethodType.After)

    -- -- Hook.Patch("Barotrauma.Character", "ControlLocalPlayer", function(instance, ptable)
    -- --     if not PlayerInput.KeyHit(MyModGlobal.CONFIG.LOOT) then return end
    -- --     quickloot.tryLoot()
    -- -- end, Hook.HookMethodType.After)

    -- Hook.Patch("Barotrauma.Character", "ControlLocalPlayer", function(instance, ptable)
    --     if not PlayerInput.KeyHit(MyModGlobal.CONFIG.SONAR) then return end
    --     sonarpinger.tryPing()
    -- end, Hook.HookMethodType.After)

    -- Hook.Patch("Barotrauma.Character", "ControlLocalPlayer", function(instance, ptable)
    --     if not PlayerInput.KeyHit(MyModGlobal.CONFIG.AOEPICKUP) then return end
    --     aoepickup.tryAoePickup()
    -- end, Hook.HookMethodType.After)

    -- Hook.Patch("Barotrauma.Character", "ControlLocalPlayer", function(instance, ptable)
    --     if not PlayerInput.KeyHit(MyModGlobal.CONFIG.QICK_FABRICATOR) then return end
    --     quickaccess.tryAccessFabricator(PlayerInput.IsShiftDown())
    -- end, Hook.HookMethodType.After)

    -- Hook.Patch("Barotrauma.Character", "ControlLocalPlayer", function(instance, ptable)
    --     if not PlayerInput.KeyHit(MyModGlobal.CONFIG.QICK_DECONSTRUCTOR) then return end
    --     quickaccess.tryAccessDeconstructor(PlayerInput.IsShiftDown())
    -- end, Hook.HookMethodType.After)

    -- Hook.Patch("Barotrauma.Character", "ControlLocalPlayer", function(instance, ptable)
    --     if not PlayerInput.KeyHit(MyModGlobal.CONFIG.QICK_MEDICAL_FABRICATOR) then return end
    --     quickaccess.tryAccessMedicalFabricator(PlayerInput.IsShiftDown())
    -- end, Hook.HookMethodType.After)
end
