"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.YcmdDetection = void 0;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const os = __importStar(require("os"));
const child_process_1 = require("child_process");
class YcmdDetection {
    static COMMON_PATHS = [
        '/usr/local/bin/ycmd',
        '/usr/bin/ycmd',
        '/opt/ycmd',
        path.join(os.homedir(), '.local/bin/ycmd'),
        path.join(os.homedir(), '.vim/plugged/YouCompleteMe/third_party/ycmd'),
        path.join(os.homedir(), '.config/nvim/plugged/YouCompleteMe/third_party/ycmd'),
        path.join(os.homedir(), '.knowhow/ycmd'),
    ];
    static isInPath() {
        try {
            (0, child_process_1.execSync)('which ycmd', { stdio: 'pipe' });
            return true;
        }
        catch {
            return false;
        }
    }
    static findInstallations() {
        const installations = [];
        for (const ycmdPath of this.COMMON_PATHS) {
            if (this.isValidYcmdInstallation(ycmdPath)) {
                installations.push(ycmdPath);
            }
        }
        if (this.isInPath()) {
            try {
                const pathResult = (0, child_process_1.execSync)('which ycmd', { encoding: 'utf8' }).trim();
                if (pathResult && !installations.includes(pathResult)) {
                    installations.push(pathResult);
                }
            }
            catch {
            }
        }
        return installations;
    }
    static getPreferredInstallation() {
        const installations = this.findInstallations();
        if (installations.length === 0) {
            return null;
        }
        const knowhowPath = path.join(os.homedir(), '.knowhow/ycmd');
        if (installations.includes(knowhowPath)) {
            return knowhowPath;
        }
        if (this.isInPath()) {
            try {
                return (0, child_process_1.execSync)('which ycmd', { encoding: 'utf8' }).trim();
            }
            catch {
            }
        }
        return installations[0];
    }
    static isValidYcmdInstallation(ycmdPath) {
        try {
            if (!fs.existsSync(ycmdPath)) {
                return false;
            }
            const stat = fs.statSync(ycmdPath);
            if (stat.isFile()) {
                return this.isExecutable(ycmdPath);
            }
            if (stat.isDirectory()) {
                const ycmdBinary = path.join(ycmdPath, 'ycmd');
                const ycmdScript = path.join(ycmdPath, 'ycmd.py');
                const ycmdMainScript = path.join(ycmdPath, 'ycmd', '__main__.py');
                return fs.existsSync(ycmdBinary) ||
                    fs.existsSync(ycmdScript) ||
                    fs.existsSync(ycmdMainScript);
            }
            return false;
        }
        catch {
            return false;
        }
    }
    static isExecutable(filePath) {
        try {
            fs.accessSync(filePath, fs.constants.F_OK | fs.constants.X_OK);
            return true;
        }
        catch {
            return false;
        }
    }
    static getYcmdCommand(ycmdPath) {
        if (!this.isValidYcmdInstallation(ycmdPath)) {
            throw new Error(`Invalid ycmd installation: ${ycmdPath}`);
        }
        const stat = fs.statSync(ycmdPath);
        if (stat.isFile() && this.isExecutable(ycmdPath)) {
            return [ycmdPath];
        }
        if (stat.isDirectory()) {
            const ycmdBinary = path.join(ycmdPath, 'ycmd');
            const ycmdScript = path.join(ycmdPath, 'ycmd.py');
            const ycmdMainScript = path.join(ycmdPath, 'ycmd', '__main__.py');
            if (fs.existsSync(ycmdBinary) && this.isExecutable(ycmdBinary)) {
                return [ycmdBinary];
            }
            if (fs.existsSync(ycmdScript)) {
                return ['python3', ycmdScript];
            }
            if (fs.existsSync(ycmdMainScript)) {
                return ['python3', '-m', 'ycmd'];
            }
        }
        throw new Error(`Could not determine ycmd command for: ${ycmdPath}`);
    }
    static isPythonAvailable() {
        try {
            (0, child_process_1.execSync)('python3 --version', { stdio: 'pipe' });
            return true;
        }
        catch {
            try {
                (0, child_process_1.execSync)('python --version', { stdio: 'pipe' });
                return true;
            }
            catch {
                return false;
            }
        }
    }
    static getPythonCommand() {
        try {
            (0, child_process_1.execSync)('python3 --version', { stdio: 'pipe' });
            return 'python3';
        }
        catch {
            try {
                (0, child_process_1.execSync)('python --version', { stdio: 'pipe' });
                return 'python';
            }
            catch {
                throw new Error('Python is not available in PATH');
            }
        }
    }
}
exports.YcmdDetection = YcmdDetection;
//# sourceMappingURL=detection.js.map