function()
    --- @class Item
    --- @field id number
    --- @field name string
    --- @field ilvl number
    --- @field type string

    --- @field new function
    Item = {
        --- @param self Item
        --- @return Item
        new = function(self)
            local obj = {}
            obj.id = id or -1
            obj.name = name or ""
            obj.ilvl = ilvl or -1
            obj.type = type or ""
            setmetatable(obj, self)
            self.__index = self
            return obj
        end,
    }

    --- @class ItemSet
    --- @field items Item[]

    --- @field new function
    --- @field equip function
    ItemSet = {
        --- @param self ItemSet
        --- @return ItemSet
        new = function(self, items)
            local obj = {}
            obj.items = items or {}
            setmetatable(obj, self)
            self.__index = self
            return obj
        end,

        equip = function(self)
            local equippedItems = getEquippedItems()
            print(#equippedItems .. " items equipped")

            for itemSlot, eqItem in pairs(equippedItems) do
                local item = self.items[itemSlot]

                if (eqItem.id ~= item.id and eqItem.ilvl ~= item.ilvl) then
                    print("Unequip " .. itemSlot)
                    PickupInventoryItem(itemSlot)
                    PutItemInBag(22)
                    print("Equip " .. item.id)
                    EquipItemByName(item.id, itemSlot)
                end
            end
        end
    }

    --- @return string
    function getItemName(itemLink)
        return select(1, GetItemInfo(itemLink))
    end

    --- @return number
    function getItemIlvl(itemLink)
        return select(4, GetItemInfo(itemLink))
    end

    --- @return string
    function getItemType(itemLink)
        return select(9, GetItemInfo(itemLink))
    end

    --- @return Item[]
    function getEquippedItems()
        --- @type Item[]
        local items = {}

        for i = 1, 19 do
            --- @type Item
            local item = Item:new()
            --- @type string
            local eqItemLink = GetInventoryItemLink("player", i)
            --- @type number
            local eqItemId = GetInventoryItemID("player", i)

            if (eqItemLink ~= nil) then
                item.name = getItemName(eqItemLink)
                item.ilvl = getItemIlvl(eqItemLink)
                item.type = getItemType(eqItemLink)
                item.id = eqItemId

                items[i] = item
            end
        end

        return items
    end

    --- @type ItemSet
    local set = ItemSet:new(getEquippedItems())
    set:equip()
end
