local ____lualib = require("lualib_bundle")
local __TS__ArrayMap = ____lualib.__TS__ArrayMap
local __TS__ArrayFilter = ____lualib.__TS__ArrayFilter
local ____exports = {}
local getTotalWeightOfCustomStageRooms, getCustomStageRoomWithChosenWeight, getTotalWeightOfBossPool, getBossEntryWithChosenWeight
local ____array = require("functions.array")
local sumArray = ____array.sumArray
local ____log = require("functions.log")
local log = ____log.log
local ____random = require("functions.random")
local getRandomFloat = ____random.getRandomFloat
function getTotalWeightOfCustomStageRooms(self, roomsMetadata)
    local weights = __TS__ArrayMap(
        roomsMetadata,
        function(____, roomMetadata) return roomMetadata.weight end
    )
    return sumArray(nil, weights)
end
function getCustomStageRoomWithChosenWeight(self, roomsMetadata, chosenWeight)
    for ____, roomMetadata in ipairs(roomsMetadata) do
        if chosenWeight < roomMetadata.weight then
            return roomMetadata
        end
        chosenWeight = chosenWeight - roomMetadata.weight
    end
    error("Failed to get a custom stage room with chosen weight: " .. tostring(chosenWeight))
end
function getTotalWeightOfBossPool(self, bossPool)
    local weights = __TS__ArrayMap(
        bossPool,
        function(____, bossEntry) return bossEntry.weight end
    )
    return sumArray(nil, weights)
end
function getBossEntryWithChosenWeight(self, bossPool, chosenWeight)
    for ____, bossEntry in ipairs(bossPool) do
        if chosenWeight < bossEntry.weight then
            return bossEntry
        end
        chosenWeight = chosenWeight - bossEntry.weight
    end
    error("Failed to get a custom stage boss entry with chosen weight: " .. tostring(chosenWeight))
end
--- Helper function to get a random custom stage room from an array of custom stage rooms.
-- 
-- Note that this function does not simply choose a random element in the provided array; it will
-- properly account for each room weight using the algorithm from:
-- https://stackoverflow.com/questions/1761626/weighted-random-numbers
function ____exports.getRandomCustomStageRoom(self, roomsMetadata, seedOrRNG, verbose)
    if verbose == nil then
        verbose = false
    end
    local totalWeight = getTotalWeightOfCustomStageRooms(nil, roomsMetadata)
    if verbose then
        log("Total weight of the custom stage rooms provided: " .. tostring(totalWeight))
    end
    local chosenWeight = getRandomFloat(nil, 0, totalWeight, seedOrRNG)
    if verbose then
        log("Randomly chose weight for custom stage room: " .. tostring(chosenWeight))
    end
    return getCustomStageRoomWithChosenWeight(nil, roomsMetadata, chosenWeight)
end
function ____exports.getRandomBossRoomFromPool(self, roomsMetadata, bossPool, seedOrRNG, verbose)
    if verbose == nil then
        verbose = false
    end
    local totalWeight = getTotalWeightOfBossPool(nil, bossPool)
    if verbose then
        log("Total weight of the custom stage boss pool provided: " .. tostring(totalWeight))
    end
    local chosenWeight = getRandomFloat(nil, 0, totalWeight, seedOrRNG)
    if verbose then
        log("Randomly chose weight for custom stage boss pool: " .. tostring(chosenWeight))
    end
    local bossEntry = getBossEntryWithChosenWeight(nil, bossPool, chosenWeight)
    local roomsMetadataForBoss = __TS__ArrayFilter(
        roomsMetadata,
        function(____, roomMetadata) return roomMetadata.subType == bossEntry.subType end
    )
    return ____exports.getRandomCustomStageRoom(nil, roomsMetadataForBoss, seedOrRNG, verbose)
end
return ____exports
