local ____lualib = require("lualib_bundle")
local __TS__TypeOf = ____lualib.__TS__TypeOf
local __TS__ObjectKeys = ____lualib.__TS__ObjectKeys
local __TS__ArrayEvery = ____lualib.__TS__ArrayEvery
local __TS__ArraySort = ____lualib.__TS__ArraySort
local ____exports = {}
local ____types = require("functions.types")
local isBoolean = ____types.isBoolean
local isNumber = ____types.isNumber
local isString = ____types.isString
local isUserdata = ____types.isUserdata
local ____utils = require("functions.utils")
local assertDefined = ____utils.assertDefined
--- In a `Map`, you can use the `clear` method to delete every element. However, in a `LuaMap`, the
-- `clear` method does not exist. Use this helper function as a drop-in replacement for this.
function ____exports.clearTable(self, luaMap)
    for key in pairs(luaMap) do
        luaMap[key] = nil
    end
end
--- Helper function to copy specific values from a userdata object (e.g. `Vector`) to a table.
function ____exports.copyUserdataValuesToTable(self, object, keys, luaMap)
    if not isUserdata(nil, object) then
        error("Failed to copy an object values to a table, since the object was of type: " .. type(object))
    end
    local userdata = object
    for ____, key in ipairs(keys) do
        local value = userdata[key]
        luaMap[key] = value
    end
end
--- Helper function to safely get boolean values from a Lua table. Will throw an error if the
-- specific value does not exist on the table.
-- 
-- This function is variadic, meaning that you can specify N arguments to get N values.
function ____exports.getBooleansFromTable(self, luaMap, objectName, ...)
    local keys = {...}
    local booleans = {}
    for ____, key in ipairs(keys) do
        local value = luaMap[key]
        assertDefined(nil, value, ((("Failed to find a value for \"" .. key) .. "\" in a table representing a \"") .. objectName) .. "\" object.")
        if isBoolean(nil, value) then
            booleans[#booleans + 1] = value
        else
            error((((("Failed to get the boolean for the \"" .. key) .. "\" value of a table representing a \"") .. objectName) .. "\" object because the type was: ") .. __TS__TypeOf(value))
        end
    end
    return booleans
end
--- Helper function to safely get number values from specific keys on a Lua table. Will throw an
-- error if the specific value does not exist on the table or if it cannot be converted to a number.
-- 
-- This function is variadic, meaning that you can specify N arguments to get N values.
function ____exports.getNumbersFromTable(self, luaMap, objectName, ...)
    local keys = {...}
    local numbers = {}
    for ____, key in ipairs(keys) do
        local value = luaMap[key]
        assertDefined(nil, value, ((("Failed to find a value for \"" .. key) .. "\" in a table representing a \"") .. objectName) .. "\" object.")
        if isNumber(nil, value) then
            numbers[#numbers + 1] = value
        elseif isString(nil, value) then
            local number = tonumber(value)
            assertDefined(nil, number, (((("Failed to convert the \"" .. key) .. "\" value of a table representing a \"") .. objectName) .. "\" object to a number: ") .. value)
            numbers[#numbers + 1] = number
        else
            error((((("Failed to get the number for the \"" .. key) .. "\" value of a table representing a \"") .. objectName) .. "\" object because the type was: ") .. __TS__TypeOf(value))
        end
    end
    return numbers
end
--- Helper function to safely get string values from a Lua table. Will throw an error if the specific
-- value does not exist on the table.
-- 
-- This function is variadic, meaning that you can specify N arguments to get N values.
function ____exports.getStringsFromTable(self, luaMap, objectName, ...)
    local keys = {...}
    local strings = {}
    for ____, key in ipairs(keys) do
        local value = luaMap[key]
        assertDefined(nil, value, ((("Failed to find a value for \"" .. key) .. "\" in a table representing a \"") .. objectName) .. "\" object.")
        if isString(nil, value) then
            strings[#strings + 1] = value
        else
            local ____string = tostring(value)
            strings[#strings + 1] = ____string
        end
    end
    return strings
end
--- Helper function to check if a Lua table has 0 keys.
function ____exports.isTableEmpty(self, luaMap)
    for _key, _value in pairs(luaMap) do
        return false
    end
    return true
end
--- Helper function to iterate over a table deterministically. This is useful because by default, the
-- `pairs` function will return the keys of a Lua table in a random order.
-- 
-- This function will sort the table entries based on the value of the key.
-- 
-- This function will only work on tables that have number keys or string keys. It will throw a
-- run-time error if it encounters a key of another type.
-- 
-- @param luaMap The table to iterate over.
-- @param func The function to run for each iteration.
-- @param inOrder Optional. Whether to iterate in order. True by default. You can dynamically set to
-- false in situations where iterating randomly would not matter and you need the
-- extra performance.
function ____exports.iterateTableInOrder(self, luaMap, func, inOrder)
    if inOrder == nil then
        inOrder = true
    end
    if not inOrder then
        for key, value in pairs(luaMap) do
            func(nil, key, value)
        end
        return
    end
    local keys = __TS__ObjectKeys(luaMap)
    local hasAllNumberKeys = __TS__ArrayEvery(
        keys,
        function(____, key) return isNumber(nil, key) end
    )
    local hasAllStringKeys = __TS__ArrayEvery(
        keys,
        function(____, key) return isString(nil, key) end
    )
    if not hasAllNumberKeys and not hasAllStringKeys then
        for key, value in pairs(luaMap) do
            func(nil, key, value)
        end
        return
    end
    __TS__ArraySort(keys)
    for ____, key in ipairs(keys) do
        local keyIndex = key
        local value = luaMap[keyIndex]
        if value ~= nil then
            func(nil, keyIndex, value)
        end
    end
end
--- Helper function to check if a Lua table has all of the provided keys.
-- 
-- This function is variadic, meaning that you can specify as many arguments as you want to check
-- for.
function ____exports.tableHasKeys(self, luaMap, ...)
    local keys = {...}
    return __TS__ArrayEvery(
        keys,
        function(____, key) return luaMap[key] ~= nil end
    )
end
return ____exports
