"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getRandomIndexFromWeightedArray = exports.getRandomFromWeightedArray = void 0;
const array_1 = require("./array");
const random_1 = require("./random");
const utils_1 = require("./utils");
/**
 * 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 getRandomFromWeightedArray(weightedArray, seedOrRNG) {
    const randomIndex = getRandomIndexFromWeightedArray(weightedArray, seedOrRNG);
    const randomElement = weightedArray[randomIndex];
    (0, utils_1.assertDefined)(randomElement, `Failed to get an element from a weighted array using a random index of: ${randomIndex}`);
    return randomElement[0];
}
exports.getRandomFromWeightedArray = getRandomFromWeightedArray;
/**
 * 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 getRandomIndexFromWeightedArray(weightedArray, seedOrRNG) {
    if (weightedArray.length === 0) {
        error("Failed to get a random index from a weighted array since the provided array was empty.");
    }
    const weights = weightedArray.map((tuple) => tuple[1]);
    const totalWeight = (0, array_1.sumArray)(weights);
    const randomWeight = (0, random_1.getRandomFloat)(0, totalWeight, seedOrRNG);
    let weightAccumulator = 0;
    for (const [i, tuple] of weightedArray.entries()) {
        const [_element, weight] = tuple;
        weightAccumulator += weight;
        if (weightAccumulator >= randomWeight) {
            return i;
        }
    }
    error("Failed to get a random index from a weighted array.");
}
exports.getRandomIndexFromWeightedArray = getRandomIndexFromWeightedArray;
