/**
 * App-level editor that extends the base TUI Editor with keybinding dispatch,
 * bracketed-paste file-path interception, and extension shortcut support.
 */
import { Editor, getEditorKeybindings, visibleWidth } from '../../../tui/index.js';
import { stripQuotes } from '../../input/file-attachments.js';
const BRACKETED_PASTE_START = '\x1b[200~';
const BRACKETED_PASTE_END = '\x1b[201~';
/**
 * Custom editor that handles app-level keybindings for coding-agent.
 */
export class CustomEditor extends Editor {
    keybindings;
    actionHandlers = new Map();
    /** Optional badge rendered right-aligned in the top border line. */
    topBorderBadge;
    // Special handlers that can be dynamically replaced
    onEscape;
    onCtrlD;
    onPasteImage;
    /** Handler for pasted file paths (drag-and-drop). Returns true if handled. */
    onFilePaste;
    /** Handler for extension-registered shortcuts. Returns true if handled. */
    onExtensionShortcut;
    /** Move focus into footer action rows when the prompt is empty and the user arrows down. */
    onFooterNavigateDown;
    /** Build a CustomEditor wired to the given keybindings manager. */
    constructor(tui, theme, keybindings, options) {
        super(tui, theme, options);
        this.keybindings = keybindings;
    }
    /**
     * Register a handler for an app action.
     */
    onAction(action, handler) {
        this.actionHandlers.set(action, handler);
    }
    /** Render editor lines, optionally overlaying a right-aligned top-border badge. */
    render(width) {
        const lines = super.render(width);
        if (this.topBorderBadge && lines.length > 0) {
            // Replace the top border line with one that has the badge right-aligned.
            const badgeWidth = visibleWidth(this.topBorderBadge);
            const dashes = Math.max(0, width - badgeWidth - 1);
            lines[0] = this.borderColor('─'.repeat(dashes) + ' ') + this.topBorderBadge;
        }
        return lines;
    }
    /** Dispatch input through extension shortcuts, app keybindings, paste interception, then editor. */
    handleInput(data) {
        // Check extension-registered shortcuts first
        if (this.onExtensionShortcut?.(data)) {
            return;
        }
        const editorKeybindings = getEditorKeybindings();
        if (editorKeybindings.matches(data, 'cursorDown') && this.getText().trim().length === 0) {
            if (this.onFooterNavigateDown?.()) {
                return;
            }
        }
        // Check for paste image keybinding
        if (this.keybindings.matches(data, 'pasteImage')) {
            this.onPasteImage?.();
            return;
        }
        // Check app keybindings first
        // Escape/interrupt - only if autocomplete is NOT active
        if (this.keybindings.matches(data, 'interrupt')) {
            if (!this.isShowingAutocomplete()) {
                // Use dynamic onEscape if set, otherwise registered handler
                const handler = this.onEscape ?? this.actionHandlers.get('interrupt');
                if (handler) {
                    handler();
                    return;
                }
            }
            // Let parent handle escape for autocomplete cancellation
            super.handleInput(data);
            return;
        }
        // Exit (Ctrl+D) - only when editor is empty
        if (this.keybindings.matches(data, 'exit')) {
            if (this.getText().length === 0) {
                const handler = this.onCtrlD ?? this.actionHandlers.get('exit');
                if (handler)
                    handler();
                return;
            }
            // Fall through to editor handling for delete-char-forward when not empty
        }
        // Check all other app actions
        for (const [action, handler] of this.actionHandlers) {
            if (action !== 'interrupt' && action !== 'exit' && this.keybindings.matches(data, action)) {
                handler();
                return;
            }
        }
        // Intercept bracketed paste: if the pasted content is a file path,
        // redirect to onFilePaste instead of inserting as text
        if (this.onFilePaste && data.includes(BRACKETED_PASTE_START)) {
            const startIdx = data.indexOf(BRACKETED_PASTE_START) + BRACKETED_PASTE_START.length;
            const endIdx = data.indexOf(BRACKETED_PASTE_END);
            if (endIdx !== -1) {
                const pasteContent = stripQuotes(data.substring(startIdx, endIdx).trim());
                // Check if the entire paste is a single absolute file path
                if (pasteContent.startsWith('/') &&
                    !pasteContent.includes('\n') &&
                    this.onFilePaste(pasteContent)) {
                    // File paste handled — process any remaining data after the paste end marker
                    const remaining = data.substring(endIdx + BRACKETED_PASTE_END.length);
                    if (remaining.length > 0) {
                        this.handleInput(remaining);
                    }
                    return;
                }
            }
        }
        // Pass to parent for editor handling
        super.handleInput(data);
    }
}
//# sourceMappingURL=custom-editor.js.map