"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.interpolateString = interpolateString;
exports.interpolateDeep = interpolateDeep;
const TOKEN_REGEX = /\$\{([^}]+)\}/g;
function getByPath(obj, path) {
    if (!path)
        return undefined;
    const parts = path.split(".");
    let current = obj;
    for (const part of parts) {
        if (current == null || typeof current !== "object")
            return undefined;
        current = current[part];
    }
    return current;
}
function parsePathSegments(path) {
    const segments = [];
    let buffer = "";
    let i = 0;
    const pushBuffer = () => {
        if (buffer) {
            segments.push(buffer);
            buffer = "";
        }
    };
    while (i < path.length) {
        const ch = path[i];
        if (ch === ".") {
            pushBuffer();
            i += 1;
            continue;
        }
        if (ch === "[") {
            pushBuffer();
            i += 1;
            if (i >= path.length)
                break;
            let quote = "";
            if (path[i] === '"' || path[i] === "'") {
                quote = path[i];
                i += 1;
            }
            let value = "";
            while (i < path.length) {
                const c = path[i];
                if (quote) {
                    if (c === "\\" && i + 1 < path.length) {
                        value += path[i + 1];
                        i += 2;
                        continue;
                    }
                    if (c === quote) {
                        i += 1;
                        break;
                    }
                    value += c;
                    i += 1;
                    continue;
                }
                if (c === "]")
                    break;
                value += c;
                i += 1;
            }
            while (i < path.length && path[i] !== "]") {
                i += 1;
            }
            if (i < path.length && path[i] === "]") {
                i += 1;
            }
            if (value) {
                segments.push(value);
            }
            continue;
        }
        buffer += ch;
        i += 1;
    }
    pushBuffer();
    return segments;
}
function getByPathWithBrackets(obj, path) {
    if (!path)
        return undefined;
    const parts = parsePathSegments(path);
    let current = obj;
    for (const part of parts) {
        if (current == null || typeof current !== "object")
            return undefined;
        current = current[part];
    }
    return current;
}
function resolveToken(token, ctx) {
    if (token.startsWith("env:")) {
        const name = token.slice("env:".length);
        if (!name) {
            throw new Error('Invalid interpolation token: "env:"');
        }
        const value = process.env[name];
        if (value === undefined) {
            throw new Error(`Missing env var for token: "${token}"`);
        }
        return { value, raw: false };
    }
    if (token.startsWith("params.")) {
        const path = token.slice("params.".length);
        if (!path) {
            throw new Error('Invalid interpolation token: "params."');
        }
        const value = getByPath(ctx.params, path);
        if (value === undefined) {
            throw new Error(`Missing param for token: "${token}"`);
        }
        return { value, raw: false };
    }
    if (token.startsWith("data:") || token.startsWith("data.")) {
        const prefix = token.startsWith("data:") ? "data:" : "data.";
        let path = token.slice(prefix.length);
        if (!path) {
            throw new Error(`Invalid interpolation token: "${prefix}"`);
        }
        let raw = false;
        if (path.endsWith("._rec")) {
            raw = true;
            path = path.slice(0, -("._rec".length));
        }
        const value = getByPathWithBrackets(ctx.testData ?? {}, path);
        if (value === undefined) {
            throw new Error(`Missing test data for token: "${token}"`);
        }
        return { value, raw };
    }
    if (token.startsWith("res:")) {
        const path = token.slice("res:".length);
        if (!path) {
            throw new Error('Invalid interpolation token: "res:"');
        }
        const value = ctx.resources.get(path);
        if (value === undefined) {
            throw new Error(`Missing resource for token: "${token}"`);
        }
        return { value, raw: false };
    }
    throw new Error(`Unknown interpolation token: "${token}"`);
}
function interpolateString(input, ctx) {
    return input.replace(TOKEN_REGEX, (_match, token) => {
        const resolved = resolveToken(token, ctx);
        return typeof resolved.value === "string"
            ? resolved.value
            : JSON.stringify(resolved.value);
    });
}
function interpolateDeep(input, ctx) {
    if (typeof input === "string") {
        const tokenMatch = input.match(/^\$\{([^}]+)\}$/);
        if (tokenMatch) {
            const resolved = resolveToken(tokenMatch[1], ctx);
            if (resolved.raw) {
                return resolved.value;
            }
        }
        return interpolateString(input, ctx);
    }
    if (Array.isArray(input)) {
        return input.map((item) => interpolateDeep(item, ctx));
    }
    if (input && typeof input === "object") {
        const out = {};
        for (const [key, value] of Object.entries(input)) {
            out[key] = interpolateDeep(value, ctx);
        }
        return out;
    }
    return input;
}
//# sourceMappingURL=interpolation.js.map