"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getRouteRegex = exports.getParametrizedRoute = void 0;
// this isn't importing the escape-string-regex module
// to reduce bytes
function escapeRegex(str) {
    return str.replace(/[|\\{}()[\]^$+*?.-]/g, '\\$&');
}
function parseParameter(param) {
    const optional = param.startsWith('[') && param.endsWith(']');
    if (optional) {
        param = param.slice(1, -1);
    }
    const repeat = param.startsWith('...');
    if (repeat) {
        param = param.slice(3);
    }
    return { key: param, repeat, optional };
}
function getParametrizedRoute(route) {
    const segments = (route.replace(/\/$/, '') || '/').slice(1).split('/');
    const groups = {};
    let groupIndex = 1;
    const parameterizedRoute = segments
        .map(segment => {
        if (segment.startsWith('[') && segment.endsWith(']')) {
            const { key, optional, repeat } = parseParameter(segment.slice(1, -1));
            groups[key] = { pos: groupIndex++, repeat, optional };
            return repeat ? (optional ? '(?:/(.+?))?' : '/(.+?)') : '/([^/]+?)';
        }
        else {
            return `/${escapeRegex(segment)}`;
        }
    })
        .join('');
    // dead code eliminate for browser since it's only needed
    // while generating routes-manifest
    let routeKeyCharCode = 97;
    let routeKeyCharLength = 1;
    // builds a minimal routeKey using only a-z and minimal number of characters
    const getSafeRouteKey = () => {
        let routeKey = '';
        for (let i = 0; i < routeKeyCharLength; i++) {
            routeKey += String.fromCharCode(routeKeyCharCode);
            routeKeyCharCode++;
            if (routeKeyCharCode > 122) {
                routeKeyCharLength++;
                routeKeyCharCode = 97;
            }
        }
        return routeKey;
    };
    const routeKeys = {};
    const namedParameterizedRoute = segments
        .map(segment => {
        if (segment.startsWith('[') && segment.endsWith(']')) {
            const { key, optional, repeat } = parseParameter(segment.slice(1, -1));
            // replace any non-word characters since they can break
            // the named regex
            let cleanedKey = key.replace(/\W/g, '');
            let invalidKey = false;
            // check if the key is still invalid and fallback to using a known
            // safe key
            if (cleanedKey.length === 0 || cleanedKey.length > 30) {
                invalidKey = true;
            }
            if (!isNaN(parseInt(cleanedKey.substr(0, 1)))) {
                invalidKey = true;
            }
            if (invalidKey) {
                cleanedKey = getSafeRouteKey();
            }
            routeKeys[cleanedKey] = key;
            return repeat
                ? optional
                    ? `(?:/(?<${cleanedKey}>.+?))?`
                    : `/(?<${cleanedKey}>.+?)`
                : `/(?<${cleanedKey}>[^/]+?)`;
        }
        else {
            return `/${escapeRegex(segment)}`;
        }
    })
        .join('');
    return {
        parameterizedRoute,
        namedParameterizedRoute,
        groups,
        routeKeys,
    };
}
exports.getParametrizedRoute = getParametrizedRoute;
function getRouteRegex(normalizedRoute) {
    const result = getParametrizedRoute(normalizedRoute);
    if ('routeKeys' in result) {
        return {
            re: new RegExp(`^${result.parameterizedRoute}(?:/)?$`),
            groups: result.groups,
            routeKeys: result.routeKeys,
            namedRegex: `^${result.namedParameterizedRoute}(?:/)?$`,
        };
    }
    return {
        re: new RegExp(`^${result.parameterizedRoute}(?:/)?$`),
        groups: result.groups,
    };
}
exports.getRouteRegex = getRouteRegex;
