local ____lualib = require("lualib_bundle")
local __TS__ObjectEntries = ____lualib.__TS__ObjectEntries
local __TS__ArrayFilter = ____lualib.__TS__ArrayFilter
local __TS__ArraySort = ____lualib.__TS__ArraySort
local __TS__ArrayMap = ____lualib.__TS__ArrayMap
local __TS__ArrayToSorted = ____lualib.__TS__ArrayToSorted
local __TS__ArrayAt = ____lualib.__TS__ArrayAt
local __TS__ArrayIncludes = ____lualib.__TS__ArrayIncludes
local __TS__New = ____lualib.__TS__New
local ____exports = {}
local ____ReadonlySet = require("types.ReadonlySet")
local ReadonlySet = ____ReadonlySet.ReadonlySet
local ____array = require("functions.array")
local getRandomArrayElement = ____array.getRandomArrayElement
local ____sort = require("functions.sort")
local sortNormal = ____sort.sortNormal
local ____types = require("functions.types")
local isNumber = ____types.isNumber
local isString = ____types.isString
local ____utils = require("functions.utils")
local assertDefined = ____utils.assertDefined
local iRange = ____utils.iRange
--- TypeScriptToLua will transpile TypeScript number enums to Lua tables that have a double mapping.
-- Thus, when you iterate over them, you will get both the names of the enums and the values of the
-- enums, in a random order. Use this helper function to get the entries of the enum with the
-- reverse mappings filtered out.
-- 
-- This function will return the enum values in a sorted order, which may not necessarily be the
-- same order as which they were declared in. (It is impossible to get the declaration order at
-- run-time.)
-- 
-- This function will work properly for both number enums and string enums. (Reverse mappings are
-- not created for string enums.)
-- 
-- Also see the `getEnumKeys` and `getEnumValues` helper functions.
-- 
-- For a more in depth explanation, see:
-- https://isaacscript.github.io/main/gotchas#iterating-over-enums
function ____exports.getEnumEntries(self, transpiledEnum)
    local entries = __TS__ObjectEntries(transpiledEnum)
    local numberEntries = __TS__ArrayFilter(
        entries,
        function(____, ____bindingPattern0)
            local value
            local _key = ____bindingPattern0[1]
            value = ____bindingPattern0[2]
            return type(value) == "number"
        end
    )
    local entriesToReturn = #numberEntries > 0 and numberEntries or entries
    __TS__ArraySort(
        entriesToReturn,
        function(____, ____bindingPattern0, ____bindingPattern1)
            local value1
            local _key1 = ____bindingPattern0[1]
            value1 = ____bindingPattern0[2]
            local value2
            local _key2 = ____bindingPattern1[1]
            value2 = ____bindingPattern1[2]
            return value1 < value2 and -1 or (value1 > value2 and 1 or 0)
        end
    )
    return entriesToReturn
end
--- TypeScriptToLua will transpile TypeScript number enums to Lua tables that have a double mapping.
-- Thus, when you iterate over them, you will get both the names of the enums and the values of the
-- enums, in a random order. If all you need are the keys of an enum, use this helper function.
-- 
-- This function will return the enum keys in a sorted order, which may not necessarily be the same
-- order as which they were declared in. (It is impossible to get the declaration order at
-- run-time.)
-- 
-- This function will work properly for both number enums and string enums. (Reverse mappings are
-- not created for string enums.)
-- 
-- Also see the `getEnumEntries` and `getEnumValues` helper functions.
-- 
-- For a more in depth explanation, see:
-- https://isaacscript.github.io/main/gotchas#iterating-over-enums
function ____exports.getEnumKeys(self, transpiledEnum)
    local enumEntries = ____exports.getEnumEntries(nil, transpiledEnum)
    return __TS__ArrayMap(
        enumEntries,
        function(____, ____bindingPattern0)
            local key
            key = ____bindingPattern0[1]
            local _value = ____bindingPattern0[2]
            return key
        end
    )
end
--- Helper function to get the amount of entries inside of an enum.
function ____exports.getEnumLength(self, transpiledEnum)
    local enumEntries = ____exports.getEnumEntries(nil, transpiledEnum)
    return #enumEntries
