import { randomIntegerBetween } from "../../math/random/randomIntegerBetween.js";
import { array_swap_one } from "./array_swap_one.js";

/**
 * Randomly re-orders items in-place using Fisher–Yates.
 *
 * Pass `length` when shuffling a prefix of a larger buffer (e.g. a scratch
 * typed array sized for a worst-case but containing only a smaller active
 * range). Elements beyond `length` are untouched. Default is `array.length`,
 * which gives the natural "shuffle the whole thing" behaviour.
 *
 * @template T
 * @param {function():number} random random number generator; can use Math.random. Must return a value between 0 and 1
 * @param {T[]|TypedArray} array what to shuffle (mutated in place)
 * @param {number} [length] how many leading entries of `array` to shuffle; defaults to `array.length`
 */
export function array_shuffle(random, array, length = array.length) {
    for (let source_index = 0; source_index < length; ++source_index) {
        const target_index = randomIntegerBetween(random, 0, length - (source_index + 1));

        if (target_index === source_index) {
            continue;
        }

        array_swap_one(array, source_index, target_index);
    }
}
