import { nonAlphanumericKeys } from '../parse-keypress.js';
import { Event } from './event.js';
function parseKey(keypress) {
    const key = {
        upArrow: keypress.name === 'up',
        downArrow: keypress.name === 'down',
        leftArrow: keypress.name === 'left',
        rightArrow: keypress.name === 'right',
        pageDown: keypress.name === 'pagedown',
        pageUp: keypress.name === 'pageup',
        wheelUp: keypress.name === 'wheelup',
        wheelDown: keypress.name === 'wheeldown',
        home: keypress.name === 'home',
        end: keypress.name === 'end',
        return: keypress.name === 'return',
        escape: keypress.name === 'escape',
        fn: keypress.fn,
        ctrl: keypress.ctrl,
        shift: keypress.shift,
        tab: keypress.name === 'tab',
        backspace: keypress.name === 'backspace',
        delete: keypress.name === 'delete',
        // `parseKeypress` parses \u001B\u001B[A (meta + up arrow) as meta = false
        // but with option = true, so we need to take this into account here
        // to avoid breaking changes in Ink.
        // TODO(vadimdemedes): consider removing this in the next major version.
        meta: keypress.meta || keypress.name === 'escape' || keypress.option,
        // Super (Cmd on macOS / Win key) — only arrives via kitty keyboard
        // protocol CSI u sequences. Distinct from meta (Alt/Option) so
        // bindings like cmd+c can be expressed separately from opt+c.
        super: keypress.super,
    };
    let input = keypress.ctrl ? keypress.name : keypress.sequence;
    // Handle undefined input case
    if (input === undefined) {
        input = '';
    }
    // When ctrl is set, keypress.name for space is the literal word "space".
    // Convert to actual space character for consistency with the CSI u branch
    // (which maps 'space' → ' '). Without this, ctrl+space leaks the literal
    // word "space" into text input.
    if (keypress.ctrl && input === 'space') {
        input = ' ';
    }
    // Suppress unrecognized escape sequences that were parsed as function keys
    // (matched by FN_KEY_RE) but have no name in the keyName map.
    // Examples: ESC[25~ (F13/Right Alt on Windows), ESC[26~ (F14), etc.
    // Without this, the ESC prefix is stripped below and the remainder (e.g.,
    // "[25~") leaks into the input as literal text.
    if (keypress.code && !keypress.name) {
        input = '';
    }
    // Suppress ESC-less SGR mouse fragments. When a heavy React commit blocks
    // the event loop past App's 50ms NORMAL_TIMEOUT flush, a CSI split across
    // stdin chunks gets its buffered ESC flushed as a lone Escape key, and the
    // continuation arrives as a text token with name='' — which falls through
    // all of parseKeypress's ESC-anchored regexes and the nonAlphanumericKeys
    // clear below (name is falsy). The fragment then leaks into the prompt as
    // literal `[<64;74;16M`. This is the same defensive sink as the F13 guard
    // above; the underlying tokenizer-flush race is upstream of this layer.
    if (!keypress.name && /^(?:\[<|<)\d+;\d+;\d+[Mm]/.test(input)) {
        input = '';
    }
    // Strip meta if it's still remaining after `parseKeypress`
    // TODO(vadimdemedes): remove this in the next major version.
    if (input.startsWith('\u001B')) {
        input = input.slice(1);
    }
    // Track whether we've already processed this as a special sequence
    // that converted input to the key name (CSI u or application keypad mode).
    // For these, we don't want to clear input with nonAlphanumericKeys check.
    let processedAsSpecialSequence = false;
    // Handle CSI u sequences (Kitty keyboard protocol): after stripping ESC,
    // we're left with "[codepoint;modifieru" (e.g., "[98;3u" for Alt+b).
    // Use the parsed key name instead for input handling. Require a digit
    // after [ — real CSI u is always [<digits>…u, and a bare startsWith('[')
    // false-matches X10 mouse at row 85 (Cy = 85+32 = 'u'), leaking the
    // literal text "mouse" into the prompt via processedAsSpecialSequence.
    if (/^\[\d/.test(input) && input.endsWith('u')) {
        if (!keypress.name) {
            // Unmapped Kitty functional key (Caps Lock 57358, F13–F35, KP nav,
            // bare modifiers, etc.) — keycodeToName() returned undefined. Swallow
            // so the raw "[57358u" doesn't leak into the prompt. See #38781.
            input = '';
        }
        else {
            // 'space' → ' '; 'escape' → '' (key.escape carries it;
            // processedAsSpecialSequence bypasses the nonAlphanumericKeys
            // clear below, so we must handle it explicitly here);
            // otherwise use key name.
            input =
                keypress.name === 'space'
                    ? ' '
                    : keypress.name === 'escape'
                        ? ''
                        : keypress.name;
        }
        processedAsSpecialSequence = true;
    }
    // Handle xterm modifyOtherKeys sequences: after stripping ESC, we're left
    // with "[27;modifier;keycode~" (e.g., "[27;3;98~" for Alt+b). Same
    // extraction as CSI u — without this, printable-char keycodes (single-letter
    // names) skip the nonAlphanumericKeys clear and leak "[27;..." as input.
    if (input.startsWith('[27;') && input.endsWith('~')) {
        if (!keypress.name) {
            // Unmapped modifyOtherKeys keycode — swallow for consistency with
            // the CSI u handler above. Practically untriggerable today (xterm
            // modifyOtherKeys only sends ASCII keycodes, all mapped), but
            // guards against future terminal behavior.
            input = '';
        }
        else {
            input =
                keypress.name === 'space'
                    ? ' '
                    : keypress.name === 'escape'
                        ? ''
                        : keypress.name;
        }
        processedAsSpecialSequence = true;
    }
    // Handle application keypad mode sequences: after stripping ESC,
    // we're left with "O<letter>" (e.g., "Op" for numpad 0, "Oy" for numpad 9).
    // Use the parsed key name (the digit character) for input handling.
    if (input.startsWith('O') &&
        input.length === 2 &&
        keypress.name &&
        keypress.name.length === 1) {
        input = keypress.name;
        processedAsSpecialSequence = true;
    }
    // Clear input for non-alphanumeric keys (arrows, function keys, etc.)
    // Skip this for CSI u and application keypad mode sequences since
    // those were already converted to their proper input characters.
    if (!processedAsSpecialSequence &&
        keypress.name &&
        nonAlphanumericKeys.includes(keypress.name)) {
        input = '';
    }
    // Set shift=true for uppercase letters (A-Z)
    // Must check it's actually a letter, not just any char unchanged by toUpperCase
    if (input.length === 1 &&
        typeof input[0] === 'string' &&
        input[0] >= 'A' &&
        input[0] <= 'Z') {
        key.shift = true;
    }
    return [key, input];
}
export class InputEvent extends Event {
    keypress;
    key;
    input;
    constructor(keypress) {
        super();
        const [key, input] = parseKey(keypress);
        this.keypress = keypress;
        this.key = key;
        this.input = input;
    }
}
//# sourceMappingURL=input-event.js.map