import { isAstNode as e, isMultiReference as t, isReference as n } from "../syntax-tree.js";
import { getDocument as r } from "../utils/ast-utils.js";
import { findNodesForProperty as i } from "../utils/grammar-utils.js";
import { URI as a } from "../../../vscode-uri/lib/esm/index.js";
//#region ../../node_modules/langium/lib/serializer/json-serializer.js
function o(e) {
	return typeof e.$comment == "string";
}
function s(e) {
	return typeof e == "object" && !!e && ("$ref" in e || "$error" in e);
}
var c = class {
	constructor(e) {
		this.ignoreProperties = new Set([
			"$container",
			"$containerProperty",
			"$containerIndex",
			"$document",
			"$cstNode"
		]), this.langiumDocuments = e.shared.workspace.LangiumDocuments, this.astNodeLocator = e.workspace.AstNodeLocator, this.nameProvider = e.references.NameProvider, this.commentProvider = e.documentation.CommentProvider;
	}
	serialize(e, t) {
		let n = t ?? {}, i = t?.replacer, a = (e, t) => this.replacer(e, t, n), o = i ? (e, t) => i(e, t, a) : a;
		try {
			return this.currentDocument = r(e), JSON.stringify(e, o, t?.space);
		} finally {
			this.currentDocument = void 0;
		}
	}
	deserialize(e, t) {
		let n = t ?? {}, r = JSON.parse(e);
		return this.linkNode(r, r, n), r;
	}
	replacer(i, a, { refText: o, sourceText: s, textRegions: c, comments: l, uriConverter: u }) {
		if (!this.ignoreProperties.has(i)) if (n(a)) {
			let e = a.ref, t = o ? a.$refText : void 0;
			if (e) {
				let n = r(e), i = "";
				this.currentDocument && this.currentDocument !== n && (i = u ? u(n.uri, e) : n.uri.toString());
				let a = this.astNodeLocator.getAstNodePath(e);
				return {
					$ref: `${i}#${a}`,
					$refText: t
				};
			} else return {
				$error: a.error?.message ?? "Could not resolve reference",
				$refText: t
			};
		} else if (t(a)) {
			let e = o ? a.$refText : void 0, t = [];
			for (let e of a.items) {
				let n = e.ref, i = r(e.ref), a = "";
				this.currentDocument && this.currentDocument !== i && (a = u ? u(i.uri, n) : i.uri.toString());
				let o = this.astNodeLocator.getAstNodePath(n);
				t.push(`${a}#${o}`);
			}
			return {
				$refs: t,
				$refText: e
			};
		} else if (e(a)) {
			let e;
			if (c && (e = this.addAstNodeRegionWithAssignmentsTo({ ...a }), (!i || a.$document) && e?.$textRegion && (e.$textRegion.documentURI = this.currentDocument?.uri.toString())), s && !i && (e ??= { ...a }, e.$sourceText = a.$cstNode?.text), l) {
				e ??= { ...a };
				let t = this.commentProvider.getComment(a);
				t && (e.$comment = t.replace(/\r/g, ""));
			}
			return e ?? a;
		} else return a;
	}
	addAstNodeRegionWithAssignmentsTo(e) {
		let t = (e) => ({
			offset: e.offset,
			end: e.end,
			length: e.length,
			range: e.range
		});
		if (e.$cstNode) {
			let n = e.$textRegion = t(e.$cstNode), r = n.assignments = {};
			return Object.keys(e).filter((e) => !e.startsWith("$")).forEach((n) => {
				let a = i(e.$cstNode, n).map(t);
				a.length !== 0 && (r[n] = a);
			}), e;
		}
	}
	linkNode(t, n, r, i, a, o) {
		for (let [i, a] of Object.entries(t)) if (Array.isArray(a)) for (let o = 0; o < a.length; o++) {
			let c = a[o];
			s(c) ? a[o] = this.reviveReference(t, i, n, c, r) : e(c) && this.linkNode(c, n, r, t, i, o);
		}
		else s(a) ? t[i] = this.reviveReference(t, i, n, a, r) : e(a) && this.linkNode(a, n, r, t, i);
		let c = t;
		c.$container = i, c.$containerProperty = a, c.$containerIndex = o;
	}
	reviveReference(t, n, r, i, a) {
		let o = i.$refText, s = i.$error, c;
		if (i.$ref) {
			let t = this.getRefNode(r, i.$ref, a.uriConverter);
			if (e(t)) return o ||= this.nameProvider.getName(t), {
				$refText: o ?? "",
				ref: t
			};
			s = t;
		} else if (i.$refs) {
			let t = [];
			for (let n of i.$refs) {
				let i = this.getRefNode(r, n, a.uriConverter);
				e(i) && t.push({ ref: i });
			}
			if (t.length === 0) c = {
				$refText: o ?? "",
				items: t
			}, s ??= "Could not resolve multi-reference";
			else return {
				$refText: o ?? "",
				items: t
			};
		}
		if (s) return c ??= {
			$refText: o ?? "",
			ref: void 0
		}, c.error = {
			info: {
				container: t,
				property: n,
				reference: c
			},
			message: s
		}, c;
	}
	getRefNode(e, t, n) {
		try {
			let r = t.indexOf("#");
			if (r === 0) return this.astNodeLocator.getAstNode(e, t.substring(1)) || "Could not resolve path: " + t;
			if (r < 0) {
				let e = n ? n(t) : a.parse(t), r = this.langiumDocuments.getDocument(e);
				return r ? r.parseResult.value : "Could not find document for URI: " + t;
			}
			let i = n ? n(t.substring(0, r)) : a.parse(t.substring(0, r)), o = this.langiumDocuments.getDocument(i);
			return o ? r === t.length - 1 ? o.parseResult.value : this.astNodeLocator.getAstNode(o.parseResult.value, t.substring(r + 1)) || "Could not resolve URI: " + t : "Could not find document for URI: " + t;
		} catch (e) {
			return String(e);
		}
	}
};
//#endregion
export { c as DefaultJsonSerializer, o as isAstNodeWithComment };
