import { dirname, extname, fromFileUrl, SEPARATOR, toFileUrl } from "../../../../@std/path/1.0.8/mod.js";
import { instantiate, WasmWorkspace } from "./wasm/loader.generated.js";
export function findWorkspace(cwd, entryPoints, configPath) {
    const cwdFileUrl = toFileUrl(cwd);
    if (!cwdFileUrl.pathname.endsWith("/")) {
        cwdFileUrl.pathname += "/";
    }
    let entrypoints;
    let isConfigFile = false;
    if (configPath !== undefined) {
        entrypoints = [configPath];
        isConfigFile = true;
    }
    else if (Array.isArray(entryPoints)) {
        entrypoints = entryPoints.flatMap((entrypoint) => {
            let specifier;
            if (typeof entrypoint === "string") {
                specifier = entrypoint;
            }
            else {
                specifier = entrypoint.in;
            }
            const url = new URL(specifier, cwdFileUrl.href);
            if (url.protocol === "file:") {
                return [dirname(fromFileUrl(url.href))];
            }
            else {
                return [];
            }
        });
    }
    else if (typeof entryPoints === "object") {
        entrypoints = Object.values(entryPoints).flatMap((entrypoint) => {
            const url = new URL(entrypoint, cwdFileUrl.href);
            if (url.protocol === "file:") {
                return [dirname(fromFileUrl(url.href))];
            }
            else {
                return [];
            }
        });
    }
    else {
        entrypoints = [];
    }
    if (entrypoints.length === 0) {
        entrypoints = [cwd];
    }
    instantiate();
    return WasmWorkspace.discover(entrypoints, isConfigFile);
}
export function mediaTypeToLoader(mediaType) {
    switch (mediaType) {
        case "JavaScript":
        case "Mjs":
            return "js";
        case "JSX":
            return "jsx";
        case "TypeScript":
        case "Mts":
            return "ts";
        case "TSX":
            return "tsx";
        case "Json":
            return "json";
        default:
            return null;
    }
}
/**
 * Turn a URL into an {@link EsbuildResolution} by splitting the URL into a
 * namespace and path.
 *
 * For file URLs, the path returned is a file path not a URL path representing a
 * file.
 */
export function urlToEsbuildResolution(url) {
    if (url.protocol === "file:") {
        return { path: fromFileUrl(url), namespace: "file" };
    }
    const namespace = url.protocol.slice(0, -1);
    const path = url.href.slice(namespace.length + 1);
    return { path, namespace };
}
/**
 * Turn an {@link EsbuildResolution} into a URL by joining the namespace and
 * path into a URL string.
 *
 * For file URLs, the path is interpreted as a file path not as a URL path
 * representing a file.
 */
