MS_IndicatorOrder = MS_IndicatorOrder or {}

MS_IndicatorOrder.ORIGINAL_SORT_ORDER = {
    ["ISBleedingStatusIndicator"] = 1,
    ["MS_BleedingIndicator"] = 1,
    ["MS_CarryWeightIndicator"] = 2,
    ["ISCarryWeightStatusIndicator"] = 2,
    ["MS_HealthIndicator"] = 3,
    ["ISHealthStatusIndicator"] = 3,
    ["MS_HungerIndicator"] = 4,
    ["ISHungerStatusIndicator"] = 4,
    ["MS_ThirstIndicator"] = 5,
    ["ISThirstStatusIndicator"] = 5,
    ["MS_EnduranceIndicator"] = 6,
    ["ISEnduranceStatusIndicator"] = 6,
    ["MS_FatigueIndicator"] = 7,
    ["ISFatigueStatusIndicator"] = 7,
    ["MS_StressIndicator"] = 8,
    ["ISStressStatusIndicator"] = 8,
    ["MS_PanicIndicator"] = 9,
    ["ISPanicStatusIndicator"] = 9,
    ["MS_BoredomIndicator"] = 10,
    ["ISBoredomStatusIndicator"] = 10,
    ["MS_DiscomfortIndicator"] = 11,
    ["ISDiscomfortStatusIndicator"] = 11,
    ["MS_UnhappynessIndicator"] = 12,
    ["ISUnhappynessStatusIndicator"] = 12,
    ["MS_AngerIndicator"] = 13,
    ["ISAngerStatusIndicator"] = 13,
    ["MS_DrunkennessIndicator"] = 14,
    ["ISDrunkennessStatusIndicator"] = 14,
    ["MS_MedicineIndicator"] = 15,
    ["ISMedicineStatusIndicator"] = 15,
    ["MS_StiffnessIndicator"] = 16,
    ["ISStiffnessStatusIndicator"] = 16,
    ["MS_PainIndicator"] = 17,
    ["ISPainStatusIndicator"] = 17,
    ["MS_PoisonIndicator"] = 18,
    ["ISPoisonStatusIndicator"] = 18,
    ["MS_NoxiousExposureIndicator"] = 19,
    ["ISNoxiousExposureStatusIndicator"] = 19,
    ["MS_SicknessIndicator"] = 20,
    ["ISSicknessStatusIndicator"] = 20,
    ["MS_WetnessIndicator"] = 21,
    ["ISWetnessStatusIndicator"] = 21,
    ["MS_WindchillIndicator"] = 22,
    ["ISWindchillStatusIndicator"] = 22,
    ["MS_TemperatureIndicator"] = 23,
    ["ISTemperatureStatusIndicator"] = 23,
    ["MS_CatchAColdIndicator"] = 24,
    ["ISCatchAColdStatusIndicator"] = 24,
    ["MS_FoodHealingIndicator"] = 25,
    ["ISFoodHealingStatusIndicator"] = 25,
    ["MS_WeightIndicator"] = 26,
    ["ISWeightStatusIndicator"] = 26,
    ["MS_CalorieIndicator"] = 27,
    ["ISCalorieStatusIndicator"] = 27,
    ["MS_CarbohydratesIndicator"] = 28,
    ["ISCarbohydratesStatusIndicator"] = 28,
    ["MS_ProteinsIndicator"] = 29,
    ["ISProteinsStatusIndicator"] = 29,
    ["MS_LipidsIndicator"] = 30,
    ["ISLipidsStatusIndicator"] = 30,
    ["MS_DirtinessIndicator"] = 31,
    ["ISDirtinessStatusIndicator"] = 31,
    ["MS_BloodinessIndicator"] = 32,
    ["ISBloodinessStatusIndicator"] = 32,
    ["ISHygieneNeedStatusIndicator"] = 33,
    ["ISBathroomNeedStatusIndicator"] = 34,
    ["ISTABASBodyGrimeStatusIndicator"] = 35,
    ["ISWORCombinedStatusIndicator"] = 36,
    ["ISExcStomachStatusIndicator"] = 37,
    ["ISExcColonStatusIndicator"] = 38,
    ["ISExcUrineStatusIndicator"] = 39,
    ["ISExcSmellStatusIndicator"] = 40,
    ["ISExcShameStatusIndicator"] = 41,
    ["ISNCBladderStatusIndicator"] = 42,
    ["ISNCBowelStatusIndicator"] = 43,
    ["ISNCGutHealthStatusIndicator"] = 44,
    ["ISNCSoilageStatusIndicator"] = 45,
    ["ISNCDigestiveEffectsStatusIndicator"] = 46,
}
function MS_IndicatorOrder.getOriginalSortOrder(indicatorType)
    return MS_IndicatorOrder.ORIGINAL_SORT_ORDER[indicatorType] or 10000
end

function MS_IndicatorOrder.getOriginalOrderCount()
    local count = 0
    for _, _ in pairs(MS_IndicatorOrder.ORIGINAL_SORT_ORDER) do
        count = count + 1
    end
    return count
end

local function _isIndicatorTable(path)
    return type(path) == "table" and path[#path] == "indicators"
end

local function _compareGeneric(a, b)
    local typeA = type(a)
    local typeB = type(b)

    if typeA == typeB then
        if typeA == "number" then
            return a < b
        elseif typeA == "string" then
            local lowerA = string.lower(a)
            local lowerB = string.lower(b)
            if lowerA == lowerB then
                return a < b
            end
            return lowerA < lowerB
        elseif typeA == "boolean" then
            return a == true and b == false
        end
    end

    local rank = {
        number = 1,
        string = 2,
        boolean = 3,
        table = 4,
        ["function"] = 5,
        userdata = 6,
        thread = 7,
        ["nil"] = 8,
    }

    return (rank[typeA] or 99) < (rank[typeB] or 99)
end

function MS_IndicatorOrder.compareKeys(a, b, path)
    if _isIndicatorTable(path) and type(a) == "string" and type(b) == "string" then
        local orderA = MS_IndicatorOrder.getOriginalSortOrder(a)
        local orderB = MS_IndicatorOrder.getOriginalSortOrder(b)
        if orderA ~= orderB then
            return orderA < orderB
        end
    end

    return _compareGeneric(a, b)
end

function MS_IndicatorOrder.getSortedKeys(tbl, path)
    local keys = {}
    for key, _ in pairs(tbl or {}) do
        keys[#keys + 1] = key
    end

    table.sort(keys, function(a, b)
        return MS_IndicatorOrder.compareKeys(a, b, path)
    end)

    return keys
end
