// engine/desktop-detector.ts — SPEC-014b desktop advanced detection
// Detects IPC patterns, Tauri commands, .NET UI frameworks, macOS app types, Linux native frameworks.
import { readFile } from 'node:fs/promises';
import { join } from 'node:path';
import { glob } from 'glob';
// --- Shared utilities ---
async function readFileSafe(filePath) {
    try {
        return await readFile(filePath, 'utf-8');
    }
    catch {
        return null;
    }
}
async function globFirst(pattern, cwd) {
    try {
        const matches = await glob(pattern, { cwd, nodir: true, maxDepth: 5, dot: false });
        return matches[0] ?? null;
    }
    catch {
        return null;
    }
}
// --- Electron IPC detection ---
/**
 * Detect Electron IPC pattern: 'context-bridge' (safe) or 'node-integration' (legacy/unsafe).
 * Reads main process files looking for contextBridge vs nodeIntegration: true.
 */
export async function detectElectronIPCPattern(projectPath) {
    const candidates = ['src/main.ts', 'src/main.js', 'main.ts', 'main.js', 'electron/main.ts'];
    for (const candidate of candidates) {
        const content = await readFileSafe(join(projectPath, candidate));
        if (content === null) {
            continue;
        }
        if (content.includes('contextBridge') || content.includes('contextIsolation')) {
            return 'context-bridge';
        }
        if (/nodeIntegration\s*:\s*true/.exec(content)) {
            return 'node-integration';
        }
    }
    // Also check preload files
    const preloadFile = await globFirst('**/preload.{ts,js}', projectPath);
    if (preloadFile !== null) {
        const preloadContent = await readFileSafe(join(projectPath, preloadFile));
        if (preloadContent?.includes('contextBridge')) {
            return 'context-bridge';
        }
    }
    return null;
}
// --- Tauri command detection ---
/**
 * Detect Tauri commands from src-tauri/src/main.rs or lib.rs and plugins from tauri.conf.json.
 */
export async function detectTauriCommands(projectPath) {
    const rustCandidates = [
        'src-tauri/src/main.rs',
        'src-tauri/src/lib.rs',
        'src-tauri/src/commands.rs',
    ];
    const commands = [];
    let foundRust = false;
    for (const candidate of rustCandidates) {
        const content = await readFileSafe(join(projectPath, candidate));
        if (content === null) {
            continue;
        }
        foundRust = true;
        const commandMatches = content.matchAll(/#\[tauri::command\]\s*(?:pub\s+)?(?:async\s+)?fn\s+(\w+)/g);
        for (const match of commandMatches) {
            if (match[1]) {
                commands.push(match[1]);
            }
        }
    }
    if (!foundRust) {
        return null;
    }
    const plugins = [];
    const confPaths = ['src-tauri/tauri.conf.json', 'tauri.conf.json', 'src-tauri/tauri.conf.json5'];
    for (const confPath of confPaths) {
        const content = await readFileSafe(join(projectPath, confPath));
        if (content === null) {
            continue;
        }
        try {
            const conf = JSON.parse(content);
            const pluginsSection = conf.plugins;
            if (pluginsSection) {
                plugins.push(...Object.keys(pluginsSection));
            }
        }
        catch {
            // Invalid JSON
        }
        break;
    }
    return { commands, plugins };
}
// --- .NET UI Framework detection ---
/**
 * Detect .NET UI framework from .csproj files:
 * WPF, WinForms, MAUI, Avalonia, or Blazor Hybrid.
 */
export async function detectDotNetUIFramework(projectPath) {
    const csprojFile = await globFirst('**/*.csproj', projectPath);
    if (csprojFile === null) {
        return null;
    }
    const content = await readFileSafe(join(projectPath, csprojFile));
    if (content === null) {
        return null;
    }
    const lower = content.toLowerCase();
    if (lower.includes('<usemaui>true</usemaui>')) {
        return 'maui';
    }
    if (lower.includes('<usewpf>true</usewpf>')) {
        return 'wpf';
    }
    if (lower.includes('<usewindowsforms>true</usewindowsforms>')) {
        return 'winforms';
    }
    if (lower.includes('avalonia')) {
        return 'avalonia';
    }
    if (lower.includes('microsoft.aspnetcore.components.webview')) {
        return 'blazor-hybrid';
    }
    return null;
}
// --- macOS native app type detection ---
/**
 * Detect native macOS app type: SwiftUI, AppKit, or menu-bar app.
 */
export async function detectMacOSAppType(projectPath) {
    // Check Info.plist for LSUIElement (menu bar app)
    const infoPlist = await readFileSafe(join(projectPath, 'Info.plist'));
    if (infoPlist?.includes('LSUIElement')) {
        return 'menu-bar';
    }
    // Scan Swift files
    const swiftFile = await globFirst('**/*.swift', projectPath);
    if (swiftFile === null) {
        return null;
    }
    const content = await readFileSafe(join(projectPath, swiftFile));
    if (content === null) {
        return null;
    }
    if (content.includes('import SwiftUI') && content.includes('@main')) {
        // Could be menu bar if using MenuBarExtra or NSStatusItem
        if (content.includes('MenuBarExtra') || content.includes('NSStatusItem')) {
            return 'menu-bar';
        }
        return 'swiftui';
    }
    if (content.includes('NSApplicationDelegate') || content.includes('NSViewController')) {
        return 'appkit';
    }
    return null;
}
// --- Linux native framework detection ---
/**
 * Detect native Linux UI framework: GTK, Qt native, or GNOME Builder project.
 */
export async function detectLinuxNativeFramework(projectPath) {
    // Check for GNOME Builder signals: .doap or meson.build
    const mesonContent = await readFileSafe(join(projectPath, 'meson.build'));
    if (mesonContent !== null) {
        if (mesonContent.includes('gnome.compile_resources') || mesonContent.includes("'gtk'")) {
            // Check if there's a .doap file which signals GNOME Builder
            const doapFile = await globFirst('*.doap', projectPath);
            if (doapFile !== null || mesonContent.includes('gnome.compile_resources')) {
                return 'gnome';
            }
        }
    }
    // Check Cargo.toml for gtk-rs or relm4
    const cargoContent = await readFileSafe(join(projectPath, 'Cargo.toml'));
    if (cargoContent !== null) {
        if (cargoContent.includes('gtk4') ||
            cargoContent.includes('gtk3') ||
            cargoContent.includes('relm4')) {
            return 'gtk';
        }
        if (cargoContent.includes('qt-rs') ||
            cargoContent.includes('qmetaobject') ||
            cargoContent.includes('cxx-qt')) {
            return 'qt-native';
        }
    }
    // Check Python dependencies
    const requirementsContent = await readFileSafe(join(projectPath, 'requirements.txt'));
    if (requirementsContent !== null) {
        const lower = requirementsContent.toLowerCase();
        if (lower.includes('pygobject') || lower.includes('pygtk') || lower.includes('gtk')) {
            return 'gtk';
        }
        if (lower.includes('pyqt6') || lower.includes('pyside6') || lower.includes('pyqt5')) {
            return 'qt-native';
        }
    }
    return null;
}
//# sourceMappingURL=desktop-detector.js.map