local re = re
local sdk = sdk
local d2d = d2d
local imgui = imgui
local log = log
local json = json
local draw = draw
local require = require
local tostring = tostring
local pairs = pairs
local ipairs = ipairs
local math = math
local string = string
local table = table
local type = type

local Core = require("_CatLib")
local CONST = require("_CatLib.const")
local Imgui = require("_CatLib.imgui")

local MOD_NAME = "Auto Restock"
local mod = Core.NewMod(MOD_NAME)
mod.EnableCJKFont(18) -- if needed

local MAX_SHORTCUT_PAGE = 8

local MAX_ITEM_MYSET = nil
local MAX_SHORTCUT_MYSET = 36

local function InitDefaultShortcutSet()
    local myset = {}
    for _ = 0, MAX_SHORTCUT_PAGE - 1, 1 do
        table.insert(myset, -1)
    end
    return myset
end

local function InitCustomConfig()
    return {
        DefaultSet = -1,
        UseCustomShortcutSet = false,
        DefaultShortcutSet = InitDefaultShortcutSet(),
    }
end

if mod.Config.DefaultSet == nil then
    mod.Config.DefaultSet = -1
    mod.Config.UseCustomShortcutSet = false
    mod.Config.DefaultShortcutSet = InitDefaultShortcutSet()
end
if mod.Config.NotifyNoEnoughItems == nil then
    mod.Config.NotifyNoEnoughItems = true
end
if mod.Config.NotifyNoEnoughItemDetails == nil then
    mod.Config.NotifyNoEnoughItemDetails = false
end
if mod.Config.NotifyDetailedShortcutMenu == nil then
    mod.Config.NotifyDetailedShortcutMenu = true
end

if mod.Config.FallbackAnotherWeapon == nil then
    mod.Config.AlsoFillShells = true
    mod.Config.AlsoFillOtherItems = true
    mod.Config.FallbackAnotherWeapon = true
    -- mod.Config.AlsoApplySubWeapon = false
end

if mod.Config.WeaponTypeConfig == nil then
    mod.Config.WeaponTypeConfig = {}
    for _ = 0, 14-1, 1 do
        table.insert(mod.Config.WeaponTypeConfig, InitCustomConfig())
    end
end

if mod.Config.EquipMySetConfig == nil then
    mod.Config.EquipMySetConfig = {}
end

local NOTIFICATION_MSG = {
    [CONST.LanguageType.English] = {
        FromDefault = "Apply default item set: <COLOR 00FFFF>%s</COLOR>",
        FromOption = "Apply item set: <COLOR 00FFFF>%s</COLOR> [<COLOR FFFF00>%s</COLOR>]",
        SubWeaponFallback = "SubWeapon ",
        Manual = "Manual",

        FillShell = "Shell filled.",
        FillOthers = "Other items filled.",
        ShortcutApply = "Shortcut menu set [<COLOR FFFF00>%s</COLOR>]",
        ShortcutApplyNotify = "Shortcut page %d set as %s",
        UseDefaultSetting = "Use Default Setting",
        InvalidSetting = "Auto Restock: Invalid Setting",
        NotEnough = "Item not enough.",
        NotEnoughDetail = "Item not enough, %s.",
    },
    [CONST.LanguageType.SimplifiedChinese] = {
        FromDefault = "已补充默认道具组合：<COLOR 00FFFF>%s</COLOR>",
        FromOption = "已补充道具组合：<COLOR 00FFFF>%s</COLOR>【<COLOR FFFF00>%s</COLOR>】",
        SubWeaponFallback = "副武器",
        Manual = "手动",

        FillShell = "弹药已补充。",
        FillOthers = "其他道具已补充。",
        ShortcutApply = "快捷菜单已设置【<COLOR FFFF00>%s</COLOR>】",
        ShortcutApplyNotify = "快捷菜单第 %d 页设置为：%s",
        UseDefaultSetting = "使用默认设置",
        InvalidSetting = "Auto Restock: 无效设置",
        NotEnough = "道具数量不足。",
        NotEnoughDetail = "道具数量不足：%s。",
    },
    [CONST.LanguageType.TraditionalChinese] = {
        FromDefault = "已補充默认道具組合：<COLOR 00FFFF>%s</COLOR>",
        FromOption = "已補充道具組合：<COLOR 00FFFF>%s</COLOR>【<COLOR FFFF00>%s</COLOR>】",
        SubWeaponFallback = "副武器",
        Manual = "手动",

        FillShell = "彈藥已補充",
        FillOthers = "其他道具已補充。",
        ShortcutApply = "快捷菜單已設置【<COLOR FFFF00>%s</COLOR>】",
        ShortcutApplyNotify = "快捷菜單第 %d 頁設置為：%s",
        UseDefaultSetting = "使用默认设置",
        InvalidSetting = "Auto Restock: 無效設定",
        NotEnough = "道具數量不足。",
        NotEnoughDetail = "道具數量不足：%s。",
    },
}

