-- NOTE:
-- B42.x may pass Java ArrayList instead of Lua tables in context menu items.
-- Iterating ArrayList with pairs() can corrupt Kahlua CallFrame and cause
-- delayed TimedAction crashes. Always iterate Java lists numerically.

print("[IIW] Loaded Inspect_Context.lua from 42.13.0")

InspectUI_Context = InspectUI_Context or {}

local function firstInventoryItemFromArrayList(list)
    if not list then return nil end
    if not instanceof(list, "ArrayList") then return nil end
    if not list.size or not list.get then return nil end

    local size = list:size()
    if not size or size <= 0 then return nil end

    for i = 0, size - 1 do
        local entry = list:get(i)
        if entry then
            if instanceof(entry, "InventoryItem") then
                return entry
            end
            if instanceof(entry, "ArrayList") then
                local nested = firstInventoryItemFromArrayList(entry)
                if nested then return nested end
            end
        end
    end

    return nil
end

-- Helper: get first InventoryItem safely (Fixed for B42/ArrayList)
local function getFirstInventoryItem(items)
    if not items then return nil end

    -- 1. Caso directo: Es un item
    if instanceof(items, "InventoryItem") then
        return items
    end

    -- 2. Caso Java: Es una ArrayList. No pasar esto a getActualItems(),
    -- porque vanilla usa ipairs() y puede dañar el CallFrame en B42.13.
    if instanceof(items, "ArrayList") then
        return firstInventoryItemFromArrayList(items)
    end

    -- 3. Caso Lua: Es una tabla (Inventory Pane stack)
    if type(items) == "table" then
        -- Usamos ipairs para forzar iteración numérica y evitar claves basura
        for _, v in ipairs(items) do
            if instanceof(v, "InventoryItem") then
                return v
            elseif type(v) == "table" then
                local nestedItems = rawget(v, "items")
                if not nestedItems then
                    nestedItems = rawget(v, "item")
                end
                if not nestedItems then
                    nestedItems = rawget(v, "inventoryItem")
                end

                -- v.items puede ser OTRA ArrayList o tabla. Verificamos de nuevo.
                if nestedItems and instanceof(nestedItems, "ArrayList") then
                    local nested = firstInventoryItemFromArrayList(nestedItems)
                    if nested then return nested end
                elseif type(nestedItems) == "table" then
                    for _, it in ipairs(nestedItems) do
                        if instanceof(it, "InventoryItem") then return it end
                    end
                end
            end
        end
    end

    return nil
end

-- Inject Inspect option (Safeguarded)
local function injectInspect(context, items)
    -- Safety checks
    if not context or not items then return end
    if not InspectUI_VanillaPlus or type(InspectUI_VanillaPlus.open) ~= "function" then return end

    local item = getFirstInventoryItem(items)
    if not item then return end

    local optionText = getText("IGUI_ContextMenu_InspectItem") or "Inspect Item"

    -- Prefer on-top when available, fallback to normal addOption.
    local addOption = context.addOptionOnTop or context.addOption
    addOption(
        context,
        optionText,
        item,
        function(it)
            InspectUI_VanillaPlus.open(it)
        end
    )
end

local function onFillInventoryObjectContextMenu(player, context, items)
    injectInspect(context, items)
end

if Events and Events.OnFillInventoryObjectContextMenu and Events.OnFillInventoryObjectContextMenu.Add then
    if InspectUI_Context.onFillInventoryObjectContextMenu and Events.OnFillInventoryObjectContextMenu.Remove then
        Events.OnFillInventoryObjectContextMenu.Remove(InspectUI_Context.onFillInventoryObjectContextMenu)
    end
    InspectUI_Context.onFillInventoryObjectContextMenu = onFillInventoryObjectContextMenu
    Events.OnFillInventoryObjectContextMenu.Add(onFillInventoryObjectContextMenu)
end

-- Keybind: press I to inspect the currently selected item (inventory or loot)
local function getSelectedItemFromPane(pane)
    if not pane or not pane.inventoryPane then return nil end
    return getFirstInventoryItem(pane.inventoryPane.selected)
end

local function onKeyPressed(key)
    if not Keyboard then return end
    if key ~= Keyboard.KEY_O then return end
    if not InspectUI_VanillaPlus or type(InspectUI_VanillaPlus.open) ~= "function" then return end

    local playerObj = getPlayer()
    if not playerObj then return end

    local playerNum = playerObj:getPlayerNum()

    local item = getSelectedItemFromPane(getPlayerInventory(playerNum))
    if item then
        InspectUI_VanillaPlus.open(item)
        return
    end

    item = getSelectedItemFromPane(getPlayerLoot(playerNum))
    if item then
        InspectUI_VanillaPlus.open(item)
        return
    end
end

if Events and Events.OnKeyPressed and Events.OnKeyPressed.Add then
    if InspectUI_Context.onKeyPressed and Events.OnKeyPressed.Remove then
        Events.OnKeyPressed.Remove(InspectUI_Context.onKeyPressed)
    end
    InspectUI_Context.onKeyPressed = onKeyPressed
    Events.OnKeyPressed.Add(onKeyPressed)
end

print("[IIW] Inspect_Context registered for 42.18-safe inventory context")
