import { escapeRegExp, regEx } from "../../../../util/regex.js";
import { massage, parse } from "../../../../util/toml.js";
import { hasKey } from "../../../../util/object.js";
import { isPlainObject, isString } from "@sindresorhus/is";
import merge from "deepmerge";
//#region lib/modules/manager/gradle/extract/catalog.ts
function findVersionIndex(content, depName, version) {
	const match = regEx(`(?:id\\s*=\\s*)?['"]?${escapeRegExp(depName)}["']?(?:(?:\\s*=\\s*)|:|,\\s*)(?:.*version(?:\\.ref)?(?:\\s*\\=\\s*))?["']?${escapeRegExp(version)}['"]?`).exec(content);
	if (match) return match.index + content.slice(match.index).indexOf(version);
	/* istanbul ignore next */
	return findIndexAfter(content, depName, version);
}
function findIndexAfter(content, sliceAfter, find) {
	const slicePoint = content.indexOf(sliceAfter) + sliceAfter.length;
	return slicePoint + content.slice(slicePoint).indexOf(find);
}
function isArtifactDescriptor(obj) {
	return hasKey("group", obj);
}
function isVersionPointer(obj) {
	return hasKey("ref", obj);
}
function normalizeAlias(alias) {
	return alias.replace(regEx(/[-_]/g), ".");
}
function findOriginalAlias(versions, alias) {
	const normalizedAlias = normalizeAlias(alias);
	for (const sectionKey of Object.keys(versions)) if (normalizeAlias(sectionKey) === normalizedAlias) return sectionKey;
	return alias;
}
function extractVersion({ version, versions, depStartIndex, depSubContent, depName, versionStartIndex, versionSubContent }) {
	if (isVersionPointer(version)) {
		const originalAlias = findOriginalAlias(versions, version.ref);
		return extractLiteralVersion({
			version: versions[originalAlias],
			depStartIndex: versionStartIndex,
			depSubContent: versionSubContent,
			sectionKey: originalAlias
		});
	} else return extractLiteralVersion({
		version,
		depStartIndex,
		depSubContent,
		sectionKey: depName
	});
}
function extractLiteralVersion({ version, depStartIndex, depSubContent, sectionKey }) {
	if (!version) return { skipReason: "unspecified-version" };
	else if (isString(version)) return {
		currentValue: version,
		fileReplacePosition: depStartIndex + findVersionIndex(depSubContent, sectionKey, version)
	};
	else if (isPlainObject(version)) {
		const versionKeys = [
			"require",
			"prefer",
			"strictly"
		];
		let found = false;
		let currentValue;
		let fileReplacePosition;
		if (version.reject || version.rejectAll) return { skipReason: "unsupported-version" };
		for (const key of versionKeys) if (key in version) {
			if (found) return { skipReason: "multiple-constraint-dep" };
			found = true;
			currentValue = version[key];
			fileReplacePosition = depStartIndex + findIndexAfter(depSubContent, sectionKey, currentValue);
		}
		if (found) return {
			currentValue,
			fileReplacePosition
		};
	}
	return { skipReason: "unspecified-version" };
}
function extractDependency({ descriptor, versions, depStartIndex, depSubContent, depName, versionStartIndex, versionSubContent }) {
	if (isString(descriptor)) {
		const [group, name, currentValue] = descriptor.split(":");
		if (!currentValue) return {
			depName,
			skipReason: "unspecified-version"
		};
		return {
			depName: `${group}:${name}`,
			currentValue,
			managerData: { fileReplacePosition: depStartIndex + findIndexAfter(depSubContent, depName, currentValue) }
		};
	}
	const { currentValue, fileReplacePosition, skipReason } = extractVersion({
		version: descriptor.version,
		versions,
		depStartIndex,
		depSubContent,
		depName,
		versionStartIndex,
		versionSubContent
	});
	if (skipReason) return {
		depName,
		skipReason
	};
	const dependency = {
		currentValue,
		managerData: { fileReplacePosition }
	};
	if (isArtifactDescriptor(descriptor)) {
		const { group, name } = descriptor;
		dependency.depName = `${group}:${name}`;
	} else {
		const [depGroupName, name] = descriptor.module.split(":");
		dependency.depName = `${depGroupName}:${name}`;
	}
	if (isVersionPointer(descriptor.version)) dependency.sharedVariableName = normalizeAlias(descriptor.version.ref);
	return dependency;
}
function parseCatalog(packageFile, content) {
	const tomlContent = parse(massage(content));
	const versions = tomlContent.versions ?? {};
	const libs = tomlContent.libraries ?? {};
	const libStartIndex = content.indexOf("libraries");
	const libSubContent = content.slice(libStartIndex);
	const versionStartIndex = content.indexOf("versions");
	const versionSubContent = content.slice(versionStartIndex);
	const extractedDeps = [];
	for (const libraryName of Object.keys(libs)) {
		const libDescriptor = libs[libraryName];
		const dependency = extractDependency({
			descriptor: libDescriptor,
			versions,
			depStartIndex: libStartIndex,
			depSubContent: libSubContent,
			depName: libraryName,
			versionStartIndex,
			versionSubContent
		});
		extractedDeps.push(dependency);
	}
	const plugins = tomlContent.plugins ?? {};
	const pluginsStartIndex = content.indexOf("[plugins]");
	const pluginsSubContent = content.slice(pluginsStartIndex);
	for (const pluginName of Object.keys(plugins)) {
		const pluginDescriptor = plugins[pluginName];
		const [depName, version] = isString(pluginDescriptor) ? pluginDescriptor.split(":") : [pluginDescriptor.id, pluginDescriptor.version];
		const { currentValue, fileReplacePosition, skipReason } = extractVersion({
			version,
			versions,
			depStartIndex: pluginsStartIndex,
			depSubContent: pluginsSubContent,
			depName,
			versionStartIndex,
			versionSubContent
		});
		const dependency = {
			depType: "plugin",
			depName,
			packageName: `${depName}:${depName}.gradle.plugin`,
			currentValue,
			commitMessageTopic: `plugin ${pluginName}`,
			managerData: { fileReplacePosition }
		};
		if (skipReason) dependency.skipReason = skipReason;
		if (isVersionPointer(version) && dependency.commitMessageTopic) {
			dependency.sharedVariableName = normalizeAlias(version.ref);
			delete dependency.commitMessageTopic;
		}
		extractedDeps.push(dependency);
	}
	return extractedDeps.map((dep) => {
		return merge(dep, { managerData: { packageFile } });
	});
}
//#endregion
export { parseCatalog };

//# sourceMappingURL=catalog.js.map