-- app.FacilityUtil isEnoughItem(app.ItemDef.ID, System.Int16, app.ItemUtil.STOCK_TYPE)

local function Localized()
    local lang = Core.GetLanguage()
    if not NOTIFICATION_MSG[lang] then
        lang = CONST.LanguageType.English
    end

    return NOTIFICATION_MSG[lang]
end

-- app.savedata.cEquipIndex
---@param equipParam app.savedata.cEquipParam
---@param myset app.savedata.cEquipMyset
local function EquipSetEquals(equipParam, myset)
    local usingIndex = equipParam._EquipIndex
    local box = equipParam._EquipBox

    ---@type app.savedata.cMysetEquipWork[]
    local mysetWorks = myset._MysetEquipWork
    ---@type app.savedata.cEquipIndex
    local mysetIndex = myset._MysetParam._EquipIndex

    local usingIndexArray = usingIndex.Index
    local mysetIndexArray = mysetIndex.Index

    local len = usingIndexArray:get_Count()
    if len ~= mysetIndexArray:get_Count() then
        return false
    end

    for i = 0, len-1, 1 do
        if usingIndexArray:get_Item(i) ~= mysetIndexArray:get_Item(i) then
            return false
        end
    end

    if len ~= mysetWorks:get_Count() then
        return false
    end

    for i = 0, len-1, 1 do
        local idx = usingIndexArray:get_Item(i)
        if idx == -1 then
            goto continue
        end
        local usingWork = box:get_Item(idx)
        local mysetWork = mysetWorks:get_Item(i)
        if usingWork.Category ~= mysetWork.Category then
            return false
        end
        if usingWork.Category == -1 then
            goto continue
        end
        if usingWork.GenderType ~= mysetWork.GenderType then
            return false
        end
        if usingWork.FreeVal0 ~= mysetWork.FreeVal0 then
            return false
        end
        if usingWork.FreeVal1 ~= mysetWork.FreeVal1 then
            return false
        end

        -- TODO:FIXME using 有 FreeVal2/FreeVal3；Myset 有 InsectId/IsNone
        -- if usingWork.FreeVal2 ~= mysetWork.FreeVal2 then
        --     return false
        -- end
        if not Core.CSharpIntArrayEquals(usingWork.EquipmentAccessoryIdArray, mysetWork.EquipmentAccessoryIdArray) then
            return false
        end
        if not Core.CSharpIntArrayEquals(usingWork.BowgunCustomizeId, mysetWork.BowgunCustomizeId) then
            return false
        end

        ::continue::
    end

    return true
end

local ShortcutUtil = Core.WrapTypedef("app.CustomShortcutUtil")
local ItemMySetUtil = Core.WrapTypedef("app.ItemMySetUtil")
local ItemUtil = Core.WrapTypedef("app.ItemUtil")
local ItemIDFixedToID = Core.TypeField("app.ItemDef", "FixedToID"):get_data()
local ItemUtil_StockTypeBoth = 2

---@return app.savedata.cItemMySet
local function GetItemMySet(index, requireValid)
    local data = ItemMySetUtil:StaticCall("getItemMySetData(System.Int32)", index)
    
    if requireValid == true then
        if data == nil then
            log.error(string.format("Meal at %d is nil", index))
            Core.SendMessage(string.format("Meal at %d is nil", index))
            return nil
        end
        if not data:isValidData() then
            local msgCfg = Localized()
            Core.SendMessage(msgCfg.InvalidSetting)
            return nil
        end
    end

    return data
end

---@return app.savedata.cCustomShortcutParam
local function GetShortcutMySet(index)
    return ShortcutUtil:StaticCall("getMysetCustomShortcut(System.Int32)", index)
end

-- 参数2是个看不懂且不变的数字：0x04000000
-- Core.HookFunc("app.CustomShortcutUtil", "applyMyset(System.Int32, System.Int32)", function (args)
--     Core.SendMessage(tostring(sdk.to_int64(args[3])) .. "-" .. tostring(sdk.to_int64(args[4]) & 0xFFFFFFFF))
-- end)

