"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.clone = clone;
exports.generateUUIDv4 = generateUUIDv4;
exports.generateRandomNumber = generateRandomNumber;
exports.getRtpParametersType = getRtpParametersType;
exports.parseVector = parseVector;
exports.parseStringStringVector = parseStringStringVector;
exports.parseStringUint8Vector = parseStringUint8Vector;
exports.parseUint16StringVector = parseUint16StringVector;
exports.parseUint32StringVector = parseUint32StringVector;
exports.parseStringStringArrayVector = parseStringStringArrayVector;
exports.deepFreeze = deepFreeze;
const node_crypto_1 = require("node:crypto");
const rtp_parameters_1 = require("./fbs/rtp-parameters");
/**
 * Clones the given value.
 */
function clone(value) {
    if (value === undefined) {
        return undefined;
    }
    else if (Number.isNaN(value)) {
        return NaN;
    }
    else if (typeof structuredClone === 'function') {
        // Available in Node >= 18.
        return structuredClone(value);
    }
    else {
        return JSON.parse(JSON.stringify(value));
    }
}
/**
 * Generates a random UUID v4.
 */
function generateUUIDv4() {
    return (0, node_crypto_1.randomUUID)();
}
/**
 * Generates a random positive integer.
 */
function generateRandomNumber() {
    return (0, node_crypto_1.randomInt)(100_000_000, 999_999_999);
}
/**
 * Get the flatbuffers RtpParameters type for a given Producer.
 */
function getRtpParametersType(producerType, pipe) {
    if (pipe) {
        return rtp_parameters_1.Type.PIPE;
    }
    switch (producerType) {
        case 'simple': {
            return rtp_parameters_1.Type.SIMPLE;
        }
        case 'simulcast': {
            return rtp_parameters_1.Type.SIMULCAST;
        }
        case 'svc': {
            return rtp_parameters_1.Type.SVC;
        }
    }
}
/**
 * Parse flatbuffers vector into an array of the given type.
 */
function parseVector(binary, methodName, parseFn) {
    const array = [];
    for (let i = 0; i < binary[`${methodName}Length`](); ++i) {
        if (parseFn) {
            array.push(parseFn(binary[methodName](i)));
        }
        else {
            array.push(binary[methodName](i));
        }
    }
    return array;
}
/**
 * Parse flatbuffers vector of StringString into the corresponding array.
 */
function parseStringStringVector(binary, methodName) {
    const array = [];
    for (let i = 0; i < binary[`${methodName}Length`](); ++i) {
        const kv = binary[methodName](i);
        array.push({ key: kv.key(), value: kv.value() });
    }
    return array;
}
/**
 * Parse flatbuffers vector of StringUint8 into the corresponding array.
 */
function parseStringUint8Vector(binary, methodName) {
    const array = [];
    for (let i = 0; i < binary[`${methodName}Length`](); ++i) {
        const kv = binary[methodName](i);
        array.push({ key: kv.key(), value: kv.value() });
    }
    return array;
}
/**
 * Parse flatbuffers vector of Uint16String into the corresponding array.
 */
function parseUint16StringVector(binary, methodName) {
    const array = [];
    for (let i = 0; i < binary[`${methodName}Length`](); ++i) {
        const kv = binary[methodName](i);
        array.push({ key: kv.key(), value: kv.value() });
    }
    return array;
}
/**
 * Parse flatbuffers vector of Uint32String into the corresponding array.
 */
function parseUint32StringVector(binary, methodName) {
    const array = [];
    for (let i = 0; i < binary[`${methodName}Length`](); ++i) {
        const kv = binary[methodName](i);
        array.push({ key: kv.key(), value: kv.value() });
    }
    return array;
}
/**
 * Parse flatbuffers vector of StringStringArray into the corresponding array.
 */
function parseStringStringArrayVector(binary, methodName) {
    const array = [];
    for (let i = 0; i < binary[`${methodName}Length`](); ++i) {
        const kv = binary[methodName](i);
        const values = [];
        for (let i2 = 0; i2 < kv.valuesLength(); ++i2) {
            values.push(kv.values(i2));
        }
        array.push({ key: kv.key(), values });
    }
    return array;
}
/**
 * Make an object or array recursively immutable.
 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze.
 */
function deepFreeze(object) {
    // Retrieve the property names defined on object.
    const propNames = Reflect.ownKeys(object);
    // Freeze properties before freezing self.
    for (const name of propNames) {
        const value = object[name];
        if ((value && typeof value === 'object') || typeof value === 'function') {
            deepFreeze(value);
        }
    }
    return Object.freeze(object);
}
