"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.ycmdServerManager = void 0;
const server_1 = require("./server");
const client_1 = require("./client");
const pathUtils_1 = require("./utils/pathUtils");
const start_1 = require("./tools/start");
const fs = __importStar(require("fs"));
const net = __importStar(require("net"));
const path = __importStar(require("path"));
const utils_1 = require("../../../utils");
class YcmdServerManager {
    static instance;
    server = null;
    constructor() { }
    static getInstance() {
        if (!YcmdServerManager.instance) {
            YcmdServerManager.instance = new YcmdServerManager();
        }
        return YcmdServerManager.instance;
    }
    getServer() {
        if (!this.server) {
            this.server = new server_1.YcmdServer();
        }
        return this.server;
    }
    async isRunning() {
        if (this.server && this.server.isRunning()) {
            return true;
        }
        const detectedServer = await this.detectRunningServer();
        if (detectedServer) {
            if (!this.server) {
                this.server = new server_1.YcmdServer();
            }
            this.server.setExternalServerInfo(detectedServer);
            return true;
        }
        return false;
    }
    async detectRunningServer() {
        const commonPorts = [
            8080, 8081, 8082, 8083, 8084, 8085, 8086, 8087, 8088, 8089,
        ];
        for (const port of commonPorts) {
            try {
                const isOpen = await this.checkPort("127.0.0.1", port);
                if (!isOpen)
                    continue;
                const serverInfo = {
                    port,
                    host: "127.0.0.1",
                    hmacSecret: "",
                    status: "running",
                };
                const client = new client_1.YcmdClient(serverInfo);
                const isReady = await client.isReady();
                if (isReady) {
                    console.log(`Detected running ycmd server on port ${port}`);
                    return serverInfo;
                }
            }
            catch (error) {
                continue;
            }
        }
        return null;
    }
    checkPort(host, port) {
        return new Promise((resolve) => {
            const socket = new net.Socket();
            socket.setTimeout(1000);
            socket.on("connect", () => {
                socket.destroy();
                resolve(true);
            });
            socket.on("timeout", () => {
                socket.destroy();
                resolve(false);
            });
            socket.on("error", () => {
                resolve(false);
            });
            socket.connect(port, host);
        });
    }
    getServerInfo() {
        return this.server ? this.server.getServerInfo() : null;
    }
    async start(workspaceRoot, port) {
        const server = this.getServer();
        return server.start(workspaceRoot, port);
    }
    async stop() {
        if (this.server) {
            await this.server.stop();
        }
    }
    async healthCheck() {
        return this.server ? this.server.healthCheck() : false;
    }
    async restart(workspaceRoot, port) {
        const server = this.getServer();
        return server.restart(workspaceRoot, port);
    }
    async setupClientAndNotifyFile(params) {
        try {
            const resolvedFilePath = (0, pathUtils_1.resolveFilePath)(params.filepath);
            const projectRoot = (0, pathUtils_1.findProjectRoot)(path.dirname(resolvedFilePath));
            const tsconfigPath = path.join(projectRoot, "tsconfig.json");
            let contents = params.fileContents;
            if (!contents) {
                try {
                    contents = await fs.promises.readFile(resolvedFilePath, "utf8");
                }
                catch (error) {
                    return {
                        success: false,
                        message: `Failed to read file: ${error.message}`,
                    };
                }
            }
            const filetypes = (0, client_1.getFileTypes)(resolvedFilePath);
            if (!(await this.isRunning())) {
                console.log("ycmd server not running, attempting to start...");
                try {
                    const startResult = await (0, start_1.ycmdStart)({});
                    if (!startResult.success) {
                        return {
                            success: false,
                            message: `Failed to start ycmd server: ${startResult.message}`,
                        };
                    }
                    console.log("ycmd server started successfully");
                }
                catch (error) {
                    return {
                        success: false,
                        message: `Failed to start ycmd server: ${error.message}`,
                    };
                }
            }
            const serverInfo = this.getServerInfo();
            if (!serverInfo) {
                return {
                    success: false,
                    message: "Failed to get server information",
                };
            }
            const client = new client_1.YcmdClient(serverInfo);
            try {
                console.log("Starting enhanced TSServer setup sequence...");
                console.log(`Project root: ${projectRoot}`);
                console.log(`TSConfig path: ${tsconfigPath}`);
                console.log(`File types: ${filetypes.join(", ")}`);
                console.log(`Target file: ${resolvedFilePath}`);
                console.log(`Notifying target file: ${resolvedFilePath}`);
                await client.notifyFileEvent("BufferVisit", resolvedFilePath, contents, filetypes);
                await (0, utils_1.wait)(100);
                await client.notifyFileEvent("FileReadyToParse", resolvedFilePath, contents, filetypes);
                await (0, utils_1.wait)(100);
                await (0, utils_1.wait)(500);
                console.log("Successfully completed enhanced TSServer setup sequence");
            }
            catch (error) {
                console.warn("Failed to notify file event:", error);
            }
            return {
                success: true,
                client,
                resolvedFilePath,
                contents,
                filetypes,
                message: "Successfully set up ycmd client and notified file",
            };
        }
        catch (error) {
            return {
                success: false,
                message: `Failed to set up ycmd client: ${error.message}`,
            };
        }
    }
}
exports.ycmdServerManager = YcmdServerManager.getInstance();
//# sourceMappingURL=serverManager.js.map