local RequestRestock = nil
local RequestMessage = nil

local function Apply(request, msg)
    if mod.Config.AlsoFillShells then
        ItemUtil:StaticCall("fillShellPouchItems()")
    end
    if mod.Config.AlsoFillOtherItems then
        ItemUtil:StaticCall("fillPouchItems()")
    end

    local data = GetItemMySet(request.ItemSet)
    if not data:isValidData() then
        return
    end
    -- DO NOT CALL DIRECTLY OR GAME WILL CRASH
    ItemMySetUtil:StaticCall("applyMySetToPouch(System.Int32)", request.ItemSet)
    -- ItemMySetUtil:StaticCall("apply(app.savedata.cItemMySet)", data)

    if request.UseShortcutSet then
        local msgCfg = Localized()
        for i = 0, MAX_SHORTCUT_PAGE - 1, 1 do
            local idx = request.ShortcutSet[i+1]
            if idx ~= -1 then
                local param = ShortcutUtil:StaticCall("getMysetCustomShortcut(System.Int32)", idx)
                if param:isValid() then
                    local existed = ShortcutUtil:StaticCall("getShortcutPallet(System.Int32)", i)
                    existed:setShortcut(param)
                    if mod.Config.NotifyDetailedShortcutMenu then
                        Core.BuildLongMessage(msgCfg.ShortcutApplyNotify, i+1, tostring(param.Name))
                    end
                end
            end
        end
        Core.FinishLongMessage()
    end
    Core.SendMessage(msg)
    if mod.Config.NotifyNoEnoughItems then
        local items = data._PouchItem
        local enough = true
        local ms = {}
        local s = {}
        Core.ForEach(items, function (item)
            local idFixed = item.ItemIdFixed
            local num = item.Num
            if ItemIDFixedToID:ContainsKey(idFixed) then
                local id = ItemIDFixedToID:get_Item(idFixed)
                local haveNum = ItemUtil:StaticCall("getItemNum(app.ItemDef.ID, app.ItemUtil.STOCK_TYPE)", id, ItemUtil_StockTypeBoth)
                if id < 0 then
                    return Core.ForEachBreak
                end
                if haveNum <= num then
                    enough = false
                    if mod.Config.NotifyNoEnoughItemDetails then
                        local name = Core.GetItemName(id)
                        if mod.Config.Debug then
                            Core.SendMessage("%s wants %d, has %d", name, num, haveNum)
                        end

                        s[#s+1] = name
                        if #s >= 4 then
                            ms[#ms+1] = table.concat(s,", ")
                            s = {}
                        end
                        -- return Core.ForEachBreak
                    else
                        return Core.ForEachBreak
                    end
                end
            end
        end)
        if not enough then
            if mod.Config.NotifyNoEnoughItemDetails then
                if #s > 0 then
                    ms[#ms+1] = table.concat(s,", ")
                end
                local msg = table.concat(ms,"\n")
                Core.SendMessage(Localized().NotEnoughDetail, msg)
            else
                Core.SendMessage(Localized().NotEnough)
            end
        end
    end
end

mod.HookFunc("app.GUIManager", "update()", function ()
    if RequestRestock then
        local req = RequestRestock
        local msg = RequestMessage
        RequestRestock = nil
        RequestMessage = nil
        Apply(req, msg)
    end
end)

local function ShellMessage()
    local msg = ""
    local msgCfg = Localized()

    if mod.Config.AlsoFillShells then
        msg = msg .. "\n" .. msgCfg.FillShell
    end
    if mod.Config.AlsoFillOtherItems then
        if mod.Config.AlsoFillShells then
            msg = msg .. " " .. msgCfg.FillOthers
        else
            msg = msg .. "\n" .. msgCfg.FillOthers
        end
    end
    
    return msg
end

local function RequestAutoRestock(idx)
    local msgCfg = Localized()

    if idx ~= nil then
        local data = GetItemMySet(idx, true)
        if not data then
            return
        end

        RequestMessage = string.format(msgCfg.FromOption, data.Name, msgCfg.Manual) .. ShellMessage()
        RequestRestock = {
            ItemSet = idx,
        }

        return
    end

    local msg
    local conf

    local mgr = Core.GetSaveDataManager()
    local equipMysetName
    if mgr ~= nil then
        local save = mgr:getCurrentUserSaveData() -- app.savedata.cUserSaveParam
        local equipParam = save:get_Equip() -- app.savedata.cEquipParam
        local equipMyset = equipParam:get_EquipMySet() -- app.savedata.cEquipMyset[]

        for i, cfg in pairs(mod.Config.EquipMySetConfig) do
            local myset = equipMyset:get_Item(i-1)
            local mysetName = myset._MysetParam.MysetName
            if mysetName == "" then
                goto continue
            end

            if EquipSetEquals(equipParam, myset) then
                conf = cfg
                equipMysetName = mysetName
                break
            end

            ::continue::
        end
    end

    if conf ~= nil then
        local data = GetItemMySet(conf.DefaultSet, true)
        if not data then
            return
        end
    
        msg = string.format(msgCfg.FromOption, data.Name, equipMysetName)
        if conf.UseCustomShortcutSet then
            msg = msg .. "\n3" .. string.format(msgCfg.ShortcutApply, equipMysetName)
        end
    else
        local weaponType = Core.GetPlayerWeaponType()
        local cfg = mod.Config.WeaponTypeConfig[weaponType+1]

        local isFallbackWeapon = false
        if cfg.DefaultSet == -1 and mod.Config.FallbackAnotherWeapon then
            weaponType = Core.GetPlayerSubWeaponType()
            cfg = mod.Config.WeaponTypeConfig[weaponType+1]
            isFallbackWeapon = true
        end

        if cfg.DefaultSet == -1 then
            conf = mod.Config

            local data = GetItemMySet(conf.DefaultSet, true)
            if not data then
                return
            end
        
            msg = string.format(msgCfg.FromDefault, data.Name)
            if conf.UseCustomShortcutSet then
                msg = msg .. "\n1" .. string.format(msgCfg.ShortcutApply, data.Name)
            end
        else
            conf = cfg

            local data = GetItemMySet(conf.DefaultSet, true)
            if not data then
                return
            end
        
            local wpName = Core.GetWeaponTypeName(weaponType)
            if isFallbackWeapon then
                wpName = msgCfg.SubWeaponFallback .. wpName
            end

            msg = string.format(msgCfg.FromOption, data.Name, wpName)
            if conf.UseCustomShortcutSet then
                msg = msg .. "\n2" .. string.format(msgCfg.ShortcutApply, wpName)
            end
        end
    end


    msg = msg .. ShellMessage()

    conf = {
        ItemSet = conf.DefaultSet,
        UseShortcutSet = conf.UseCustomShortcutSet,
        ShortcutSet = conf.DefaultShortcutSet
    }

    RequestMessage = msg
    RequestRestock = conf
end

Core.OnAcceptQuest(function ()
    RequestAutoRestock()
end)

Core.OnQuestEnd(function ()
    RequestAutoRestock()
end)

local ItemMySetData = {}
local ItemMySetNameMap = {}
-- local ShortcutMySetData = {}
local ShortcutMySetNameMap = {}
-- local EquipMySetData = {}
-- local EquipMySetNameMap = {}

local function InitItemMySetData()
    local firstSetIndex = -1

    if MAX_ITEM_MYSET == nil then
        MAX_ITEM_MYSET = Core.TypeField("app.ItemMySetUtil", "SET_NUM_MAX"):get_data() or 80
    end

    for i = 0, MAX_ITEM_MYSET - 1, 1 do
        local myset = GetItemMySet(i)
        if not myset:isValidData() then
            goto continue
        end

        if firstSetIndex == -1 then
            firstSetIndex = i
        end

        ItemMySetData[i] = myset
        ItemMySetNameMap[i] = myset.Name
        ::continue::
    end
    ItemMySetNameMap[-1] = Localized().UseDefaultSetting

    return firstSetIndex
end

local function InitShortcutMySetData()
    for i = 0, MAX_SHORTCUT_MYSET - 1, 1 do
        local myset = GetShortcutMySet(i)
        if not myset:isValid() then
            goto continue
        end

        -- ShortcutMySetData[i] = myset
        ShortcutMySetNameMap[i] = myset.Name
        ::continue::
    end
    ShortcutMySetNameMap[-1] = Localized().UseDefaultSetting
end

-- local function InitEquipMySetData()
--     local mgr = Core.GetSaveDataManager()
--     local save = mgr:getCurrentUserSaveData() -- app.savedata.cUserSaveParam
--     local equipParam = save:get_Equip() -- app.savedata.cEquipParam
--     local equipMyset = equipParam:get_EquipMySet() -- app.savedata.cEquipMyset[]

--     Core.ForEach(equipMyset, function (myset, i)
--         if myset._MysetParam.MysetName == "" then
--             return
--         end
--         EquipMySetData[i] = myset
--         EquipMySetNameMap[i] = myset._MysetParam.MysetName
--     end)
-- end

mod.Menu(function ()
	local configChanged = false
    local changed

    changed, mod.Config.NotifyNoEnoughItems = imgui.checkbox("Notify No Enough Items", mod.Config.NotifyNoEnoughItems)
    configChanged = configChanged or changed
    changed, mod.Config.NotifyNoEnoughItemDetails = imgui.checkbox("Notify No Enough Item Names", mod.Config.NotifyNoEnoughItemDetails)
    configChanged = configChanged or changed
    changed, mod.Config.NotifyDetailedShortcutMenu = imgui.checkbox("Notify Shortcut Menu Details", mod.Config.NotifyDetailedShortcutMenu)
    configChanged = configChanged or changed
    
    changed, mod.Config.AlsoFillShells = imgui.checkbox("Also Fill Shells", mod.Config.AlsoFillShells)
    configChanged = configChanged or changed
    changed, mod.Config.AlsoFillOtherItems = imgui.checkbox("Also Fill Other Items", mod.Config.AlsoFillOtherItems)
    configChanged = configChanged or changed

    local firstSetIndex = InitItemMySetData()
    if firstSetIndex == -1 then
        imgui.text("No item set")
        return
    end

    if mod.Config.DefaultSet == -1 then
        mod.Config.DefaultSet = firstSetIndex
    end

    InitShortcutMySetData()
    -- InitEquipMySetData()

    if mod.Config.Debug then
        for i = 0, MAX_ITEM_MYSET - 1, 1 do
            if not ItemMySetData[i] then
                goto continue
            end
            imgui.text(tostring(i) .. " MySet: " .. tostring(ItemMySetData[i].Name))
            imgui.same_line()
            if imgui.button("Apply #" .. tostring(i) .. ": " .. tostring(ItemMySetData[i].Name)) then
                RequestAutoRestock(i)
            end
            ::continue::
        end
    end

    Imgui.Rect(function ()
        mod.Runtime.ManualSet = mod.Runtime.ManualSet or mod.Config.DefaultSet
        Imgui.Button("Restock this item set:", function ()
            RequestAutoRestock(mod.Runtime.ManualSet)
        end)
        imgui.same_line()
        _, mod.Runtime.ManualSet = imgui.combo("Manual Restock This", mod.Runtime.ManualSet, ItemMySetNameMap)
        imgui.text("this will not apply shortcut menu")
    end)

    imgui.text()

    if imgui.button("Apply Restock") then
        RequestAutoRestock()
    end

    changed, mod.Config.DefaultSet = imgui.combo("Default Set", mod.Config.DefaultSet, ItemMySetNameMap)
    configChanged = configChanged or changed
    changed, mod.Config.UseCustomShortcutSet = imgui.checkbox("Use Custom Shortcut Set", mod.Config.UseCustomShortcutSet)
    configChanged = configChanged or changed

    if mod.Config.UseCustomShortcutSet then
        if imgui.tree_node("Default Shortcut Set") then
            for i = 0, MAX_SHORTCUT_PAGE-1, 1 do
                local defaultSet = mod.Config.DefaultShortcutSet[i+1]
                changed, defaultSet = imgui.combo("Page " .. tostring(i+1), defaultSet, ShortcutMySetNameMap)
                configChanged = configChanged or changed
                if changed then
                    mod.Config.DefaultShortcutSet[i+1] = defaultSet
                end
            end

            imgui.tree_pop()
        end
    end

    if imgui.tree_node("Weapon Type") then
        -- changed, mod.Config.AlsoApplySubWeapon =
        --    imgui.checkbox("Also Apply Sub Weapon", mod.Config.AlsoApplySubWeapon)
        -- configChanged = configChanged or changed

        changed, mod.Config.FallbackAnotherWeapon =
            imgui.checkbox("Use Another Weapon If Main Weapon is Default", mod.Config.FallbackAnotherWeapon)
        configChanged = configChanged or changed

        local wpType = Core.GetPlayerWeaponType()
        local wp2Type = Core.GetPlayerSubWeaponType()
        for i = 0, 14-1, 1 do
            local weaponName = Core.GetWeaponTypeName(i)

            local opened = imgui.tree_node(weaponName)
            if mod.Config.WeaponTypeConfig[i+1].DefaultSet ~= -1 then
                imgui.same_line()
                imgui.text(ItemMySetNameMap[mod.Config.WeaponTypeConfig[i+1].DefaultSet])
            end
            if i == wpType then
                imgui.same_line()
                imgui.text("#1 weapon type")
            end
            if i == wp2Type then
                imgui.same_line()
                imgui.text("#2 weapon type")
            end

            if opened then
                changed, mod.Config.WeaponTypeConfig[i+1].DefaultSet = imgui.combo(weaponName,
                    mod.Config.WeaponTypeConfig[i+1].DefaultSet, ItemMySetNameMap)
                configChanged = configChanged or changed

                changed, mod.Config.WeaponTypeConfig[i+1].UseCustomShortcutSet =
                    imgui.checkbox("Use Custom Shortcut Set", mod.Config.WeaponTypeConfig[i+1].UseCustomShortcutSet)
                configChanged = configChanged or changed

                if mod.Config.WeaponTypeConfig[i+1].UseCustomShortcutSet then
                    for j = 0, MAX_SHORTCUT_PAGE-1, 1 do
                        local set = mod.Config.WeaponTypeConfig[i+1].DefaultShortcutSet[j+1]
                        changed, set = imgui.combo("Page " .. tostring(j+1), set, ShortcutMySetNameMap)
                        configChanged = configChanged or changed
                        if changed then
                            mod.Config.WeaponTypeConfig[i+1].DefaultShortcutSet[j+1] = set
                        end
                    end
                end

                imgui.tree_pop()
            end
        end

        imgui.tree_pop()
    end

    if imgui.tree_node("Equipment Loadout") then
        local mgr = Core.GetSaveDataManager()
        local save = mgr:getCurrentUserSaveData() -- app.savedata.cUserSaveParam
        local equipParam = save:get_Equip() -- app.savedata.cEquipParam
        local equipMyset = equipParam:get_EquipMySet() -- app.savedata.cEquipMyset[]

        Core.ForEach(equipMyset, function (myset, i)
            local name = myset._MysetParam.MysetName
            if name == "" then
                mod.Config.EquipMySetConfig[i+1] = nil
                return
            end
            -- EquipMySetData[i] = myset
            -- EquipMySetNameMap[i] = name
            if mod.Config.EquipMySetConfig[i+1] == nil then
                mod.Config.EquipMySetConfig[i+1] = InitCustomConfig()
            end

            local equipWorks = myset._MysetEquipWork

            -- 0 and 7: EQUIP_INDEX WEAPON, RESERVE_WEAPON
            local wpMsg = string.format("%s|%s", Core.GetWeaponTypeName(equipWorks:get_Item(0).FreeVal0), Core.GetWeaponTypeName(equipWorks:get_Item(7).FreeVal0))

            local opened = imgui.tree_node(name .. ": " .. wpMsg)

            if mod.Config.EquipMySetConfig[i+1].DefaultSet ~= -1 then
                imgui.same_line()
                imgui.text(ItemMySetNameMap[mod.Config.EquipMySetConfig[i+1].DefaultSet])
            end

            if EquipSetEquals(equipParam, myset) then
                imgui.same_line()
                imgui.text("using")
            end

            if opened then
                changed, mod.Config.EquipMySetConfig[i+1].DefaultSet = imgui.combo(name,
                    mod.Config.EquipMySetConfig[i+1].DefaultSet, ItemMySetNameMap)
                configChanged = configChanged or changed

                changed, mod.Config.EquipMySetConfig[i+1].UseCustomShortcutSet =
                    imgui.checkbox("Use Custom Shortcut Set", mod.Config.EquipMySetConfig[i+1].UseCustomShortcutSet)
                configChanged = configChanged or changed

                if mod.Config.EquipMySetConfig[i+1].UseCustomShortcutSet then
                    for j = 0, MAX_SHORTCUT_PAGE-1, 1 do
                        local set = mod.Config.EquipMySetConfig[i+1].DefaultShortcutSet[j+1]
                        changed, set = imgui.combo("Page " .. tostring(j+1), set, ShortcutMySetNameMap)
                        configChanged = configChanged or changed
                        if changed then
                            mod.Config.EquipMySetConfig[i+1].DefaultShortcutSet[j+1] = set
                        end
                    end
                end

                imgui.tree_pop()
            end
        end)

        imgui.tree_pop()
    end

    return configChanged
end)
