local RECEIVER_NAME = "ixInventoryItem"

    ICON_RENDER_QUEUE = ICON_RENDER_QUEUE or {}
    
    local function RenderNewIcon(panel, itemTable)
        local model = itemTable:GetModel()
        if ((itemTable.iconCam and !ICON_RENDER_QUEUE[string.lower(model)]) or itemTable.forceRender) then
            local iconCam = itemTable.iconCam
            iconCam = {
                cam_pos = iconCam.pos,
                cam_ang = iconCam.ang,
                cam_fov = iconCam.fov,
            }
            ICON_RENDER_QUEUE[string.lower(model)] = true
    
            panel.Icon:RebuildSpawnIconEx(
                iconCam
            )
        end
    end
    
    local function InventoryAction(action, itemID, invID, data)
        net.Start("ixInventoryAction")
            net.WriteString(action)
            net.WriteUInt(itemID, 32)
            net.WriteUInt(invID, 32)
            net.WriteTable(data or {})
        net.SendToServer()
    end
    
    local PANEL = {}
    
    AccessorFunc(PANEL, "itemTable", "ItemTable")
    AccessorFunc(PANEL, "inventoryID", "InventoryID")
    
    function PANEL:Init()
        self:Droppable(RECEIVER_NAME)
    end
    
    function PANEL:DoDoubleClick()
        local invPanel = IsValid(ix.gui.openedStorage) and ix.gui.openedStorage.storageInventory
    
        if IsValid(invPanel) then
            if self:GetInventoryID() ~= ix.gui.inv1.invID then
                invPanel = ix.gui.inv1
            end
    
            local newX, newY = invPanel:FindEmptySlotItemPanel(self)
            if newX ~= nil and newY ~= nil then
                self:Move(newX, newY, invPanel)
                return
            end
        end

        local itemTable = self.itemTable
        local inventory = self.inventoryID

        if (itemTable and inventory) then
            itemTable.player = LocalPlayer()
            local defaultAction = nil
            
            local priorityActions = {"use", "eat", "drink", "equip", "wear", "open"}
            for _, actionName in ipairs(priorityActions) do
                local v = itemTable.functions[actionName]
                if (v and (not v.OnCanRun or v.OnCanRun(itemTable) ~= false)) then
                    defaultAction = actionName
                    break
                end
            end

            if (not defaultAction) then
                for k, v in SortedPairs(itemTable.functions) do
                    if (k == "drop" or k == "combine" or (v.OnCanRun and v.OnCanRun(itemTable) == false)) then
                        continue
                    end
                    defaultAction = k
                    break
                end
            end

            if (defaultAction) then
                local v = itemTable.functions[defaultAction]
                local send = true

                if (v.OnClick) then
                    send = v.OnClick(itemTable)
                end

                if (v.sound) then
                    surface.PlaySound(v.sound)
                end

                if (send ~= false) then
                    InventoryAction(defaultAction, itemTable.id, inventory)
                end
                surface.PlaySound("anomalyzone/ui_sounds/item_use/anomaly_1_5_2/inv_properties_2.ogg")
            end
            itemTable.player = nil
        end
    end

    function PANEL:DoDoubleClickShift()
        local item = self:GetItemTable()
        if item.inv_slot and type(item.inv_slot) == "string" then
            if not LocalPlayer():GetCharacter():GetInventorySlot(item.inv_slot) then return end
            local invPanel = ix.gui["inv"..LocalPlayer():GetCharacter():GetInventorySlot(item.inv_slot):GetID()]
            if not IsValid(invPanel) then return end
            if item.invID != LocalPlayer():GetCharacter():GetInventory():GetID() then
                invPanel = ix.gui.inv1
            end
            local newX, newY = invPanel:FindEmptySlotItemPanel(self)
            if newX ~= nil and newY ~= nil then
                self:Move(newX, newY, invPanel)
            end
        end
    end
    
    function PANEL:OnMousePressed(code)
        if code == MOUSE_LEFT then
            if self.DoDoubleClick ~= nil and self.LastClickTime ~= nil and SysTime() - self.LastClickTime < 0.2 and not input.IsKeyDown(KEY_LSHIFT) then
                self:DoDoubleClick()
            end

            if self.DoDoubleClick ~= nil and self.LastClickTime ~= nil and SysTime() - self.LastClickTime < 0.2 and input.IsKeyDown(KEY_LSHIFT) then
                self:DoDoubleClickShift()
            end
    
            self.LastClickTime = SysTime()
    
            if self:IsDraggable() then
                self:MouseCapture(true)
                self:DragMousePress(code)
    
                self.clickX, self.clickY = input.GetCursorPos()
            end
        elseif (code == MOUSE_RIGHT and self.DoRightClick) then
            self:DoRightClick()
        end
    end
        
    function PANEL:OnMouseReleased(code)
        if (!dragndrop.m_ReceiverSlot or dragndrop.m_ReceiverSlot.Name != RECEIVER_NAME) then
            self:OnDrop(dragndrop.IsDragging())
        end
        self:DragMouseRelease(code)
        --self:SetZPos(99)
        self:MouseCapture(false)
    end
    
    function PANEL:DoRightClick()
        local itemTable = self.itemTable
        local inventory = self.inventoryID
    
        if (itemTable and inventory) then
            itemTable.player = LocalPlayer()
    
            local menu = DermaMenu()
            local override = hook.Run("CreateItemInteractionMenu", self, menu, itemTable)
    
            if (override == true) then
                if (menu.Remove) then
                    menu:Remove()
                end
    
                return
            end
    
            for k, v in SortedPairs(itemTable.functions) do
                if (k == "drop" or k == "combine" or (v.OnCanRun and v.OnCanRun(itemTable) == false)) then
                    continue
                end
    
                if (v.isMulti) then
                    local subMenu, subMenuOption = menu:AddSubMenu(L(v.name or k), function()
                        itemTable.player = LocalPlayer()
                            local send = true
    
                            if (v.OnClick) then
                                send = v.OnClick(itemTable)
                            end
    
                            if (v.sound) then
                                surface.PlaySound(v.sound)
                            end
    
                            if (send != false) then
                                InventoryAction(k, itemTable.id, inventory)
                            end
                            surface.PlaySound("anomalyzone/ui_sounds/item_use/anomaly_1_5_2/inv_properties_2.ogg")
                        itemTable.player = nil
                    end)
                    subMenuOption:SetImage(v.icon or "icon16/brick.png")
    
                    if (v.multiOptions) then
                        local options = isfunction(v.multiOptions) and v.multiOptions(itemTable, LocalPlayer()) or v.multiOptions
    
                        for _, sub in pairs(options) do
                            subMenu:AddOption(L(sub.name or "subOption"), function()
                                itemTable.player = LocalPlayer()
                                    local send = true
    
                                    if (sub.OnClick) then
                                        send = sub.OnClick(itemTable)
                                    end
    
                                    if (sub.sound) then
                                        surface.PlaySound(sub.sound)
                                    end
    
                                    if (send != false) then
                                        InventoryAction(k, itemTable.id, inventory, sub.data)
                                    end
                                    surface.PlaySound("anomalyzone/ui_sounds/item_use/anomaly_1_5_2/inv_properties_2.ogg")
                                itemTable.player = nil
                            end)
                        end
                    end
                else
                    menu:AddOption(L(v.name or k), function()
                        itemTable.player = LocalPlayer()
                            local send = true
    
                            if (v.OnClick) then
                                send = v.OnClick(itemTable)
                            end
    
                            if (v.sound) then
                                surface.PlaySound(v.sound)
                            end
    
                            if (send != false) then
                                InventoryAction(k, itemTable.id, inventory)
                            end
                            surface.PlaySound("anomalyzone/ui_sounds/item_use/anomaly_1_5_2/inv_properties_2.ogg")
                        itemTable.player = nil
                    end):SetImage(v.icon or "icon16/brick.png")
                end
            end
    
            local info = itemTable.functions.drop
    
            if (info and info.OnCanRun and info.OnCanRun(itemTable) != false) then
                menu:AddOption(L(info.name or "drop"), function()
                    itemTable.player = LocalPlayer()
                        local send = true
    
                        if (info.OnClick) then
                            send = info.OnClick(itemTable)
                        end
    
                        if (info.sound) then
                            surface.PlaySound(info.sound)
                        end
    
                        if (send != false) then
                            InventoryAction("drop", itemTable.id, inventory)
                        end
                    itemTable.player = nil
                end):SetImage(info.icon or "icon16/brick.png")
            end
            surface.PlaySound(Sound("anomalyzone/ui_sounds/item_use/anomaly_1_5_2/inv_properties.ogg"))
    
            menu:Open()
            itemTable.player = nil
        end
    end
    
    function PANEL:OnDrop(bDragging, inventoryPanel, inventory, gridX, gridY)
        local item = self.itemTable
    
        if (!item or !bDragging) then
            return
        end
    
        if (!IsValid(inventoryPanel)) then
            local inventoryID = self.inventoryID
    
            if (inventoryID) then
                InventoryAction("drop", item.id, inventoryID, {})
            end
        elseif (inventoryPanel:IsAllEmpty(gridX, gridY, item.width, item.height, self)) then
            local oldX, oldY = self.gridX, self.gridY
    
            if (oldX != gridX or oldY != gridY or self.inventoryID != inventoryPanel.invID) then
                self:Move(gridX, gridY, inventoryPanel)
            end
        elseif (inventoryPanel.combineItem) then
            local combineItem = inventoryPanel.combineItem
            local inventoryID = combineItem.invID
    
            if (inventoryID) then
                if ix.item.inventories[inventoryID] and ix.item.inventories[inventoryID].vars and ix.item.inventories[inventoryID].vars.isNewVendor then return end
                if ix.item.inventories[item.invID] and ix.item.inventories[item.invID].vars and ix.item.inventories[item.invID].vars.isNewVendor then return end
                combineItem.player = LocalPlayer()
                    if (combineItem.functions.combine.sound) then
                        surface.PlaySound(combineItem.functions.combine.sound)
                    end
    
                    InventoryAction("combine", combineItem.id, inventoryID, {item.id})
                combineItem.player = nil
            end
        end
    end
    
    function PANEL:Move(newX, newY, givenInventory, bNoSend)
        local iconSize = givenInventory.iconSize
        local oldX, oldY = self.gridX, self.gridY
        local oldParent = self:GetParent()
        if givenInventory.invID == LocalPlayer():GetCharacter():GetInventory():GetID() and SORT_CATEGORY then
            LocalPlayer():Notify("Во время сортировки в своём инвентаре нельзя перемещать вещи!")
            return false
        end
    
        if (givenInventory:OnTransfer(oldX, oldY, newX, newY, oldParent, bNoSend) == false) then
            return
        end
    
        local x = (newX - 1) * iconSize + 4
        local y = (newY - 1) * iconSize + givenInventory:GetPadding(2)
    
        self.gridX = newX
        self.gridY = newY
    
        self:SetParent(givenInventory)
        self:SetPos(x, y)
    
        if (self.slots) then
            for _, v in next, self.slots do
                if (IsValid(v) and v.item == self) then
                    v.item = nil
                end
            end
        end
    
        self.slots = {}
    
        for currentX = 1, self.gridW do
            for currentY = 1, self.gridH do
                local slot = givenInventory.slots[self.gridX + currentX - 1][self.gridY + currentY - 1]
    
                slot.item = self
                self.slots[#self.slots + 1] = slot
            end
        end
        local table_item_pickup_sound = {
            "anomalyzone/ui_sounds/item_pick_up/inv_items_cloth_1.ogg",
            "anomalyzone/ui_sounds/item_pick_up/inv_items_cloth_2.ogg",
            "anomalyzone/ui_sounds/item_pick_up/inv_items_cloth_3.ogg",
            "anomalyzone/ui_sounds/item_pick_up/inv_items_generic_1.ogg",
            "anomalyzone/ui_sounds/item_pick_up/inv_items_generic_2.ogg",
            "anomalyzone/ui_sounds/item_pick_up/inv_items_generic_3.ogg"
        }
        local item = self:GetItemTable()
        local sound = item.MoveSound
        if item.MoveSound and istable(item.MoveSound) then
            sound = table.Random(item.MoveSound)
        elseif item.MoveSound == nil or !item.MoveSound and table_item_pickup_sound != nil then
            sound = table.Random(table_item_pickup_sound)
        else
            sound = "anomalyzone/ui_sounds/item_pick_up/inv_items_generic_3.ogg"
        end
        LocalPlayer():EmitSound(sound)
        local inv = ix.inventory.Get(givenInventory.invID)
        if inv != LocalPlayer():GetCharacter():GetInventory() then
            net.Start("INVENTORY.ValidateItemData")
                net.WriteString(tostring(inv:GetID()))
                net.WriteString(tostring(item:GetID()))
            net.SendToServer()
        end
    end
    
    function PANEL:PaintOver(width, height)
        local itemTable = self.itemTable
    
        if (itemTable and itemTable.PaintOver) then
            itemTable.PaintOver(self, itemTable, width, height)
        end
    end
    
    function PANEL:ExtraPaint(width, height)
    end
    
    function PANEL:Paint(width, height)
        self:ExtraPaint(width, height)
    end

    local INV_MOUSE_DATA = {
        --["sniper"] = {
        --    position = {.38, .013},
        --    info = {.071, .335},
        --    texture_info = {
        --        x = 215,
        --        y = 545,
        --        w = 90,
        --        h = 360,
        --    },
        --},
        --["primary"] = {
        --    position = {.54, .013},
        --    info = {.071, .335},
        --    texture_info = {
        --        x = 215,
        --        y = 545,
        --        w = 90,
        --        h = 360,
        --    },
        --},
        --["armor"] = {
        --    position = {.454, .153},
        --    info = {.083, .19},
        --    texture_info = {
        --        x = 215,
        --        y = 545,
        --        w = 90,
        --        h = 360,
        --    },
        --},
        --["shlem"] = {
        --    position = {.454, .018},
        --    info = {.083, .107},
        --    texture_info = {
        --        x = 215,
        --        y = 545,
        --        w = 90,
        --        h = 360,
        --    },
        --},
        --["electronika"] = {
        --    position = {.382, .372},
        --    info = {.034, .053},
        --    texture_info = {
        --        x = 215,
        --        y = 545,
        --        w = 90,
        --        h = 360,
        --    },
        --},
        --["pda"] = {
        --    position = {.417, .372},
        --    info = {.034, .053},
        --    texture_info = {
        --        x = 215,
        --        y = 545,
        --        w = 90,
        --        h = 360,
        --    },
        --},
        --["flashlight"] = {
        --    position = {.54, .374},
        --    info = {.034, .053},
        --    texture_info = {
        --        x = 215,
        --        y = 545,
        --        w = 90,
        --        h = 360,
        --    },
        --},
        --["detector"] = {
        --    position = {.576, .374},
        --    info = {.034, .053},
        --    texture_info = {
        --        x = 215,
        --        y = 545,
        --        w = 90,
        --        h = 360,
        --    },
        --},
        --["sumka"] = {
        --    position = {.454, .374},
        --    info = {.083, .118},
        --    texture_info = {
        --        x = 215,
        --        y = 545,
        --        w = 90,
        --        h = 360,
        --    },
        --},
        --["knife"] = {
        --    position = {.38, .442},
        --    info = {.074, .05},
        --    texture_info = {
        --        x = 215,
        --        y = 545,
        --        w = 90,
        --        h = 360,
        --    },
        --},
        --["pistol"] = {
        --    position = {.537, .444},
        --    info = {.074, .05},
        --    texture_info = {
        --        x = 215,
        --        y = 545,
        --        w = 90,
        --        h = 360,
        --    },
        --},
        --["hotkey_1"] = {
        --    position = {.38, .52},
        --    info = {.0592, .075},
        --    texture_info = {
        --        x = 215,
        --        y = 545,
        --        w = 90,
        --        h = 360,
        --    },
        --},
        --["hotkey_2"] = {
        --    position = {.437, .52},
        --    info = {.0592, .075},
        --    texture_info = {
        --        x = 215,
        --        y = 545,
        --        w = 90,
        --        h = 360,
        --    },
        --},
        --["hotkey_3"] = {
        --    position = {.494, .52},
        --    info = {.0592, .075},
        --    texture_info = {
        --        x = 215,
        --        y = 545,
        --        w = 90,
        --        h = 360,
        --    },
        --},
        --["hotkey_4"] = {
        --    position = {.552, .52},
        --    info = {.0592, .075},
        --    texture_info = {
        --        x = 215,
        --        y = 545,
        --        w = 90,
        --        h = 360,
        --    },
        --},
        --["art_slot_1"] = {
        --    position = {.38, .618},
        --    info = {.048, .063},
        --    texture_info = {
        --        x = 215,
        --        y = 545,
        --        w = 90,
        --        h = 360,
        --    },
        --},
        --["art_slot_2"] = {
        --    position = {.426, .618},
        --    info = {.048, .063},
        --    texture_info = {
        --        x = 215,
        --        y = 545,
        --        w = 90,
        --        h = 360,
        --    },
        --},
        --["art_slot_3"] = {
        --    position = {.472, .618},
        --    info = {.048, .063},
        --    texture_info = {
        --        x = 215,
        --        y = 545,
        --        w = 90,
        --        h = 360,
        --    },
        --},
        --["art_slot_4"] = {
        --    position = {.517, .618},
        --    info = {.048, .063},
        --    texture_info = {
        --        x = 215,
        --        y = 545,
        --        w = 90,
        --        h = 360,
        --    },
        --},
        --["art_slot_5"] = {
        --    position = {.563, .618},
        --    info = {.048, .063},
        --    texture_info = {
        --        x = 215,
        --        y = 545,
        --        w = 90,
        --        h = 360,
        --    },
        --},
    }
    

    function PANEL:OnCursorEntered()
        local item = self.itemTable
        if item and item.inv_slot then
            if type(item.inv_slot) == "string" then
                if LocalPlayer():GetCharacter():GetInventorySlot(item.inv_slot) --[[and table.Count(LocalPlayer():GetCharacter():GetInventorySlot(item.inv_slot):GetItems()) <= 0]] then
                    for k, v in pairs(INV_MOUSE_DATA) do
                        if k == item.inv_slot then
                            if IsValid(ix.gui["inv" .. LocalPlayer():GetCharacter():GetInventorySlot(item.inv_slot):GetID()]) then
                                local x, y = ScrW() * INV_MOUSE_DATA[item.inv_slot].position[1], ScrH() * INV_MOUSE_DATA[item.inv_slot].position[2]
                                local width, height = ScrW() * INV_MOUSE_DATA[item.inv_slot].info[1], ScrH() * INV_MOUSE_DATA[item.inv_slot].info[2]
                                hook.Add("PostRenderVGUI", "SlotTrasferHelper", function()
                                    surface.SetDrawColor(255, 255, 255, 70)
                                    --surface.SetMaterial(Material("stalplay/ui/ui_actor_sleep_screen.png"))
                                    surface.DrawPartialTexturedRect( x, y, width, height, INV_MOUSE_DATA[item.inv_slot].texture_info.x, INV_MOUSE_DATA[item.inv_slot].texture_info.y, INV_MOUSE_DATA[item.inv_slot].texture_info.w, INV_MOUSE_DATA[item.inv_slot].texture_info.h, 1024, 1024 )
                                end)
                            end
                        end
                    end
                end
            elseif type(item.inv_slot) == "table" then
                hook.Add("PostRenderVGUI", "SlotTrasferHelper", function()
                    for slot, result in pairs(item.inv_slot) do
                        if LocalPlayer():GetCharacter():GetInventorySlot(result) --[[and table.Count(LocalPlayer():GetCharacter():GetInventorySlot(result):GetItems()) <= 0]] then
                            for k, v in pairs(INV_MOUSE_DATA) do
                                if k == result then
                                    if IsValid(ix.gui["inv" .. LocalPlayer():GetCharacter():GetInventorySlot(result):GetID()]) then
                                        local x, y = ScrW() * INV_MOUSE_DATA[result].position[1], ScrH() * INV_MOUSE_DATA[result].position[2]
                                        local width, height = ScrW() * INV_MOUSE_DATA[result].info[1], ScrH() * INV_MOUSE_DATA[result].info[2]
                                        surface.SetDrawColor(255, 255, 255, 70)
                                        --surface.SetMaterial(Material("stalplay/ui/ui_actor_sleep_screen.png"))
                                        surface.DrawPartialTexturedRect( x, y, width, height, INV_MOUSE_DATA[result].texture_info.x, INV_MOUSE_DATA[result].texture_info.y, INV_MOUSE_DATA[result].texture_info.w, INV_MOUSE_DATA[result].texture_info.h, 1024, 1024 )
                                    end
                                end
                            end
                        end
                    end
                end)
            end
        end
    end

    function PANEL:OnCursorExited()
        hook.Remove("PostRenderVGUI", "SlotTrasferHelper")
    end
    
    vgui.Register("ixItemIcon", PANEL, "SpawnIcon")
    
    PANEL = {}
    DEFINE_BASECLASS("DFrame")
    
    AccessorFunc(PANEL, "iconSize", "IconSize", FORCE_NUMBER)
    AccessorFunc(PANEL, "bHighlighted", "Highlighted", FORCE_BOOL)
    
    function PANEL:Init()
        self:SetIconSize(ScreenScale(17.90))
        self:ShowCloseButton(false)
        self:SetDraggable(false)
        self:SetSizable(false)
        --self:MakePopup()
        self:SetTitle()
        self:Receiver(RECEIVER_NAME, self.ReceiveDrop)
        self.Paint = function() end
    
        self.btnMinim:SetVisible(false)
        self.btnMinim:SetMouseInputEnabled(false)
        self.btnMaxim:SetVisible(false)
        self.btnMaxim:SetMouseInputEnabled(false)
    
        self.panels = {}
        hook.Run("StalkerInventoryCreated")
    end
    
    function PANEL:GetPadding(index)
        return select(index, self:GetDockPadding())
    end
    
    function PANEL:SetTitle(text)
        if (text == nil) then
            self.oldPadding = {self:GetDockPadding()}
    
            self.lblTitle:SetText("")
            self.lblTitle:SetVisible(false)
    
            self:DockPadding(5, 5, 5, 5)
        else
            if (self.oldPadding) then
                self:DockPadding(unpack(self.oldPadding))
                self.oldPadding = nil
            end
    
            BaseClass.SetTitle(self, text)
        end
    end
    
    function PANEL:FitParent(invWidth, invHeight)
        local parent = self:GetParent()
    
        if (!IsValid(parent)) then
            return
        end
    
        local width, height = parent:GetSize()
        local padding = 4
        local iconSize
    
        if (invWidth > invHeight) then
            iconSize = (width - padding * 2) / invWidth
        elseif (invHeight > invWidth) then
            iconSize = (height - padding * 2) / invHeight
        else
            iconSize = (height - padding * 2) / invHeight - 4
        end
    
        self:SetSize(iconSize * invWidth + padding * 2, iconSize * invHeight + padding * 2)
        self:SetIconSize(iconSize)
    end
    
    function PANEL:OnRemove()
        if (self.childPanels) then
            for _, v in ipairs(self.childPanels) do
                if (v != self) then
                    v:Remove()
                end
            end
        end
        hook.Remove("PostRenderVGUI", "SlotTrasferHelper")
        hook.Run("StalkerInventoryRemoved")
    end
    
    function PANEL:ViewOnly()
        self.viewOnly = true
    
        for _, icon in pairs(self.panels) do
            icon.OnMousePressed = nil
            icon.OnMouseReleased = nil
            icon.doRightClick = nil
        end
    end
    
    function PANEL:SetInventory(inventory, bFitParent)
        if (inventory.slots) then
            local invWidth, invHeight = inventory:GetSize()
            self.invID = inventory:GetID()
    
            if (IsValid(ix.gui.inv1) and ix.gui.inv1.childPanels and inventory != LocalPlayer():GetCharacter():GetInventory()) then
                self:SetIconSize(ix.gui.inv1:GetIconSize())
                self:SetPaintedManually(true)
                self.bNoBackgroundBlur = true
    
                ix.gui.inv1.childPanels[#ix.gui.inv1.childPanels + 1] = self
            elseif (bFitParent) then
                self:FitParent(invWidth, invHeight)
            else
                self:SetSize(self.iconSize, self.iconSize)
            end
    
            self:SetGridSize(invWidth, invHeight)
    
            for x, items in next, inventory.slots do
                for y, data in next, items do
                    if (!data.id) then continue end
    
                    local item = ix.item.instances[data.id]
    
                    if (item and !IsValid(self.panels[item.id])) then
                        local function AddItemIcon()
                            local icon = self:AddIcon(item:GetModel() or "models/props_junk/popcan01a.mdl",
                                x, y, item.width, item.height, item:GetSkin())
        
                            if (IsValid(icon)) then
                                icon:SetHelixTooltip(function(tooltip)
                                    ix.hud.PopulateItemTooltip(tooltip, item)
                                end)
        
                                self.panels[item.id] = icon
                            end
                        end
                        if SORT_CATEGORY == nil then
                            AddItemIcon()
                        else 
                            if string.find(item.uniqueID, "_flipped") then
                                if SORT_CATEGORY != nil and type(SORT_CATEGORY) == "string" then
                                    if string.find(item.subcategory:lower(), SORT_CATEGORY:lower()) and LocalPlayer():GetCharacter():GetInventory() == inventory then
                                        AddItemIcon()
                                    elseif SORT_CATEGORY != nil and inventory != LocalPlayer():GetCharacter():GetInventory() then
                                        AddItemIcon()
                                    end
                                elseif SORT_CATEGORY != nil and type(SORT_CATEGORY) == "table" then
                                    if inventory != LocalPlayer():GetCharacter():GetInventory() then
                                        AddItemIcon()
                                    else
                                        for k, v in next, SORT_CATEGORY do
                                            if string.find(item.subcategory:lower(), tostring(v:lower())) and LocalPlayer():GetCharacter():GetInventory() == inventory then
                                                AddItemIcon()
                                            end
                                        end
                                    end
                                end
                            else
                                if SORT_CATEGORY != nil and type(SORT_CATEGORY) == "string" then
                                    if string.find(item.category:lower(), SORT_CATEGORY:lower()) and LocalPlayer():GetCharacter():GetInventory() == inventory then
                                        AddItemIcon()
                                    elseif SORT_CATEGORY != nil and inventory != LocalPlayer():GetCharacter():GetInventory() then
                                        AddItemIcon()
                                    end
                                elseif SORT_CATEGORY != nil and type(SORT_CATEGORY) == "table" then
                                    if inventory != LocalPlayer():GetCharacter():GetInventory() then
                                        AddItemIcon()
                                    else
                                        for k, v in next, SORT_CATEGORY do
                                            if string.find(item.category:lower(), tostring(v:lower())) and LocalPlayer():GetCharacter():GetInventory() == inventory then
                                                AddItemIcon()
                                            end
                                        end
                                    end
                                end
                            end
                        end
                    end
                end
            end
        end
    end


    function PANEL:SetGridSize(w, h)
        local iconSize = self.iconSize
        local newWidth = w * iconSize + 8
        local newHeight = h * iconSize + self:GetPadding(2) + self:GetPadding(4)
    
        self.gridW = w
        self.gridH = h
    
        self:SetSize(newWidth, newHeight)
        self:SetMinWidth(newWidth)
        self:SetMinHeight(newHeight)
        self:BuildSlots()
    end
    
    function PANEL:PerformLayout(width, height)
        BaseClass.PerformLayout(self, width, height)
    
        if (self.Sizing and self.gridW and self.gridH) then
            local newWidth = (width - 8) / self.gridW
            local newHeight = (height - self:GetPadding(2) + self:GetPadding(4)) / self.gridH
    
            self:SetIconSize((newWidth + newHeight) / 2)
            self:RebuildItems()
        end
    end
    
    function PANEL:BuildSlots()
        local iconSize = self.iconSize
    
        self.slots = self.slots or {}
    
        local function PaintSlot(slot, w, h)
            local inventory = ix.item.inventories[self.invID]
            if inventory and inventory.vars and inventory.vars.isBag and ix.stalker.slots[inventory.vars.isBag] then
                --nice
            elseif inventory:GetID() == LocalPlayer():GetCharacter():GetInventory():GetID() or inventory and inventory.vars and inventory.vars.isBag and not ix.stalker.slots[inventory.vars.isBag] then
                surface.SetDrawColor(35, 35, 35, 85)
                surface.DrawRect(0, 0, w - 2, h - 2)

                surface.SetDrawColor(0, 0, 0, 250)
                surface.DrawOutlinedRect(0, 0, w - 2, h - 2)
            elseif inventory:GetID() != LocalPlayer():GetCharacter():GetInventory():GetID() or inventory and inventory.vars and inventory.vars.isBag and not ix.stalker.slots[inventory.vars.isBag] then
                surface.SetDrawColor(35, 35, 35, 85)
                surface.DrawRect(0, 0, w - 2, h - 2)

                surface.SetDrawColor(0, 0, 0, 250)
                surface.DrawOutlinedRect(0, 0, w - 2, h - 2)
            end
        end
    
        for _, v in ipairs(self.slots) do
            for _, v2 in ipairs(v) do
                v2:Remove()
            end
        end
    
        self.slots = {}
    
        for x = 1, self.gridW do
            self.slots[x] = {}
    
            for y = 1, self.gridH do
                local slot = self:Add("DPanel")
                slot:SetZPos(-999)
                slot.gridX = x
                slot.gridY = y
                slot:SetPos((x - 1) * iconSize + 4, (y - 1) * iconSize + self:GetPadding(2))
                slot:SetSize(iconSize, iconSize)
                slot.Paint = PaintSlot
                self.slots[x][y] = slot
            end
        end
    end
    
    function PANEL:RebuildItems()
        local iconSize = self.iconSize
    
        for x = 1, self.gridW do
            for y = 1, self.gridH do
                local slot = self.slots[x][y]
    
                slot:SetPos((x - 1) * iconSize + 4, (y - 1) * iconSize + self:GetPadding(2))
                slot:SetSize(iconSize, iconSize)
            end
        end
    
        for _, v in pairs(self.panels) do
            if (IsValid(v)) then
                v:SetPos(self.slots[v.gridX][v.gridY]:GetPos())
                v:SetSize(v.gridW * iconSize, v.gridH * iconSize)
            end
        end
    end

    local INV_DATA = {
        ["armor"] = {
            position = {.445, .15},
            slotssize = 23
        },
    }
    
    function PANEL:PaintDragPreview(width, height, mouseX, mouseY, itemPanel)
        local iconSize = self.iconSize
        local item = itemPanel:GetItemTable()
    
        if (item) then
            local inventory = ix.item.inventories[self.invID]
            local dropX = math.ceil((mouseX - 4 - (itemPanel.gridW - 1) * 32) / iconSize)
            local dropY = math.ceil((mouseY - self:GetPadding(2) - (itemPanel.gridH - 1) * 32) / iconSize)
    
            local hoveredPanel = vgui.GetHoveredPanel()
    
            if (IsValid(hoveredPanel) and hoveredPanel != itemPanel and hoveredPanel.GetItemTable) then
                local hoveredItem = hoveredPanel:GetItemTable()
    
                if (hoveredItem) then
                    local info = hoveredItem.functions.combine
    
                    if (info and info.OnCanRun and info.OnCanRun(hoveredItem, {item.id}) != false) then
                        surface.SetDrawColor(ColorAlpha(derma.GetColor("Info", self, Color(200, 0, 0)), 20))
                        surface.DrawRect(
                            hoveredPanel.x,
                            hoveredPanel.y,
                            hoveredPanel:GetWide(),
                            hoveredPanel:GetTall()
                        )
    
                        self.combineItem = hoveredItem
    
                        return
                    end
                end
            end
    
            self.combineItem = nil
    
            -- don't draw grid if we're dragging it out of bounds
            if (inventory) then
                local invWidth, invHeight = inventory:GetSize()
    
                if (dropX < 1 or dropY < 1 or
                    dropX + itemPanel.gridW - 1 > invWidth or
                    dropY + itemPanel.gridH - 1 > invHeight) then
                    return
                end
            end
    
            local bEmpty = true
    
            for x = 0, itemPanel.gridW - 1 do
                for y = 0, itemPanel.gridH - 1 do
                    local x2 = dropX + x
                    local y2 = dropY + y
    
                    bEmpty = self:IsEmpty(x2, y2, itemPanel)
    
                    if (!bEmpty) then
                        goto finish
                    end
                end
            end
    
            ::finish::
            local previewColor = ColorAlpha(bEmpty and Color(95, 186, 119) or Color(232, 114, 114), 20)
            surface.SetDrawColor(previewColor)
            surface.DrawRect(
                (dropX - 1) * iconSize + 4,
                (dropY - 1) * iconSize + self:GetPadding(2),
                itemPanel:GetWide(),
                itemPanel:GetTall()
            )
        end
    end
    
    function PANEL:PaintOver(width, height)
        local panel = self.previewPanel
        if (IsValid(panel)) then
            local itemPanel = (dragndrop.GetDroppable() or {})[1]
    
            if (IsValid(itemPanel)) then
                self:PaintDragPreview(width, height, self.previewX, self.previewY, itemPanel)
            end
        end
    
        self.previewPanel = nil
    end
    
    function PANEL:IsEmpty(x, y, this)
        return (self.slots[x] and self.slots[x][y]) and (!IsValid(self.slots[x][y].item) or self.slots[x][y].item == this)
    end
    
    function PANEL:IsAllEmpty(x, y, width, height, this)
        for x2 = 0, width - 1 do
            for y2 = 0, height - 1 do
                if (!self:IsEmpty(x + x2, y + y2, this)) then
                    return false
                end
            end
        end
    
        return true
    end
    
    function PANEL:OnTransfer(oldX, oldY, x, y, oldInventory, noSend)
        local inventories = ix.item.inventories
        local inventory = inventories[oldInventory.invID]
        local inventory2 = inventories[self.invID]
        local item
    
        if (inventory) then
            item = inventory:GetItemAt(oldX, oldY)
    
            if (!item) then
                return false
            end
    
            if (hook.Run("CanTransferItem", item, inventories[oldInventory.invID], inventories[self.invID]) == false) then
                return false, "notAllowed"
            end
    
            if (item.CanTransfer and
                item:CanTransfer(inventory, inventory != inventory2 and inventory2 or nil) == false) then
                return false
            end
        end
    
        if (!noSend) then
            net.Start("ixInventoryMove")
                net.WriteUInt(oldX, 6)
                net.WriteUInt(oldY, 6)
                net.WriteUInt(x, 6)
                net.WriteUInt(y, 6)
                net.WriteUInt(oldInventory.invID, 32)
                net.WriteUInt(self != oldInventory and self.invID or oldInventory.invID, 32)
            net.SendToServer()
        end
    
        if (inventory) then
            inventory.slots[oldX][oldY] = nil
        end
    
        if (item and inventory2) then
            inventory2.slots[x] = inventory2.slots[x] or {}
            inventory2.slots[x][y] = item
        end
    end
    
    function PANEL:AddIcon(model, x, y, w, h, skin)
        local iconSize = self.iconSize
    
        w = w or 1
        h = h or 1
        if (self.slots[x] and self.slots[x][y]) then
            local panel = self:Add("ixItemIcon")
            panel:SetSize(w * iconSize, h * iconSize)
            panel:SetZPos(999)
            panel:InvalidateLayout(true)
            panel:SetModel(model, skin)
            panel:SetPos(self.slots[x][y]:GetPos())
            panel.gridX = x
            panel.gridY = y
            panel.gridW = w
            panel.gridH = h
    
            local inventory = ix.item.inventories[self.invID]
    
            if (!inventory) then
                return
            end
    
            local itemTable = inventory:GetItemAt(panel.gridX, panel.gridY)
            
    
            panel:SetInventoryID(inventory:GetID())
            panel:SetItemTable(itemTable)
    
            if (self.panels[itemTable:GetID()]) then
                self.panels[itemTable:GetID()]:Remove()
            end
    
            if itemTable.img then
                panel.Icon:SetVisible(false)
                panel.ExtraPaint = function(this, panel_x, panel_y)
                    local icon = itemTable.img
                    if (icon) then
                        surface.SetMaterial(icon)
                        surface.SetDrawColor(color_white)
                        surface.DrawTexturedRect(0, 0, panel_x, panel_y)
                    end
                end
            else
                RenderNewIcon(panel, itemTable)
            end
    
            panel.slots = {}
    
            for i = 0, w - 1 do
                for i2 = 0, h - 1 do
                    local slot = self.slots[x + i] and self.slots[x + i][y + i2]
    
                    if (IsValid(slot)) then
                        slot.item = panel
                        panel.slots[#panel.slots + 1] = slot
                    else
                        for _, v in ipairs(panel.slots) do
                            v.item = nil
                        end
    
                        panel:Remove()
    
                        return
                    end
                end
            end
    
            return panel
        end
    end
    
    function PANEL:ReceiveDrop(panels, bDropped, menuIndex, x, y)
        local panel = panels[1]
    
        if (!IsValid(panel)) then
            self.previewPanel = nil
            return
        end
    
        if (bDropped) then
            local inventory = ix.item.inventories[self.invID]
    
            if (inventory and panel.OnDrop) then
                local dropX = math.ceil((x - 4 - (panel.gridW - 1) * 32) / self.iconSize)
                local dropY = math.ceil((y - self:GetPadding(2) - (panel.gridH - 1) * 32) / self.iconSize)
    
                panel:OnDrop(true, self, inventory, dropX, dropY)
            end
    
            self.previewPanel = nil
        else
            self.previewPanel = panel
            self.previewX = x
            self.previewY = y
        end
    end
    
    function PANEL:FindEmptySlotItemPanel(itemPanel)
        local item = itemPanel.itemTable
        local inventory_w, inventory_h, item_w, item_h = self.gridW, self.gridH, item.width, item.height
    
        if item_w > inventory_w or item_h > inventory_h then
            return false
        end
    
        for y = 1, inventory_h - (item_h - 1) do
            for x = 1, inventory_w - (item_w - 1) do
                if self:IsAllEmpty(x, y, item_w, item_h, itemPanel) then
                    return x, y
                end
            end
        end
    end
    
    vgui.Register("ixInventory", PANEL, "DFrame")

    hook.Remove("CreateMenuButtons", "ixInventory")
    
    hook.Add("PostRenderVGUI", "ixInvHelper", function()
        local pnl = ix.gui.inv1
    
        hook.Run("PostDrawInventory", pnl)
    end)
