import { isAstNode as e, isCompositeCstNode as t, isLeafCstNode as n, isReference as r, isRootCstNode as i } from "../syntax-tree.js";
import { streamAst as a } from "../utils/ast-utils.js";
import { isAbstractElement as o } from "../languages/generated/ast.js";
import { streamCst as s } from "../utils/cst-utils.js";
import { CompositeCstNodeImpl as c, LeafCstNodeImpl as l, RootCstNodeImpl as u } from "../parser/cst-node-builder.js";
import { BiMap as d } from "../utils/collections.js";
//#region ../../node_modules/langium/lib/serializer/hydrator.js
var f = class {
	constructor(e) {
		this.grammarElementIdMap = new d(), this.tokenTypeIdMap = new d(), this.grammar = e.Grammar, this.lexer = e.parser.Lexer, this.linker = e.references.Linker;
	}
	dehydrate(e) {
		return {
			lexerErrors: e.lexerErrors,
			lexerReport: e.lexerReport ? this.dehydrateLexerReport(e.lexerReport) : void 0,
			parserErrors: e.parserErrors.map((e) => ({
				...e,
				message: e.message
			})),
			value: this.dehydrateAstNode(e.value, this.createDehyrationContext(e.value))
		};
	}
	dehydrateLexerReport(e) {
		return e;
	}
	createDehyrationContext(e) {
		let t = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map();
		for (let n of a(e)) t.set(n, {});
		if (e.$cstNode) for (let t of s(e.$cstNode)) n.set(t, {});
		return {
			astNodes: t,
			cstNodes: n
		};
	}
	dehydrateAstNode(t, n) {
		let i = n.astNodes.get(t);
		i.$type = t.$type, i.$containerIndex = t.$containerIndex, i.$containerProperty = t.$containerProperty, t.$cstNode !== void 0 && (i.$cstNode = this.dehydrateCstNode(t.$cstNode, n));
		for (let [a, o] of Object.entries(t)) if (!a.startsWith("$")) if (Array.isArray(o)) {
			let t = [];
			i[a] = t;
			for (let i of o) e(i) ? t.push(this.dehydrateAstNode(i, n)) : r(i) ? t.push(this.dehydrateReference(i, n)) : t.push(i);
		} else e(o) ? i[a] = this.dehydrateAstNode(o, n) : r(o) ? i[a] = this.dehydrateReference(o, n) : o !== void 0 && (i[a] = o);
		return i;
	}
	dehydrateReference(e, t) {
		let n = {};
		return n.$refText = e.$refText, e.$refNode && (n.$refNode = t.cstNodes.get(e.$refNode)), n;
	}
	dehydrateCstNode(e, r) {
		let a = r.cstNodes.get(e);
		return i(e) ? a.fullText = e.fullText : a.grammarSource = this.getGrammarElementId(e.grammarSource), a.hidden = e.hidden, a.astNode = r.astNodes.get(e.astNode), t(e) ? a.content = e.content.map((e) => this.dehydrateCstNode(e, r)) : n(e) && (a.tokenType = e.tokenType.name, a.offset = e.offset, a.length = e.length, a.startLine = e.range.start.line, a.startColumn = e.range.start.character, a.endLine = e.range.end.line, a.endColumn = e.range.end.character), a;
	}
	hydrate(e) {
		let t = e.value, n = this.createHydrationContext(t);
		return "$cstNode" in t && this.hydrateCstNode(t.$cstNode, n), {
			lexerErrors: e.lexerErrors,
			lexerReport: e.lexerReport,
			parserErrors: e.parserErrors,
			value: this.hydrateAstNode(t, n)
		};
	}
	createHydrationContext(e) {
		let t = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map();
		for (let n of a(e)) t.set(n, {});
		let r;
		if (e.$cstNode) for (let t of s(e.$cstNode)) {
			let e;
			"fullText" in t ? (e = new u(t.fullText), r = e) : "content" in t ? e = new c() : "tokenType" in t && (e = this.hydrateCstLeafNode(t)), e && (n.set(t, e), e.root = r);
		}
		return {
			astNodes: t,
			cstNodes: n
		};
	}
	hydrateAstNode(t, n) {
		let i = n.astNodes.get(t);
		i.$type = t.$type, i.$containerIndex = t.$containerIndex, i.$containerProperty = t.$containerProperty, t.$cstNode && (i.$cstNode = n.cstNodes.get(t.$cstNode));
		for (let [a, o] of Object.entries(t)) if (!a.startsWith("$")) if (Array.isArray(o)) {
			let t = [];
			i[a] = t;
			for (let s of o) e(s) ? t.push(this.setParent(this.hydrateAstNode(s, n), i)) : r(s) ? t.push(this.hydrateReference(s, i, a, n)) : t.push(s);
		} else e(o) ? i[a] = this.setParent(this.hydrateAstNode(o, n), i) : r(o) ? i[a] = this.hydrateReference(o, i, a, n) : o !== void 0 && (i[a] = o);
		return i;
	}
	setParent(e, t) {
		return e.$container = t, e;
	}
	hydrateReference(e, t, n, r) {
		return this.linker.buildReference(t, n, r.cstNodes.get(e.$refNode), e.$refText);
	}
	hydrateCstNode(e, n, r = 0) {
		let i = n.cstNodes.get(e);
		if (typeof e.grammarSource == "number" && (i.grammarSource = this.getGrammarElement(e.grammarSource)), i.astNode = n.astNodes.get(e.astNode), t(i)) for (let t of e.content) {
			let e = this.hydrateCstNode(t, n, r++);
			i.content.push(e);
		}
		return i;
	}
	hydrateCstLeafNode(e) {
		let t = this.getTokenType(e.tokenType), n = e.offset, r = e.length, i = e.startLine, a = e.startColumn, o = e.endLine, s = e.endColumn, c = e.hidden;
		return new l(n, r, {
			start: {
				line: i,
				character: a
			},
			end: {
				line: o,
				character: s
			}
		}, t, c);
	}
	getTokenType(e) {
		return this.lexer.definition[e];
	}
	getGrammarElementId(e) {
		if (e) return this.grammarElementIdMap.size === 0 && this.createGrammarElementIdMap(), this.grammarElementIdMap.get(e);
	}
	getGrammarElement(e) {
		return this.grammarElementIdMap.size === 0 && this.createGrammarElementIdMap(), this.grammarElementIdMap.getKey(e);
	}
	createGrammarElementIdMap() {
		let e = 0;
		for (let t of a(this.grammar)) o(t) && this.grammarElementIdMap.set(t, e++);
	}
};
//#endregion
export { f as DefaultHydrator };
