local ____lualib = require("lualib_bundle")
local __TS__ArrayMap = ____lualib.__TS__ArrayMap
local __TS__ArrayEntries = ____lualib.__TS__ArrayEntries
local __TS__Iterator = ____lualib.__TS__Iterator
local ____exports = {}
local ____array = require("functions.array")
local sumArray = ____array.sumArray
local ____random = require("functions.random")
local getRandomFloat = ____random.getRandomFloat
local ____utils = require("functions.utils")
local assertDefined = ____utils.assertDefined
--- Get a random index from a `WeightedArray`. (A `WeightedArray` is an array of tuples, where the
-- first element in the tuple is a value, and the second element in the tuple is a float
-- corresponding to the value's weight.)
-- 
-- If you want to get an unseeded index, you must explicitly pass `undefined` to the `seedOrRNG`
-- parameter.
-- 
-- @param weightedArray The array to pick 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.
function ____exports.getRandomIndexFromWeightedArray(self, weightedArray, seedOrRNG)
    if #weightedArray == 0 then
        error("Failed to get a random index from a weighted array since the provided array was empty.")
    end
    local weights = __TS__ArrayMap(
        weightedArray,
        function(____, tuple) return tuple[2] end
    )
    local totalWeight = sumArray(nil, weights)
    local randomWeight = getRandomFloat(nil, 0, totalWeight, seedOrRNG)
    local weightAccumulator = 0
    for ____, ____value in __TS__Iterator(__TS__ArrayEntries(weightedArray)) do
        local i = ____value[1]
        local tuple = ____value[2]
        local _element, weight = table.unpack(tuple)
        weightAccumulator = weightAccumulator + weight
        if weightAccumulator >= randomWeight then
            return i
        end
    end
    error("Failed to get a random index from a weighted array.")
end
--- Get a random value from a `WeightedArray`. (A `WeightedArray` is an array of tuples, where the
-- first element in the tuple is a value, and the second element in the tuple is a float
-- corresponding to the value's weight.)
-- 
-- If you want to get an unseeded element, you must explicitly pass `undefined` to the `seedOrRNG`
-- parameter.
-- 
-- @param weightedArray The array to pick 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.
function ____exports.getRandomFromWeightedArray(self, weightedArray, seedOrRNG)
    local randomIndex = ____exports.getRandomIndexFromWeightedArray(nil, weightedArray, seedOrRNG)
    local randomElement = weightedArray[randomIndex + 1]
    assertDefined(
        nil,
        randomElement,
        "Failed to get an element from a weighted array using a random index of: " .. tostring(randomIndex)
    )
    return randomElement[1]
end
return ____exports