export function esbuildResolutionToURL(specifier) {
    if (specifier.namespace === "file") {
        return toFileUrl(specifier.path);
    }
    return new URL(`${specifier.namespace}:${specifier.path}`);
}
export function mapContentType(specifier, contentType) {
    if (contentType !== null) {
        const contentTypes = contentType.split(";");
        const mediaType = contentTypes[0].toLowerCase();
        switch (mediaType) {
            case "application/typescript":
            case "text/typescript":
            case "video/vnd.dlna.mpeg-tts":
            case "video/mp2t":
            case "application/x-typescript":
                return mapJsLikeExtension(specifier, "TypeScript");
            case "application/javascript":
            case "text/javascript":
            case "application/ecmascript":
            case "text/ecmascript":
            case "application/x-javascript":
            case "application/node":
                return mapJsLikeExtension(specifier, "JavaScript");
            case "text/jsx":
                return "JSX";
            case "text/tsx":
                return "TSX";
            case "application/json":
            case "text/json":
                return "Json";
            case "application/wasm":
                return "Wasm";
            case "text/plain":
            case "application/octet-stream":
                return mediaTypeFromSpecifier(specifier);
            default:
                return "Unknown";
        }
    }
    else {
        return mediaTypeFromSpecifier(specifier);
    }
}
function mapJsLikeExtension(specifier, defaultType) {
    const path = specifier.pathname;
    switch (extname(path)) {
        case ".jsx":
            return "JSX";
        case ".mjs":
            return "Mjs";
        case ".cjs":
            return "Cjs";
        case ".tsx":
            return "TSX";
        case ".ts":
            if (path.endsWith(".d.ts")) {
                return "Dts";
            }
            else {
                return defaultType;
            }
        case ".mts": {
            if (path.endsWith(".d.mts")) {
                return "Dmts";
            }
            else {
                return defaultType == "JavaScript" ? "Mjs" : "Mts";
            }
        }
        case ".cts": {
            if (path.endsWith(".d.cts")) {
                return "Dcts";
            }
            else {
                return defaultType == "JavaScript" ? "Cjs" : "Cts";
            }
        }
        default:
            return defaultType;
    }
}
export function mediaTypeFromSpecifier(specifier) {
    const path = specifier.pathname;
    switch (extname(path)) {
        case "":
            if (path.endsWith("/.tsbuildinfo")) {
                return "TsBuildInfo";
            }
            else {
                return "Unknown";
            }
        case ".ts":
            if (path.endsWith(".d.ts")) {
                return "Dts";
            }
            else {
                return "TypeScript";
            }
        case ".mts":
            if (path.endsWith(".d.mts")) {
                return "Dmts";
            }
            else {
                return "Mts";
            }
        case ".cts":
            if (path.endsWith(".d.cts")) {
                return "Dcts";
            }
            else {
                return "Cts";
            }
        case ".tsx":
            return "TSX";
        case ".js":
            return "JavaScript";
        case ".jsx":
            return "JSX";
        case ".mjs":
            return "Mjs";
        case ".cjs":
            return "Cjs";
        case ".json":
            return "Json";
        case ".wasm":
            return "Wasm";
        case ".tsbuildinfo":
            return "TsBuildInfo";
        case ".map":
            return "SourceMap";
        default:
            return "Unknown";
    }
}
export function parseNpmSpecifier(specifier) {
    if (specifier.protocol !== "npm:")
        throw new Error("Invalid npm specifier");
    const path = specifier.pathname;
    const startIndex = path[0] === "/" ? 1 : 0;
    let pathStartIndex;
    let versionStartIndex;
    if (path[startIndex] === "@") {
        const firstSlash = path.indexOf("/", startIndex);
        if (firstSlash === -1) {
            throw new Error(`Invalid npm specifier: ${specifier}`);
        }
        pathStartIndex = path.indexOf("/", firstSlash + 1);
        versionStartIndex = path.indexOf("@", firstSlash + 1);
    }
    else {
        pathStartIndex = path.indexOf("/", startIndex);
        versionStartIndex = path.indexOf("@", startIndex);
    }
    if (pathStartIndex === -1)
        pathStartIndex = path.length;
    if (versionStartIndex === -1)
        versionStartIndex = path.length;
    if (versionStartIndex > pathStartIndex) {
        versionStartIndex = pathStartIndex;
    }
    if (startIndex === versionStartIndex) {
        throw new Error(`Invalid npm specifier: ${specifier}`);
    }
    return {
        name: path.slice(startIndex, versionStartIndex),
        version: versionStartIndex === pathStartIndex
            ? null
            : path.slice(versionStartIndex + 1, pathStartIndex),
        path: pathStartIndex === path.length ? null : path.slice(pathStartIndex),
    };
}
export function parseJsrSpecifier(specifier) {
    if (specifier.protocol !== "jsr:")
        throw new Error("Invalid jsr specifier");
    const path = specifier.pathname;
    const startIndex = path[0] === "/" ? 1 : 0;
    if (path[startIndex] !== "@") {
        throw new Error(`Invalid jsr specifier: ${specifier}`);
    }
    const firstSlash = path.indexOf("/", startIndex);
    if (firstSlash === -1) {
        throw new Error(`Invalid jsr specifier: ${specifier}`);
    }
    let pathStartIndex = path.indexOf("/", firstSlash + 1);
    let versionStartIndex = path.indexOf("@", firstSlash + 1);
    if (pathStartIndex === -1)
        pathStartIndex = path.length;
    if (versionStartIndex === -1)
        versionStartIndex = path.length;
    if (versionStartIndex > pathStartIndex) {
        versionStartIndex = pathStartIndex;
    }
    if (startIndex === versionStartIndex) {
        throw new Error(`Invalid jsr specifier: ${specifier}`);
    }
    return {
        name: path.slice(startIndex, versionStartIndex),
        version: versionStartIndex === pathStartIndex
            ? null
            : path.slice(versionStartIndex + 1, pathStartIndex),
        path: pathStartIndex === path.length ? null : path.slice(pathStartIndex),
    };
}
const SLASH_NODE_MODULES_SLASH = `${SEPARATOR}node_modules${SEPARATOR}`;
const SLASH_NODE_MODULES = `${SEPARATOR}node_modules`;
export function isInNodeModules(path) {
    return path.includes(SLASH_NODE_MODULES_SLASH) ||
        path.endsWith(SLASH_NODE_MODULES);
}
export function isNodeModulesResolution(args) {
    return ((args.namespace === "" || args.namespace === "file") &&
        (isInNodeModules(args.resolveDir) || isInNodeModules(args.path) ||
            isInNodeModules(args.importer)));
}
//# sourceMappingURL=shared.js.map