"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isUnformattable = exports.isRoot = exports.isMultiBlock = exports.isBlock = exports.isInline = exports.parseGoTemplate = void 0;
const create_id_generator_1 = require("./create-id-generator");
const parseGoTemplate = (text, parsers, options) => {
    var _a, _b, _c, _d, _e, _f, _g, _h, _j;
    const regex = /{{(?<startdelimiter>-|<|%|\/\*)?\s*(?<statement>(?<keyword>if|range|block|with|define|end|else|prettier-ignore-start|prettier-ignore-end)?[\s\S]*?)\s*(?<endDelimiter>-|>|%|\*\/)?}}|(?<unformattableScript><(script)((?!<)[\s\S])*>((?!<\/script)[\s\S])*?{{[\s\S]*?<\/(script)>)|(?<unformattableStyle><(style)((?!<)[\s\S])*>((?!<\/style)[\s\S])*?{{[\s\S]*?<\/(style)>)/g;
    const root = {
        type: "root",
        content: text,
        aliasedContent: "",
        children: {},
        index: 0,
        contentStart: 0,
        length: text.length,
    };
    const nodeStack = [root];
    const getId = (0, create_id_generator_1.createIdGenerator)();
    for (let match of text.matchAll(regex)) {
        const current = last(nodeStack);
        const keyword = (_a = match.groups) === null || _a === void 0 ? void 0 : _a.keyword;
        const statement = (_b = match.groups) === null || _b === void 0 ? void 0 : _b.statement;
        const unformattable = (_d = (_c = match.groups) === null || _c === void 0 ? void 0 : _c.unformattableScript) !== null && _d !== void 0 ? _d : (_e = match.groups) === null || _e === void 0 ? void 0 : _e.unformattableStyle;
        const startDelimiter = ((_g = (_f = match.groups) === null || _f === void 0 ? void 0 : _f.startdelimiter) !== null && _g !== void 0 ? _g : "");
        const endDelimiter = ((_j = (_h = match.groups) === null || _h === void 0 ? void 0 : _h.endDelimiter) !== null && _j !== void 0 ? _j : "");
        if (current === undefined) {
            throw Error("Node stack empty.");
        }
        if (match.index === undefined) {
            throw Error("Regex match index undefined.");
        }
        const id = getId();
        if (unformattable) {
            current.children[id] = {
                id,
                type: "unformattable",
                index: match.index,
                length: match[0].length,
                content: unformattable,
                parent: current,
            };
            continue;
        }
        if (statement === undefined) {
            throw Error("Formattable match without statement.");
        }
        const inline = {
            index: match.index,
            length: match[0].length,
            startDelimiter,
            endDelimiter,
            parent: current,
            type: "inline",
            statement,
            id,
        };
        if (keyword === "end" || keyword === "prettier-ignore-end") {
            if (current.type !== "block") {
                throw Error("Encountered unexpected end keyword.");
            }
            current.length = match[0].length + match.index - current.index;
            current.content = text.substring(current.contentStart, match.index);
            current.aliasedContent = aliasNodeContent(current);
            current.end = inline;
            if (current.parent.type === "double-block") {
                const firstChild = current.parent.blocks[0];
                const lastChild = current.parent.blocks[current.parent.blocks.length - 1];
                current.parent.length =
                    lastChild.index + lastChild.length - firstChild.index;
            }
            nodeStack.pop();
        }
        else if (isBlock(current) && keyword === "else") {
            const nextChild = {
                type: "block",
                start: inline,
                end: null,
                children: {},
                keyword: keyword,
                index: match.index,
                parent: current.parent,
                contentStart: match.index + match[0].length,
                content: "",
                aliasedContent: "",
                length: -1,
                id: getId(),
                startDelimiter,
                endDelimiter,
            };
            if (isMultiBlock(current.parent)) {
                current.parent.blocks.push(nextChild);
            }
            else {
                const multiBlock = {
                    type: "double-block",
                    parent: current.parent,
                    index: current.index,
                    length: -1,
                    keyword,
                    id: current.id,
                    blocks: [current, nextChild],
                };
                nextChild.parent = multiBlock;
                current.parent = multiBlock;
                if ("children" in multiBlock.parent) {
                    multiBlock.parent.children[multiBlock.id] = multiBlock;
                }
                else {
                    throw Error("Could not find child in parent.");
                }
            }
            current.id = getId();
            current.length = match[0].length + match.index - current.index;
            current.content = text.substring(current.contentStart, match.index);
            current.aliasedContent = aliasNodeContent(current);
            nodeStack.pop();
            nodeStack.push(nextChild);
        }
        else if (keyword) {
            const block = {
                type: "block",
                start: inline,
                end: null,
                children: {},
                keyword: keyword,
                index: match.index,
                parent: current,
                contentStart: match.index + match[0].length,
                content: "",
                aliasedContent: "",
                length: -1,
                id: getId(),
                startDelimiter,
                endDelimiter,
            };
            current.children[block.id] = block;
            nodeStack.push(block);
        }
        else {
            current.children[inline.id] = inline;
        }
    }
    if (!isRoot(nodeStack.pop())) {
        throw Error("Missing end block.");
    }
    root.aliasedContent = aliasNodeContent(root);
    return root;
};
exports.parseGoTemplate = parseGoTemplate;
function aliasNodeContent(current) {
    let result = current.content;
    Object.entries(current.children)
        .sort(([_, node1], [__, node2]) => node2.index - node1.index)
        .forEach(([id, node]) => (result =
        result.substring(0, node.index - current.contentStart) +
            id +
            result.substring(node.index + node.length - current.contentStart)));
    return result;
}
function last(array) {
    return array[array.length - 1];
}
function isInline(node) {
    return node.type === "inline";
}
exports.isInline = isInline;
function isBlock(node) {
    return node.type === "block";
}
exports.isBlock = isBlock;
function isMultiBlock(node) {
    return node.type === "double-block";
}
exports.isMultiBlock = isMultiBlock;
function isRoot(node) {
    return node.type === "root";
}
exports.isRoot = isRoot;
function isUnformattable(node) {
    return node.type === "unformattable";
}
exports.isUnformattable = isUnformattable;
//# sourceMappingURL=data:application/json;base64,[encoded data, 18168 characters]