"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.PATH_VALUE_KINDS = void 0;
exports.parseRepositoryRelativePath = parseRepositoryRelativePath;
exports.resolveRepositoryRelativePath = resolveRepositoryRelativePath;
exports.resolveRuntimeAbsolutePath = resolveRuntimeAbsolutePath;
exports.isAbsolutePathLike = isAbsolutePathLike;
exports.pathsEqualForFilesystem = pathsEqualForFilesystem;
exports.pathsOverlap = pathsOverlap;
const node_path_1 = __importDefault(require("node:path"));
exports.PATH_VALUE_KINDS = ["repository-relative", "runtime-absolute"];
function parseRepositoryRelativePath(input) {
    if (input === "") {
        throw new RangeError("Repository-relative paths must not be empty.");
    }
    const normalizedSeparators = input.replace(/\\/g, "/");
    if (isAbsolutePathLike(normalizedSeparators)) {
        throw new RangeError(`Absolute paths are not allowed: ${input}`);
    }
    const rawSegments = normalizedSeparators.split("/");
    if (rawSegments.some((segment) => segment === "..")) {
        throw new RangeError(`Repository-relative paths must not contain '..' segments: ${input}`);
    }
    const normalizedPath = stripTrailingSeparator(node_path_1.default.posix.normalize(normalizedSeparators));
    if (normalizedPath === "." || normalizedPath === "") {
        throw new RangeError(`Repository-relative paths must resolve to a concrete path: ${input}`);
    }
    return {
        kind: "repository-relative",
        originalInput: input,
        normalizedPath,
        segments: normalizedPath.split("/")
    };
}
function resolveRepositoryRelativePath(repositoryRoot, relativePath) {
    return resolveRuntimeAbsolutePath(repositoryRoot, relativePath).absolutePath;
}
function resolveRuntimeAbsolutePath(repositoryRoot, relativePath) {
    const repositoryRelativePath = typeof relativePath === "string" ? parseRepositoryRelativePath(relativePath) : relativePath;
    return {
        kind: "runtime-absolute",
        repositoryRoot,
        repositoryRelativePath,
        absolutePath: node_path_1.default.resolve(repositoryRoot, repositoryRelativePath.normalizedPath)
    };
}
function isAbsolutePathLike(value) {
    return node_path_1.default.isAbsolute(value) || node_path_1.default.win32.isAbsolute(value);
}
function pathsEqualForFilesystem(a, b) {
    const pathApi = selectPathComparisonApi(a, b);
    return normalizeForFilesystemComparison(a, pathApi) ===
        normalizeForFilesystemComparison(b, pathApi);
}
function pathsOverlap(a, b) {
    return isWithinOrEqual(a, b) || isWithinOrEqual(b, a);
}
function stripTrailingSeparator(value) {
    return value.replace(/\/+$/, "");
}
function isWithinOrEqual(candidatePath, parentPath) {
    if (pathsEqualForFilesystem(candidatePath, parentPath)) {
        return true;
    }
    const pathApi = selectPathComparisonApi(candidatePath, parentPath);
    const normalizedCandidate = normalizeForFilesystemComparison(candidatePath, pathApi);
    const normalizedParent = normalizeForFilesystemComparison(parentPath, pathApi);
    const relativePath = pathApi.relative(normalizedParent, normalizedCandidate);
    return relativePath === "" ||
        (!relativePath.startsWith("..") && !pathApi.isAbsolute(relativePath));
}
function selectPathComparisonApi(a, b) {
    if (isWindowsStyleAbsolutePath(a) || isWindowsStyleAbsolutePath(b)) {
        return node_path_1.default.win32;
    }
    return node_path_1.default;
}
function isWindowsStyleAbsolutePath(value) {
    return /^[A-Za-z]:[\\/]/.test(value) || value.startsWith("\\\\");
}
function normalizeForFilesystemComparison(value, pathApi) {
    const normalizedValue = stripTrailingSeparator(pathApi.normalize(value));
    if (pathApi === node_path_1.default.win32) {
        return normalizedValue.toLowerCase();
    }
    return normalizedValue;
}
