/**
 * @license
 * Copyright 2025 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import { IdeClient, logIdeConnection, IdeConnectionEvent, IdeConnectionType, } from 'sixth-cli-core';
import { getIdeInstaller, IDEConnectionStatus, ideContextStore, GEMINI_CLI_COMPANION_EXTENSION_NAME, } from 'sixth-cli-core';
import path from 'node:path';
import { CommandKind } from './types.js';
import { SettingScope } from '../../config/settings.js';
function getIdeStatusMessage(ideClient) {
    const connection = ideClient.getConnectionStatus();
    switch (connection.status) {
        case IDEConnectionStatus.Connected:
            return {
                messageType: 'info',
                content: `🟢 Connected to ${ideClient.getDetectedIdeDisplayName()}`,
            };
        case IDEConnectionStatus.Connecting:
            return {
                messageType: 'info',
                content: `🟡 Connecting...`,
            };
        default: {
            let content = `🔴 Disconnected`;
            if (connection?.details) {
                content += `: ${connection.details}`;
            }
            return {
                messageType: 'error',
                content,
            };
        }
    }
}
function formatFileList(openFiles) {
    const basenameCounts = new Map();
    for (const file of openFiles) {
        const basename = path.basename(file.path);
        basenameCounts.set(basename, (basenameCounts.get(basename) || 0) + 1);
    }
    const fileList = openFiles
        .map((file) => {
        const basename = path.basename(file.path);
        const isDuplicate = (basenameCounts.get(basename) || 0) > 1;
        const parentDir = path.basename(path.dirname(file.path));
        const displayName = isDuplicate
            ? `${basename} (/${parentDir})`
            : basename;
        return `  - ${displayName}${file.isActive ? ' (active)' : ''}`;
    })
        .join('\n');
    const infoMessage = `
(Note: The file list is limited to a number of recently accessed files within your workspace and only includes local files on disk)`;
    return `\n\nOpen files:\n${fileList}\n${infoMessage}`;
}
async function getIdeStatusMessageWithFiles(ideClient) {
    const connection = ideClient.getConnectionStatus();
    switch (connection.status) {
        case IDEConnectionStatus.Connected: {
            let content = `🟢 Connected to ${ideClient.getDetectedIdeDisplayName()}`;
            const context = ideContextStore.get();
            const openFiles = context?.workspaceState?.openFiles;
            if (openFiles && openFiles.length > 0) {
                content += formatFileList(openFiles);
            }
            return {
                messageType: 'info',
                content,
            };
        }
        case IDEConnectionStatus.Connecting:
            return {
                messageType: 'info',
                content: `🟡 Connecting...`,
            };
        default: {
            let content = `🔴 Disconnected`;
            if (connection?.details) {
                content += `: ${connection.details}`;
            }
            return {
                messageType: 'error',
                content,
            };
        }
    }
}
async function setIdeModeAndSyncConnection(config, value) {
    config.setIdeMode(value);
    const ideClient = await IdeClient.getInstance();
    if (value) {
        await ideClient.connect();
        logIdeConnection(config, new IdeConnectionEvent(IdeConnectionType.SESSION));
    }
    else {
        await ideClient.disconnect();
    }
}
export const ideCommand = async () => {
    const ideClient = await IdeClient.getInstance();
    const currentIDE = ideClient.getCurrentIde();
    if (!currentIDE) {
        return {
            name: 'ide',
            description: 'Manage IDE integration',
            kind: CommandKind.BUILT_IN,
            action: () => ({
                type: 'message',
                messageType: 'error',
                content: `IDE integration is not supported in your current environment. To use this feature, run Gemini CLI in one of these supported IDEs: VS Code or VS Code forks.`,
            }),
        };
    }
    const ideSlashCommand = {
        name: 'ide',
        description: 'Manage IDE integration',
        kind: CommandKind.BUILT_IN,
        subCommands: [],
    };
    const statusCommand = {
        name: 'status',
        description: 'Check status of IDE integration',
        kind: CommandKind.BUILT_IN,
        action: async () => {
            const { messageType, content } = await getIdeStatusMessageWithFiles(ideClient);
            return {
                type: 'message',
                messageType,
                content,
            };
        },
    };
    const installCommand = {
        name: 'install',
        description: `Install required IDE companion for ${ideClient.getDetectedIdeDisplayName()}`,
        kind: CommandKind.BUILT_IN,
        action: async (context) => {
            const installer = getIdeInstaller(currentIDE);
            if (!installer) {
                context.ui.addItem({
                    type: 'error',
                    text: `No installer is available for ${ideClient.getDetectedIdeDisplayName()}. Please install the '${GEMINI_CLI_COMPANION_EXTENSION_NAME}' extension manually from the marketplace.`,
                }, Date.now());
                return;
            }
            context.ui.addItem({
                type: 'info',
                text: `Installing IDE companion...`,
            }, Date.now());
            const result = await installer.install();
            context.ui.addItem({
                type: result.success ? 'info' : 'error',
                text: result.message,
            }, Date.now());
            if (result.success) {
                context.services.settings.setValue(SettingScope.User, 'ide.enabled', true);
                // Poll for up to 5 seconds for the extension to activate.
                for (let i = 0; i < 10; i++) {
                    await setIdeModeAndSyncConnection(context.services.config, true);
                    if (ideClient.getConnectionStatus().status ===
                        IDEConnectionStatus.Connected) {
                        break;
                    }
                    await new Promise((resolve) => setTimeout(resolve, 500));
                }
                const { messageType, content } = getIdeStatusMessage(ideClient);
                if (messageType === 'error') {
                    context.ui.addItem({
                        type: messageType,
                        text: `Failed to automatically enable IDE integration. To fix this, run the CLI in a new terminal window.`,
                    }, Date.now());
                }
                else {
                    context.ui.addItem({
                        type: messageType,
                        text: content,
                    }, Date.now());
                }
            }
        },
    };
    const enableCommand = {
        name: 'enable',
        description: 'Enable IDE integration',
        kind: CommandKind.BUILT_IN,
        action: async (context) => {
            context.services.settings.setValue(SettingScope.User, 'ide.enabled', true);
            await setIdeModeAndSyncConnection(context.services.config, true);
            const { messageType, content } = getIdeStatusMessage(ideClient);
            context.ui.addItem({
                type: messageType,
                text: content,
            }, Date.now());
        },
    };
    const disableCommand = {
        name: 'disable',
        description: 'Disable IDE integration',
        kind: CommandKind.BUILT_IN,
        action: async (context) => {
            context.services.settings.setValue(SettingScope.User, 'ide.enabled', false);
            await setIdeModeAndSyncConnection(context.services.config, false);
            const { messageType, content } = getIdeStatusMessage(ideClient);
            context.ui.addItem({
                type: messageType,
                text: content,
            }, Date.now());
        },
    };
    const { status } = ideClient.getConnectionStatus();
    const isConnected = status === IDEConnectionStatus.Connected;
    if (isConnected) {
        ideSlashCommand.subCommands = [statusCommand, disableCommand];
    }
    else {
        ideSlashCommand.subCommands = [
            enableCommand,
            statusCommand,
            installCommand,
        ];
    }
    return ideSlashCommand;
};
//# sourceMappingURL=ideCommand.js.map