require "IS/UI/ISPanel"
local c = require "EquipmentUI/Settings"
local function REH_getEquipmentSlotTexture()
    local suffix = (REH and REH.Slots and REH.Slots.getSuffix()) or ""
    return getTexture("media/ui/equipmentui/ItemSlot" .. suffix .. ".png")
end

EquipmentSlot = ISPanel:derive("EquipmentSlot");

function EquipmentSlot:new(x, y, bodyLocation, equipmentUi, inventoryPane, playerNum)
    local o = ISPanel:new(x, y, c.SLOT_SIZE, c.SLOT_SIZE)
    setmetatable(o, self)
    self.__index = self

    o.x = x
    o.y = y

    o.borderColor = {r=1, g=1, b=1, a=1}

    o.bodyLocation = bodyLocation
    o.equipmentUi = equipmentUi
    o.inventoryPane = inventoryPane
    o.playerNum = playerNum

    o.bodyLocationGroup =
        getSpecificPlayer(playerNum):getWornItems():getBodyLocationGroup()

    return o
end

function EquipmentSlot:initialise()
    ISPanel.initialise(self)

    table.insert(c.OnScaleChanged, function(scale)
        self:setWidth(c.SLOT_SIZE)
        self:setHeight(c.SLOT_SIZE)
    end)

    NotlocControllerNode
        :injectControllerNode(self)
        :setJoypadDownHandler(self.controllerNodeOnJoypadDown)
end

function EquipmentSlot:setItem(item)
    self.item = item
end

function EquipmentSlot:clearItem()
    self.item = nil
end

---------------------------------------------------------
-- Background + border (PNG-based, no tint)
---------------------------------------------------------
function EquipmentSlot:prerender()
    local function REH_getEquipmentSlotTexture()
        local suffix = (REH and REH.Slots and REH.Slots.getSuffix()) or ""
        return getTexture("media/ui/equipmentui/ItemSlot" .. suffix .. ".png")
    end

    local brightness = 0.4
    if REH and REH.Slots and REH.Slots.getFadeBrightness then
        brightness = REH.Slots.getFadeBrightness(brightness)
    end

    self:drawTextureScaled(
        REH_getEquipmentSlotTexture(),
        0, 0,
        self.width,
        self.height,
        1,
        brightness, brightness, brightness
    )

    -- Clean white border
    self:drawRectBorder(
        0, 0,
        self.width,
        self.height,
        1, 1, 1, 1
    )

    -----------------------------------------------------
    -- Red overlay on conflict
    -----------------------------------------------------
    local dragItem = DragAndDrop.getDraggedItem()
    if dragItem and dragItem ~= self.item then

        local bodyLocation = EquipmentSlot.getBodyLocationForItem(dragItem)

        -- Make sure both slot + item have valid, non-empty body locations
        if bodyLocation and bodyLocation ~= "" and
           self.bodyLocation and self.bodyLocation ~= "" then

            local conflicts = false

            -- SAME slot = guaranteed conflict
            if bodyLocation == self.bodyLocation then
                conflicts = true

            -- EXCLUSIVE SLOT CHECK (safe)
            elseif self.bodyLocationGroup then
                conflicts = self.bodyLocationGroup:isExclusive(
                    bodyLocation,
                    self.bodyLocation
                ) or false
            end

            if conflicts then
                self:drawRect(
                    1, 1,
                    self.width - 2,
                    self.height - 2,
                    0.5,
                    1, 0, 0
                )
            end
        end
    end
end  

---------------------------------------------------------
-- Item Drawing
---------------------------------------------------------
function EquipmentSlot:render()
    if not self.item then return end

    local alpha = (self.item == DragAndDrop.getDraggedItem()) and 0.5 or 1

    -- Draw the item with its color
    self:drawTextureScaledUniform(
        self.item:getTex(),
        1, 1,
        c.SCALE,
        alpha,
        self.getItemColor(self.item)
    )

    -- Tooltip
    if self:isMouseOver() or self.controllerNode.isFocused then
        self.equipmentUi:doTooltipForItem(self, self.item)
    end
end

---------------------------------------------------------
-- Interaction
---------------------------------------------------------
function EquipmentSlot:onRightMouseUp(x, y)
    if self.item then
        EquipmentSlot.openItemContextMenu(
            self, x, y, self.item, self.inventoryPane, self.playerNum
        )
    end
end

function EquipmentSlot:onMouseDown(x, y)
    if self.item then
        DragAndDrop.prepareDrag(
            self,
            DragAndDrop.convertItemToStack(self.item),
            x, y
        )
    end
end

function EquipmentSlot:onMouseMove(dx, dy)
    DragAndDrop.startDrag(self)
end

function EquipmentSlot:onMouseMoveOutside(dx, dy)
    DragAndDrop.startDrag(self)
end

function EquipmentSlot:onMouseUp(x, y)
    DragAndDrop.endDrag()
end

function EquipmentSlot:onMouseUpOutside(x, y)
    DragAndDrop.cancelDrag(self, EquipmentSlot.dropOrUnequip)
end

function EquipmentSlot:dropOrUnequip()
    local item = self.item
    if not item then return end

    if not InventoryTetris and self.inventoryPane:isMouseOver() then
        ISInventoryPaneContextMenu.unequipItem(item, self.playerNum)
        return
    end

    local playerObj = getSpecificPlayer(self.playerNum)
    if playerObj:getVehicle() then return end

    if not ISUIElement.isMouseOverAnyUI() then
        ISInventoryPaneContextMenu.dropItem(item, self.playerNum)
    end
end

---------------------------------------------------------
-- Static Methods
---------------------------------------------------------
EquipmentSlot.getBodyLocationForItem = function(item)
    if not item:IsClothing() and not item:IsInventoryContainer() then return nil end
    local loc = item:IsClothing() and item:getBodyLocation() or item:canBeEquipped()
    return (loc == "" and nil or loc)
end

EquipmentSlot.openItemContextMenu = function(ui, x, y, item, pane, playerNum)
    local container = item:getContainer()
    local isInInv =
        container and container:isInCharacterInventory(getSpecificPlayer(playerNum))

    local menu = ISInventoryPaneContextMenu.createMenu(
        playerNum,
        isInInv,
        NotUtil.createVanillaStacksFromItems({item}, pane),
        ui:getAbsoluteX() + x,
        ui:getAbsoluteY() + y
    )

    if menu and menu.numOptions > 1 and JoypadState.players[playerNum+1] then
        ui.controllerNode:focusContextMenu(playerNum, menu)
    end
end

function EquipmentSlot.getItemColor(item)
    if not item then return 1,1,1 end
    if not item:allowRandomTint() then
        return item:getR(), item:getG(), item:getB()
    end

    local c = item:getColorInfo()
    local r,g,b = c:getR(), c:getG(), c:getB()

    -- prevent items from going too dark
    local limit = 0.2
    while r < limit and g < limit and b < limit do
        r = r + limit/4
        g = g + limit/4
        b = b + limit/4
    end
    return r,g,b
end

function EquipmentSlot:controllerNodeOnJoypadDown(button)
    if button == Joypad.XButton then
        self:unequip()
        return true
    end

    if button == Joypad.AButton then
        if self.item then
            EquipmentSlot.openItemContextMenu(
                self, self.width, self.height/2, self.item,
                self.inventoryPane, self.playerNum
            )
        end
        return true
    end

    return false
end
