/**
 * Core Command Executor
 *
 * UI-agnostic command execution engine.
 *
 * Input: raw string command line
 * Output: structured result (events, actions, state updates)
 *
 * Responsibilities:
 * - Parse command name + args
 * - Lookup in registry
 * - Execute handler
 * - Route output to eventBus (or return results for UI to display)
 *
 * No console.log spam — only emit events.
 */
import { commandRegistry } from './commandRegistry.js';
import { eventBus } from './eventBus.js';
/**
 * Parse command line input
 *
 * Responsibilities:
 * - Trim leading/trailing whitespace
 * - Support quoted arguments: "quoted value" and 'quoted value'
 * - Preserve spaces inside quotes
 * - Split unquoted tokens on whitespace
 *
 * Rules:
 * - Empty input → return { name: "", args: [], raw }
 * - Parsing never throws
 * - Parsing never emits UI output
 */
export function parseCommand(line) {
    const raw = line;
    const trimmed = line.trim();
    // Empty input
    if (!trimmed) {
        return { name: '', args: [], raw };
    }
    // Remove prompt if present
    const withoutPrompt = trimmed.replace(/^4runr>\s*/, '').trim();
    if (!withoutPrompt) {
        return { name: '', args: [], raw };
    }
    // Parse with quoted argument support
    const tokens = [];
    let current = '';
    let inDoubleQuote = false;
    let inSingleQuote = false;
    for (let i = 0; i < withoutPrompt.length; i++) {
        const char = withoutPrompt[i];
        if (char === '"' && !inSingleQuote) {
            if (inDoubleQuote) {
                // End of double-quoted string
                tokens.push(current);
                current = '';
                inDoubleQuote = false;
            }
            else {
                // Start of double-quoted string
                inDoubleQuote = true;
            }
        }
        else if (char === "'" && !inDoubleQuote) {
            if (inSingleQuote) {
                // End of single-quoted string
                tokens.push(current);
                current = '';
                inSingleQuote = false;
            }
            else {
                // Start of single-quoted string
                inSingleQuote = true;
            }
        }
        else if ((char === ' ' || char === '\t') && !inDoubleQuote && !inSingleQuote) {
            // Whitespace outside quotes - end current token
            if (current) {
                tokens.push(current);
                current = '';
            }
        }
        else {
            // Regular character - add to current token
            current += char;
        }
    }
    // Add final token if any
    if (current || inDoubleQuote || inSingleQuote) {
        tokens.push(current);
    }
    if (tokens.length === 0) {
        return { name: '', args: [], raw };
    }
    const name = tokens[0].toLowerCase();
    const args = tokens.slice(1);
    return { name, args, raw };
}
/**
 * Execute a parsed command
 *
 * @param parsed - Parsed command
 * @param ctx - Command context
 * @param emitToBus - If true, emit events to eventBus. If false, return events.
 * @returns Command result
 */
export async function executeCommand(parsed, ctx = {}, emitToBus = true) {
    // Empty command
    if (!parsed.name) {
        return { events: [] };
    }
    // Lookup command
    const command = commandRegistry.get(parsed.name);
    if (!command) {
        const errorEvent = {
            id: `err-${Date.now()}`,
            ts: Date.now(),
            tag: 'ERR',
            level: 'ERROR',
            msg: `Unknown command: ${parsed.name} (try 'help')`,
        };
        if (emitToBus) {
            eventBus.emit(errorEvent);
        }
        return { events: [errorEvent] };
    }
    // Execute handler
    try {
        const result = await command.handler(ctx, parsed.args);
        // Emit events to bus if requested
        if (emitToBus && result.events) {
            for (const event of result.events) {
                eventBus.emit(event);
            }
        }
        return result;
    }
    catch (error) {
        const errorEvent = {
            id: `err-${Date.now()}`,
            ts: Date.now(),
            tag: 'ERR',
            level: 'ERROR',
            msg: `Command error: ${error instanceof Error ? error.message : String(error)}`,
        };
        if (emitToBus) {
            eventBus.emit(errorEvent);
        }
        return { events: [errorEvent] };
    }
}
/**
 * Execute command from raw input string
 *
 * Convenience function that parses and executes in one call.
 */
export async function executeCommandLine(line, ctx = {}, emitToBus = true) {
    const parsed = parseCommand(line);
    return executeCommand(parsed, ctx, emitToBus);
}
//# sourceMappingURL=commandExecutor.js.map