import { spawnSync } from "child_process";
import { existsSync } from "fs";
import { join, resolve } from "path";
const SERVERS = [
    {
        id: "typescript",
        command: "npx",
        args: ["-y", "typescript-language-server", "--stdio"],
        languageIds: ["typescript", "javascript", "typescriptreact", "javascriptreact"],
        extensions: [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".mts", ".cts"],
        rootIndicators: ["package.json", "package-lock.json", "tsconfig.json", "jsconfig.json"],
    },
    {
        id: "pyright",
        command: "npx",
        args: ["-y", "pyright", "--stdio"],
        languageIds: ["python"],
        extensions: [".py", ".pyi"],
        rootIndicators: ["pyproject.toml", "setup.py", "requirements.txt", "Pipfile", ".git"],
    },
    {
        id: "gopls",
        command: "gopls",
        args: [],
        languageIds: ["go"],
        extensions: [".go"],
        rootIndicators: ["go.mod", "go.work"],
    },
    {
        id: "rust-analyzer",
        command: "rust-analyzer",
        args: [],
        languageIds: ["rust"],
        extensions: [".rs"],
        rootIndicators: ["Cargo.toml"],
    },
    {
        id: "clangd",
        command: "clangd",
        args: [],
        languageIds: ["c", "cpp", "objective-c", "objective-cpp"],
        extensions: [".c", ".cpp", ".cc", ".cxx", ".h", ".hpp", ".hh", ".hxx", ".m", ".mm"],
        rootIndicators: ["compile_commands.json", ".clangd"],
    },
    {
        id: "elixir-ls",
        command: "elixir-ls",
        args: [],
        languageIds: ["elixir"],
        extensions: [".ex", ".exs"],
        rootIndicators: ["mix.exs"],
    },
    {
        id: "ruby-lsp",
        command: "ruby-lsp",
        args: [],
        languageIds: ["ruby"],
        extensions: [".rb", ".rake", ".gemspec"],
        rootIndicators: ["Gemfile"],
    },
    {
        id: "zls",
        command: "zls",
        args: [],
        languageIds: ["zig"],
        extensions: [".zig", ".zon"],
        rootIndicators: ["build.zig"],
    },
    {
        id: "bash-language-server",
        command: "bash-language-server",
        args: ["start"],
        languageIds: ["shellscript", "bash"],
        extensions: [".sh", ".bash", ".zsh"],
        rootIndicators: [],
    },
];
export function findProjectRoot(filePath, indicators) {
    const dir = resolve(filePath);
    const current = existsSync(dir) && !dir.endsWith("/") ? resolve(dir) : resolve(process.cwd());
    // If filePath is a file, start from its directory
    let candidate = existsSync(current) ? current : process.cwd();
    if (indicators.length === 0)
        return candidate;
    while (true) {
        for (const indicator of indicators) {
            if (existsSync(join(candidate, indicator))) {
                return candidate;
            }
        }
        const parent = resolve(candidate, "..");
        if (parent === candidate)
            return null;
        candidate = parent;
    }
}
const EXT_TO_LANG_ID = {
    ".ts": "typescript",
    ".tsx": "typescriptreact",
    ".js": "javascript",
    ".jsx": "javascriptreact",
    ".mjs": "javascript",
    ".cjs": "javascript",
    ".mts": "typescript",
    ".cts": "typescript",
    ".py": "python",
    ".pyi": "python",
    ".go": "go",
    ".rs": "rust",
    ".c": "c",
    ".cpp": "cpp",
    ".cc": "cpp",
    ".cxx": "cpp",
    ".h": "c",
    ".hpp": "cpp",
    ".hh": "cpp",
    ".hxx": "cpp",
    ".ex": "elixir",
    ".exs": "elixir",
    ".rb": "ruby",
    ".rake": "ruby",
    ".gemspec": "ruby",
    ".zig": "zig",
    ".zon": "zig",
    ".sh": "bash",
    ".bash": "bash",
    ".zsh": "bash",
};
export function getLanguageId(extension) {
    return EXT_TO_LANG_ID[extension];
}
export function findServerForFile(filePath) {
    const ext = Object.keys(EXT_TO_LANG_ID).find((e) => filePath.endsWith(e));
    if (!ext)
        return null;
    const langId = EXT_TO_LANG_ID[ext];
    for (const info of SERVERS) {
        if (info.extensions.includes(ext) || info.languageIds.includes(langId)) {
            const rootPath = findProjectRoot(filePath, info.rootIndicators);
            if (rootPath || info.rootIndicators.length === 0) {
                return { info, rootPath: rootPath ?? resolve(process.cwd()) };
            }
        }
    }
    return null;
}
export function isServerAvailable(info) {
    if (info.command === "npx")
        return true; // npx is always available
    const result = spawnSync("which", [info.command], { encoding: "utf-8" });
    return result.status === 0;
}
export function getAllServers() {
    return [...SERVERS];
}
//# sourceMappingURL=server-registry.js.map