import { MaskedValueError, PatternError } from '../errors.js';
export function parseNumberAsSkeleton(tokens, onError) {
    const res = {};
    let hasGroups = false;
    let hasExponent = false;
    let intOptional = 0;
    let intDigits = '';
    let decimalPos = -1;
    let fracDigits = '';
    let fracOptional = 0;
    for (let pos = 0; pos < tokens.length; ++pos) {
        const token = tokens[pos];
        switch (token.char) {
            case '#': {
                if (decimalPos === -1) {
                    if (intDigits) {
                        const msg = 'Pattern has # after integer digits';
                        onError(new PatternError('#', msg));
                    }
                    intOptional += token.width;
                }
                else {
                    fracOptional += token.width;
                }
                break;
            }
            case '0': {
                if (decimalPos === -1) {
                    intDigits += token.digits;
                }
                else {
                    if (fracOptional) {
                        const msg = 'Pattern has digits after # in fraction';
                        onError(new PatternError('0', msg));
                    }
                    fracDigits += token.digits;
                }
                break;
            }
            case '@': {
                if (res.precision)
                    onError(new MaskedValueError('precision', res.precision));
                res.precision = {
                    style: 'precision-fraction',
                    minSignificant: token.min,
                    maxSignificant: token.width
                };
                break;
            }
            case ',':
                hasGroups = true;
                break;
            case '.':
                if (decimalPos === 1) {
                    const msg = 'Pattern has more than one decimal separator';
                    onError(new PatternError('.', msg));
                }
                decimalPos = pos;
                break;
            case 'E': {
                if (hasExponent)
                    onError(new MaskedValueError('exponent', res.notation));
                if (hasGroups) {
                    const msg = 'Exponential patterns may not contain grouping separators';
                    onError(new PatternError('E', msg));
                }
                res.notation = { style: 'scientific' };
                if (token.expDigits > 1)
                    res.notation.expDigits = token.expDigits;
                if (token.plus)
                    res.notation.expSign = 'sign-always';
                hasExponent = true;
            }
        }
    }
    // imprecise mapping due to paradigm differences
    if (hasGroups)
        res.group = 'group-auto';
    else if (intOptional + intDigits.length > 3)
        res.group = 'group-off';
    const increment = Number(`${intDigits || '0'}.${fracDigits}`);
    if (increment)
        res.precision = { style: 'precision-increment', increment };
    if (!hasExponent) {
        if (intDigits.length > 1)
            res.integerWidth = { min: intDigits.length };
        if (!res.precision && (fracDigits.length || fracOptional)) {
            res.precision = {
                style: 'precision-fraction',
                minFraction: fracDigits.length,
                maxFraction: fracDigits.length + fracOptional
            };
        }
    }
    else {
        if (!res.precision || increment) {
            res.integerWidth = intOptional
                ? { min: 1, max: intOptional + intDigits.length }
                : { min: Math.max(1, intDigits.length) };
        }
        if (res.precision) {
            if (!increment)
                res.integerWidth = { min: 1, max: 1 };
        }
        else {
            const dc = intDigits.length + fracDigits.length;
            if (decimalPos === -1) {
                if (dc > 0)
                    res.precision = { style: 'precision-fraction', maxSignificant: dc };
            }
            else {
                res.precision = {
                    style: 'precision-fraction',
                    maxSignificant: Math.max(1, dc) + fracOptional
                };
                if (dc > 1)
                    res.precision.minSignificant = dc;
            }
        }
    }
    return res;
}
