"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.TARGET_PATH_PLATFORMS = exports.PATH_VALUE_KINDS = void 0;
exports.createCanonicalPathPolicy = createCanonicalPathPolicy;
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"];
exports.TARGET_PATH_PLATFORMS = ["posix", "windows", "wsl"];
/**
 * Creates an injectable target-platform policy. The target platform controls
 * filesystem comparison semantics, never canonical identity: stored paths are
 * repository-relative POSIX on every supported platform.
 */
function createCanonicalPathPolicy(options = {}) {
    const targetPlatform = options.targetPlatform ?? defaultTargetPlatform();
    if (!exports.TARGET_PATH_PLATFORMS.includes(targetPlatform)) {
        throw new RangeError(`Unsupported target path platform: ${String(targetPlatform)}`);
    }
    return {
        protocolVersion: 1,
        targetPlatform,
        caseSensitive: options.caseSensitive ?? defaultCaseSensitivity(targetPlatform),
        acceptedSeparators: "posix-and-backslash",
        canonicalIdentity: "repository-relative-posix"
    };
}
function parseRepositoryRelativePath(input, _policy = createCanonicalPathPolicy()) {
    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;
}
function defaultTargetPlatform() {
    return process.platform === "win32" ? "windows" : "posix";
}
function defaultCaseSensitivity(targetPlatform) {
    if (targetPlatform === "windows")
        return false;
    return targetPlatform === "posix"
        ? process.platform !== "darwin"
        : true;
}
