/**
 * sprintf.ts
 *
 * Converted to a pure, strictly-typed TypeScript module.
 */
export default function sprintf(format, ...args) {
    let i = 0;
    const regex = /%%|%(\d+\$)?([-+'#0 ]*)(\*\d+\$|\*|\d+)?(\.(\*\d+\$|\*|\d+))?([scboxXuidfegEG])/g;
    const pad = (str, len, chr, leftJustify) => {
        const padding = str.length >= len ? '' : Array.from({ length: 1 + len - str.length }).join(chr || ' ');
        return leftJustify ? str + padding : padding + str;
    };
    const justify = (value, prefix, leftJustify, minWidth, zeroPad, customPadChar) => {
        const diff = minWidth - value.length;
        if (diff > 0) {
            if (leftJustify || !zeroPad) {
                value = pad(value, minWidth, customPadChar || ' ', leftJustify);
            }
            else {
                value = value.slice(0, prefix.length) + pad('', diff, '0', true) + value.slice(prefix.length);
            }
        }
        return value;
    };
    const formatBaseX = (value, base, prefix, leftJustify, minWidth, precision, zeroPad) => {
        const number = value >>> 0;
        const p = (prefix && number && { 2: '0b', 8: '0', 16: '0x' }[base]) || '';
        const val = p + pad(number.toString(base), precision || 0, '0', false);
        return justify(val, p, leftJustify, minWidth, zeroPad);
    };
    const formatString = (value, leftJustify, minWidth, precision, zeroPad, customPadChar) => {
        if (precision !== null && precision !== undefined) {
            value = value.slice(0, precision);
        }
        return justify(value, '', leftJustify, minWidth, zeroPad, customPadChar);
    };
    const doFormat = (substring, valueIndex, flags, minWidthStr, _, // Explicitly type the unused parameter
    precisionStr, type) => {
        if (substring === '%%') {
            return '%';
        }
        let leftJustify = false;
        let positivePrefix = '';
        let zeroPad = false;
        let prefixBaseX = false;
        let customPadChar = ' ';
        for (let j = 0; flags && j < flags.length; j++) {
            switch (flags.charAt(j)) {
                case ' ': {
                    positivePrefix = ' ';
                    break;
                }
                case '0': {
                    zeroPad = true;
                    break;
                }
                case '#': {
                    prefixBaseX = true;
                    break;
                }
                case "'": {
                    customPadChar = flags.charAt(j + 1);
                    break;
                }
                case '+': {
                    positivePrefix = '+';
                    break;
                }
                case '-': {
                    leftJustify = true;
                    break;
                }
            }
        }
        let minWidth = minWidthStr ? +minWidthStr : 0;
        if (minWidthStr === '*') {
            minWidth = +args[i++];
        }
        else if (minWidthStr?.charAt(0) === '*') {
            minWidth = +args[Number.parseInt(minWidthStr.slice(1, -1)) - 1];
        }
        if (minWidth < 0) {
            minWidth = -minWidth;
            leftJustify = true;
        }
        if (!isFinite(minWidth)) {
            throw new TypeError('sprintf: (minimum-)width must be finite');
        }
        let precision = precisionStr ? +precisionStr : undefined;
        if (precisionStr === '*') {
            precision = +args[i++];
        }
        else if (precisionStr?.charAt(0) === '*') {
            precision = +args[Number.parseInt(precisionStr.slice(1, -1)) - 1];
        }
        if (precision === undefined) {
            precision = 'fFeE'.includes(type) ? 6 : type === 'd' ? 0 : undefined;
        }
        const value = valueIndex ? args[Number.parseInt(valueIndex.slice(0, -1)) - 1] : args[i++];
        switch (type) {
            case 'b': {
                return formatBaseX(value, 2, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
            }
            case 'c': {
                return formatString(String.fromCharCode(+value), leftJustify, minWidth, precision, zeroPad);
            }
            case 'd':
            case 'i': {
                const number = +value | 0;
                const prefix = number < 0 ? '-' : positivePrefix;
                const val = prefix + pad(String(Math.abs(number)), precision || 0, '0', false);
                return justify(val, prefix, leftJustify, minWidth, zeroPad);
            }
            case 'e':
            case 'E':
            case 'f':
            case 'F':
            case 'g':
            case 'G': {
                {
                    const number = +value;
                    const prefix = number < 0 ? '-' : positivePrefix;
                    const method = ['toExponential', 'toFixed', 'toPrecision']['efg'.indexOf(type.toLowerCase())];
                    const textTransform = ['toString', 'toUpperCase']['eEfFgG'.indexOf(type) % 2];
                    const val = prefix + Math.abs(number)[method](precision);
                    return justify(val, prefix, leftJustify, minWidth, zeroPad)[textTransform]();
                }
            }
            case 'o': {
                {
                    return formatBaseX(value, 8, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
                }
            }
            case 's': {
                {
                    return formatString(String(value), leftJustify, minWidth, precision, zeroPad, customPadChar);
                }
            }
            case 'u': {
                {
                    return formatBaseX(value, 10, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
                }
            }
            case 'x': {
                {
                    return formatBaseX(value, 16, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
                }
            }
            case 'X': {
                return formatBaseX(value, 16, prefixBaseX, leftJustify, minWidth, precision, zeroPad).toUpperCase();
            }
            default: {
                return substring;
            }
        }
    };
    return format.replaceAll(regex, doFormat);
}
