// @ts-expect-error - Importing from vendored file
import * as TreeSitter from "./vendor/web-tree-sitter.js";
/**
 * TreeSitterParser handles WASM initialization and parser instantiation
 * for the v2.9 AST-based transition.
 */
export class TreeSitterParser {
    static parser = null;
    static languages = new Map();
    static initPromise = null;
    static async init(options) {
        if (TreeSitterParser.parser &&
            (!options.grammars ||
                Object.keys(options.grammars).every((lang) => TreeSitterParser.languages.has(lang))))
            return;
        if (TreeSitterParser.initPromise) {
            return TreeSitterParser.initPromise;
        }
        TreeSitterParser.initPromise = TreeSitterParser.doInit(options);
        return TreeSitterParser.initPromise;
    }
    static async doInit(options) {
        try {
            const { Parser, Language } = TreeSitter;
            if (!TreeSitterParser.parser) {
                // Initializing core with vendored library
                if (!Parser) {
                    throw new Error("Parser class not found in vendored web-tree-sitter module.");
                }
                const initOptions = Object.create(null);
                if (options.webTreeSitterWasm instanceof Uint8Array ||
                    Buffer.isBuffer(options.webTreeSitterWasm)) {
                    initOptions.wasmBinary = options.webTreeSitterWasm;
                }
                else {
                    initOptions.locateFile = (scriptName) => {
                        if (scriptName === "web-tree-sitter.wasm") {
                            return options.webTreeSitterWasm;
                        }
                        return scriptName;
                    };
                }
                await Parser.init(initOptions);
                TreeSitterParser.parser = new Parser();
            }
            if (options.grammars) {
                for (const [name, grammar] of Object.entries(options.grammars)) {
                    if (TreeSitterParser.languages.has(name))
                        continue;
                    // Loading grammar silently
                    const grammarWasm = grammar instanceof Uint8Array
                        ? grammar
                        : typeof grammar === "string"
                            ? grammar
                            : new Uint8Array(grammar);
                    const language = await Language.load(grammarWasm);
                    TreeSitterParser.languages.set(name, language);
                }
            }
            // Default to bash if available and nothing set
            if (!TreeSitterParser.parser.language &&
                TreeSitterParser.languages.has("bash")) {
                TreeSitterParser.parser.setLanguage(TreeSitterParser.languages.get("bash"));
            }
        }
        catch (e) {
            TreeSitterParser.initPromise = null;
            const errorMsg = e instanceof Error ? e.message : String(e);
            throw new Error(`Failed to initialize TreeSitterParser: ${errorMsg}`);
        }
    }
    static async loadLanguage(name, grammarWasm) {
        if (TreeSitterParser.languages.has(name))
            return;
        const { Language } = TreeSitter;
        const wasm = grammarWasm instanceof Uint8Array
            ? grammarWasm
            : typeof grammarWasm === "string"
                ? grammarWasm
                : new Uint8Array(grammarWasm);
        const language = await Language.load(wasm);
        TreeSitterParser.languages.set(name, language);
    }
    static setLanguage(name) {
        const lang = TreeSitterParser.languages.get(name);
        if (!lang) {
            throw new Error(`Language '${name}' not loaded. Call loadLanguage() or init() first.`);
        }
        TreeSitterParser.parser.setLanguage(lang);
    }
    static parse(code, language) {
        if (!TreeSitterParser.parser) {
            throw new Error("TreeSitterParser not initialized. Call init() first.");
        }
        if (language) {
            TreeSitterParser.setLanguage(language);
        }
        return TreeSitterParser.parser.parse(code);
    }
    static getLanguage(name) {
        if (name)
            return TreeSitterParser.languages.get(name);
        return TreeSitterParser.parser?.language;
    }
    static resetForTest() {
        TreeSitterParser.parser = null;
        TreeSitterParser.languages.clear();
        TreeSitterParser.initPromise = null;
    }
}