end
--- TypeScriptToLua will transpile TypeScript number enums to Lua tables that have a double mapping.
-- Thus, when you iterate over them, you will get both the names of the enums and the values of the
-- enums, in a random order. If all you need are the names of an enum from the reverse mapping, use
-- this helper function.
-- 
-- This function will return the enum names in a sorted order, which may not necessarily be the same
-- order as which they were declared in. (It is impossible to get the declaration order at
-- run-time.)
-- 
-- This function will work properly for both number enums and string enums. (Reverse mappings are
-- not created for string enums, so their names would be equivalent to what would be returned by the
-- `getEnumKeys` function.)
-- 
-- For a more in depth explanation, see:
-- https://isaacscript.github.io/main/gotchas#iterating-over-enums
function ____exports.getEnumNames(self, transpiledEnum)
    local enumNames = {}
    for key, _value in pairs(transpiledEnum) do
        if isString(nil, key) then
            enumNames[#enumNames + 1] = key
        end
    end
    __TS__ArraySort(enumNames)
    return enumNames
end
--- TypeScriptToLua will transpile TypeScript number enums to Lua tables that have a double mapping.
-- Thus, when you iterate over them, you will get both the names of the enums and the values of the
-- enums, in a random order. If all you need are the values of an enum, use this helper function.
-- 
-- This function will return the enum values in a sorted order, which may not necessarily be the
-- same order as which they were declared in. (It is impossible to get the declaration order at
-- run-time.)
-- 
-- This function will work properly for both number enums and string enums. (Reverse mappings are
-- not created for string enums.)
-- 
-- Also see the `getEnumEntries` and `getEnumKeys` helper functions.
-- 
-- For a more in depth explanation, see:
-- https://isaacscript.github.io/main/gotchas#iterating-over-enums
function ____exports.getEnumValues(self, transpiledEnum)
    local enumEntries = ____exports.getEnumEntries(nil, transpiledEnum)
    return __TS__ArrayMap(
        enumEntries,
        function(____, ____bindingPattern0)
            local value
            local _key = ____bindingPattern0[1]
            value = ____bindingPattern0[2]
            return value
        end
    )
end
--- Helper function to get the enum value with the highest value.
-- 
-- Note that this is not necessarily the enum value that is declared last in the code, since there
-- is no way to infer that at run-time.
-- 
-- Throws an error if the provided enum is empty.
function ____exports.getHighestEnumValue(self, transpiledEnum)
    local enumValues = ____exports.getEnumValues(nil, transpiledEnum)
    local sortedValues = __TS__ArrayToSorted(enumValues, sortNormal)
    local lastElement = __TS__ArrayAt(sortedValues, -1)
    assertDefined(nil, lastElement, "Failed to get the highest value from an enum since the enum was empty.")
    return lastElement
end
--- Helper function to get the enum value with the lowest value.
-- 
-- Note that this is not necessarily the enum value that is declared first in the code, since there
-- is no way to infer that at run-time.
-- 
-- Throws an error if the provided enum is empty.
function ____exports.getLowestEnumValue(self, transpiledEnum)
    local enumValues = ____exports.getEnumValues(nil, transpiledEnum)
    local sortedValues = __TS__ArrayToSorted(enumValues, sortNormal)
    local firstElement = sortedValues[1]
    assertDefined(nil, firstElement, "Failed to get the lowest value from an enum since the enum was empty.")
    return firstElement
end
--- Helper function to get a random value from the provided enum.
-- 
-- If you want an unseeded value, you must explicitly pass `undefined` to the `seedOrRNG` parameter.
-- 
-- @param transpiledEnum The enum to get the value from.
-- @param seedOrRNG The `Seed` or `RNG` object to use. If an `RNG` object is provided, the
-- `RNG.Next` method will be called. If `undefined` is provided, it will default to
-- a random seed.
-- @param exceptions Optional. An array of elements to skip over if selected.
function ____exports.getRandomEnumValue(self, transpiledEnum, seedOrRNG, exceptions)
    if exceptions == nil then
        exceptions = {}
    end
    local enumValues = ____exports.getEnumValues(nil, transpiledEnum)
    return getRandomArrayElement(nil, enumValues, seedOrRNG, exceptions)
end
--- Helper function to validate that a particular value exists inside of an enum.
function ____exports.isEnumValue(self, value, transpiledEnum)
    local enumValues = ____exports.getEnumValues(nil, transpiledEnum)
    return __TS__ArrayIncludes(enumValues, value)
end
--- Helper function to check every value of a custom enum for -1. Will throw an run-time error if any
-- -1 values are found. This is helpful because many methods of the Isaac class return -1 if they
-- fail.
-- 
-- For example:
-- 
-- ```ts
-- enum EntityTypeCustom {
--   FOO = Isaac.GetEntityTypeByName("Foo"),
-- }
-- 
-- validateCustomEnum("EntityTypeCustom", EntityTypeCustom);
-- ```
function ____exports.validateCustomEnum(self, transpiledEnumName, transpiledEnum)
    for ____, ____value in ipairs(____exports.getEnumEntries(nil, transpiledEnum)) do
        local key = ____value[1]
        local value = ____value[2]
        if value == -1 then
            error((("Failed to find the custom enum value: " .. transpiledEnumName) .. ".") .. key)
        end
    end
end
--- Helper function to validate if every value in a number enum is contiguous, starting at 0.
-- 
-- This is useful to automate checking large enums for typos.
function ____exports.validateEnumContiguous(self, transpiledEnumName, transpiledEnum)
    local values = ____exports.getEnumValues(nil, transpiledEnum)
    local lastValue = __TS__ArrayAt(values, -1)
    assertDefined(nil, lastValue, "Failed to validate that an enum was contiguous, since the last value was undefined.")
    if not isNumber(nil, lastValue) then
        error("Failed to validate that an enum was contiguous, since the last value was not a number.")
    end
    local valuesSet = __TS__New(ReadonlySet, values)
    for ____, value in ipairs(iRange(nil, lastValue)) do
        if not valuesSet:has(value) then
            error((("Failed to find a custom enum value of " .. tostring(value)) .. " for: ") .. transpiledEnumName)
        end
    end
end
--- Helper function to validate that an interface contains all of the keys of an enum. You must
-- specify both generic parameters in order for this to work properly (i.e. the interface and then
-- the enum).
-- 
-- For example:
-- 
-- ```ts
-- enum MyEnum {
--   Value1,
--   Value2,
--   Value3,
-- }
-- 
-- interface MyEnumToType {
--   [MyEnum.Value1]: boolean;
--   [MyEnum.Value2]: number;
--   [MyEnum.Value3]: string;
-- }
-- 
-- validateInterfaceMatchesEnum<MyEnumToType, MyEnum>();
-- ```
-- 
-- This function is only meant to be used with interfaces (i.e. types that will not exist at
-- run-time). If you are generating an object that will contain all of the keys of an enum, use the
-- `satisfies` operator with the `Record` type instead.
function ____exports.validateInterfaceMatchesEnum(self)
end
return ____exports
