import { isMultiReference, isReference } from "../syntax-tree.js";
import { stream } from "../utils/stream.js";
import { getDocument, getReferenceNodes, streamAst, streamReferences } from "../utils/ast-utils.js";
import { isCrossReference } from "../languages/generated/ast.js";
import { isChildNode, toDocumentSegment } from "../utils/cst-utils.js";
import { findAssignment } from "../utils/grammar-utils.js";
import { UriUtils } from "../utils/uri-utils.js";
var DefaultReferences = class {
	constructor(e) {
		this.nameProvider = e.references.NameProvider, this.index = e.shared.workspace.IndexManager, this.nodeLocator = e.workspace.AstNodeLocator, this.documents = e.shared.workspace.LangiumDocuments, this.hasMultiReference = streamAst(e.Grammar).some((e) => isCrossReference(e) && e.isMulti);
	}
	findDeclarations(c) {
		if (c) {
			let l = findAssignment(c), d = c.astNode;
			if (l && d) {
				let f = d[l.feature];
				if (isReference(f) || isMultiReference(f)) return getReferenceNodes(f);
				if (Array.isArray(f)) {
					for (let l of f) if ((isReference(l) || isMultiReference(l)) && l.$refNode && l.$refNode.offset <= c.offset && l.$refNode.end >= c.end) return getReferenceNodes(l);
				}
			}
			if (d) {
				let e = this.nameProvider.getNameNode(d);
				if (e && (e === c || isChildNode(c, e))) return this.getSelfNodes(d);
			}
		}
		return [];
	}
	getSelfNodes(s) {
		if (this.hasMultiReference) {
			let c = this.index.findAllReferences(s, this.nodeLocator.getAstNodePath(s)), l = this.getNodeFromReferenceDescription(c.head());
			if (l) {
				for (let c of streamReferences(l)) if (isMultiReference(c.reference) && c.reference.items.some((e) => e.ref === s)) return c.reference.items.map((e) => e.ref);
			}
			return [s];
		} else return [s];
	}
	getNodeFromReferenceDescription(e) {
		if (!e) return;
		let s = this.documents.getDocument(e.sourceUri);
		if (s) return this.nodeLocator.getAstNode(s.parseResult.value, e.sourcePath);
	}
	findDeclarationNodes(e) {
		let s = this.findDeclarations(e), c = [];
		for (let e of s) {
			let s = this.nameProvider.getNameNode(e) ?? e.$cstNode;
			s && c.push(s);
		}
		return c;
	}
	findReferences(e, s) {
		let l = [];
		s.includeDeclaration && l.push(...this.getSelfReferences(e));
		let u = this.index.findAllReferences(e, this.nodeLocator.getAstNodePath(e));
		return s.documentUri && (u = u.filter((e) => UriUtils.equals(e.sourceUri, s.documentUri))), l.push(...u), stream(l);
	}
	getSelfReferences(e) {
		let s = this.getSelfNodes(e), c = [];
		for (let e of s) {
			let s = this.nameProvider.getNameNode(e);
			if (s) {
				let u = getDocument(e), d = this.nodeLocator.getAstNodePath(e);
				c.push({
					sourceUri: u.uri,
					sourcePath: d,
					targetUri: u.uri,
					targetPath: d,
					segment: toDocumentSegment(s),
					local: !0
				});
			}
		}
		return c;
	}
};
export { DefaultReferences };
