import { logger } from "../../../logger/index.js";
import { readLocalFile } from "../../../util/fs/index.js";
import { MavenDatasource } from "../../datasource/maven/index.js";
import { isXmlElement } from "../nuget/util.js";
import { applyProps, findAttrValuePosition, parsePropertiesFile, resolveChainedProps } from "./properties.js";
import upath from "upath";
import { XmlDocument } from "xmldoc";
//#region lib/modules/manager/ant/extract.ts
const scopeNames = new Set([
	"compile",
	"runtime",
	"test",
	"provided",
	"system"
]);
function getDependencyType(scope) {
	if (scope && scopeNames.has(scope)) return scope;
	return "compile";
}
function collectDependency(node, packageFile, content) {
	const { groupId, artifactId, version, scope } = node.attr;
	if (!version || !groupId || !artifactId) return null;
	const dep = {
		datasource: MavenDatasource.id,
		depName: `${groupId}:${artifactId}`,
		currentValue: version,
		depType: getDependencyType(scope),
		registryUrls: []
	};
	dep.fileReplacePosition = findAttrValuePosition(content, node, "version");
	return {
		dep,
		depPackageFile: packageFile
	};
}
function walkNode(node, rawDeps, packageFile, content) {
	for (const child of node.children) {
		if (!isXmlElement(child)) continue;
		if (child.name === "dependency") {
			const rawDep = collectDependency(child, packageFile, content);
			if (rawDep) rawDeps.push(rawDep);
		} else walkNode(child, rawDeps, packageFile, content);
	}
}
function extractPackageFile(content, packageFile) {
	let doc;
	try {
		doc = new XmlDocument(content);
	} catch {
		logger.debug(`ant manager: could not parse XML ${packageFile}`);
		return null;
	}
	const rawDeps = [];
	walkNode(doc, rawDeps, packageFile, content);
	const deps = rawDeps.map((rd) => rd.dep);
	if (deps.length === 0) return null;
	return { deps };
}
/**
* Walk an XML node tree in document order, processing properties,
* property file references, and dependencies as they appear.
*/
async function walkNodeInOrder(node, packageFile, content, visitedFiles, allProps, allRawDeps) {
	const baseDir = upath.dirname(packageFile);
	for (const child of node.children) {
		if (!isXmlElement(child)) continue;
		if (child.name === "property") {
			const name = child.attr.name;
			const value = child.attr.value;
			if (name && value && !(name in allProps)) allProps[name] = {
				val: value,
				fileReplacePosition: findAttrValuePosition(content, child, "value"),
				packageFile
			};
			const file = child.attr.file;
			if (file) {
				const propFilePath = file.startsWith("/") ? file : upath.join(baseDir, file);
				if (!visitedFiles.has(propFilePath)) {
					visitedFiles.add(propFilePath);
					const propContent = await readLocalFile(propFilePath, "utf8");
					if (propContent) parsePropertiesFile(propContent, propFilePath, allProps);
					else logger.debug(`ant manager: could not read properties file ${propFilePath}`);
				}
			}
		} else if (child.name === "import" && child.attr.file) await walkXmlFile(upath.normalize(upath.join(baseDir, child.attr.file)), visitedFiles, allProps, allRawDeps);
		else if (child.name === "dependency") {
			const rawDep = collectDependency(child, packageFile, content);
			if (rawDep) allRawDeps.push(rawDep);
		} else await walkNodeInOrder(child, packageFile, content, visitedFiles, allProps, allRawDeps);
	}
}
async function walkXmlFile(packageFile, visitedFiles, allProps, allRawDeps) {
	if (visitedFiles.has(packageFile)) return;
	visitedFiles.add(packageFile);
	const content = await readLocalFile(packageFile, "utf8");
	if (!content) {
		logger.debug(`ant manager: could not read ${packageFile}`);
		return;
	}
	let doc;
	try {
		doc = new XmlDocument(content);
	} catch {
		logger.debug(`ant manager: could not parse XML ${packageFile}`);
		return;
	}
	await walkNodeInOrder(doc, packageFile, content, visitedFiles, allProps, allRawDeps);
}
async function extractAllPackageFiles(_config, packageFiles) {
	const results = [];
	const seen = /* @__PURE__ */ new Set();
	for (const packageFile of packageFiles) {
		if (seen.has(packageFile)) continue;
		seen.add(packageFile);
		const visitedFiles = /* @__PURE__ */ new Set();
		const allProps = {};
		const allRawDeps = [];
		await walkXmlFile(packageFile, visitedFiles, allProps, allRawDeps);
		resolveChainedProps(allProps);
		const resolvedDeps = allRawDeps.map((rawDep) => applyProps(rawDep.dep, rawDep.depPackageFile, allProps));
		if (resolvedDeps.length === 0) continue;
		const fileMap = /* @__PURE__ */ new Map();
		for (let i = 0; i < resolvedDeps.length; i++) {
			const dep = resolvedDeps[i];
			const targetFile = dep.propSource ?? allRawDeps[i].depPackageFile;
			if (!fileMap.has(targetFile)) fileMap.set(targetFile, []);
			fileMap.get(targetFile).push(dep);
		}
		for (const [pkgFile, deps] of fileMap) {
			for (const dep of deps) delete dep.propSource;
			results.push({
				packageFile: pkgFile,
				deps
			});
		}
	}
	return results.length > 0 ? results : null;
}
//#endregion
export { extractAllPackageFiles, extractPackageFile };

//# sourceMappingURL=extract.js.map