/** biome-ignore-all lint/suspicious/noControlCharactersInRegex: intentional ESC/CSI pattern matching in kitty keyboard protocol */
// Kitty Keyboard Protocol parser
// Based on https://sw.kovidgoyal.net/kitty/keyboard-protocol/

const kittyKeyMap = {
  // Standard keys
  27: "escape",
  9: "tab",
  13: "return",
  127: "backspace",
  // Arrow keys
  57344: "escape",
  57345: "return",
  57346: "tab",
  57347: "backspace",
  57348: "insert",
  57349: "delete",
  57350: "left",
  57351: "right",
  57352: "up",
  57353: "down",
  57354: "pageup",
  57355: "pagedown",
  57356: "home",
  57357: "end",
  57358: "capslock",
  57359: "scrolllock",
  57360: "numlock",
  57361: "printscreen",
  57362: "pause",
  57363: "menu",
  // Function keys
  57364: "f1",
  57365: "f2",
  57366: "f3",
  57367: "f4",
  57368: "f5",
  57369: "f6",
  57370: "f7",
  57371: "f8",
  57372: "f9",
  57373: "f10",
  57374: "f11",
  57375: "f12",
  57376: "f13",
  57377: "f14",
  57378: "f15",
  57379: "f16",
  57380: "f17",
  57381: "f18",
  57382: "f19",
  57383: "f20",
  57384: "f21",
  57385: "f22",
  57386: "f23",
  57387: "f24",
  57388: "f25",
  57389: "f26",
  57390: "f27",
  57391: "f28",
  57392: "f29",
  57393: "f30",
  57394: "f31",
  57395: "f32",
  57396: "f33",
  57397: "f34",
  57398: "f35",
  // Keypad
  57399: "kp0",
  57400: "kp1",
  57401: "kp2",
  57402: "kp3",
  57403: "kp4",
  57404: "kp5",
  57405: "kp6",
  57406: "kp7",
  57407: "kp8",
  57408: "kp9",
  57409: "kpdecimal",
  57410: "kpdivide",
  57411: "kpmultiply",
  57412: "kpminus",
  57413: "kpplus",
  57414: "kpenter",
  57415: "kpequal",
  57416: "kpseparator",
  57417: "kpleft",
  57418: "kpright",
  57419: "kpup",
  57420: "kpdown",
  57421: "kppageup",
  57422: "kppagedown",
  57423: "kphome",
  57424: "kpend",
  57425: "kpinsert",
  57426: "kpdelete",
  57427: "clear",
  // Media keys
  57428: "mediaplay",
  57429: "mediapause",
  57430: "mediaplaypause",
  57431: "mediareverse",
  57432: "mediastop",
  57433: "mediafastforward",
  57434: "mediarewind",
  57435: "medianext",
  57436: "mediaprev",
  57437: "mediarecord",
  // Volume keys
  57438: "volumedown",
  57439: "volumeup",
  57440: "mute",
  // Modifiers
  57441: "leftshift",
  57442: "leftctrl",
  57443: "leftalt",
  57444: "leftsuper",
  57445: "lefthyper",
  57446: "leftmeta",
  57447: "rightshift",
  57448: "rightctrl",
  57449: "rightalt",
  57450: "rightsuper",
  57451: "righthyper",
  57452: "rightmeta",
  // Special
  57453: "iso_level3_shift",
  57454: "iso_level5_shift"
};
function fromKittyMods(mod) {
  return {
    shift: !!(mod & 1),
    alt: !!(mod & 2),
    ctrl: !!(mod & 4),
    super: !!(mod & 8),
    hyper: !!(mod & 16),
    meta: !!(mod & 32),
    capsLock: !!(mod & 64),
    numLock: !!(mod & 128)
  };
}

// Map functional key CSI codes to key names
const functionalKeyMap = {
  A: "up",
  B: "down",
  C: "right",
  D: "left",
  H: "home",
  F: "end",
  E: "clear",
  P: "f1",
  Q: "f2",
  S: "f4"
};

// Map tilde key numbers to key names (CSI number ~ format)
const tildeKeyMap = {
  "1": "home",
  "2": "insert",
  "3": "delete",
  "4": "end",
  "5": "pageup",
  "6": "pagedown",
  "7": "home",
  // rxvt
  "8": "end",
  // rxvt
  "11": "f1",
  "12": "f2",
  "13": "f3",
  "14": "f4",
  "15": "f5",
  "17": "f6",
  "18": "f7",
  "19": "f8",
  "20": "f9",
  "21": "f10",
  "23": "f11",
  "24": "f12",
  "29": "menu",
  "57427": "clear"
};

/**
 * Parse Kitty keyboard protocol special keys (functional and tilde) with event type
 * Formats:
 *   Functional: CSI 1;modifiers:event_type LETTER (e.g., \x1b[1;1:1A = up arrow press)
 *   Tilde: CSI number;modifiers:event_type ~ (e.g., \x1b[5;1:1~ = pageup press)
 */
const specialKeyRe = /^\x1b\[(\d+);(\d+):(\d+)([A-Z~])$/;
function parseKittySpecialKey(sequence) {
  const match = specialKeyRe.exec(sequence);
  if (!match) return null;
  const keyNumOrOne = match[1];
  const modifierStr = match[2];
  const eventTypeStr = match[3];
  const terminator = match[4];

  // Determine key name based on terminator
  let keyName;
  if (terminator === "~") {
    // Tilde key: lookup by number
    keyName = keyNumOrOne ? tildeKeyMap[keyNumOrOne] : undefined;
  } else {
    // Functional key: must have "1" as first param, lookup by letter
    if (keyNumOrOne !== "1") return null;
    keyName = terminator ? functionalKeyMap[terminator] : undefined;
  }
  if (!keyName) return null;
  const key = {
    name: keyName,
    ctrl: false,
    meta: false,
    shift: false,
    option: false,
    number: false,
    sequence,
    raw: sequence,
    eventType: "press",
    source: "kitty",
    super: false,
    hyper: false,
    capsLock: false,
    numLock: false
  };

  // Parse modifiers
  if (modifierStr) {
    const modifierMask = parseInt(modifierStr, 10);
    if (!Number.isNaN(modifierMask) && modifierMask > 1) {
      const mods = fromKittyMods(modifierMask - 1);
      key.shift = mods.shift;
      key.ctrl = mods.ctrl;
      key.meta = mods.alt || mods.meta;
      key.option = mods.alt;
      key.super = mods.super;
      key.hyper = mods.hyper;
      key.capsLock = mods.capsLock;
      key.numLock = mods.numLock;
    }
  }

  // Parse event type: 1 = press, 2 = repeat, 3 = release
  if (eventTypeStr === "1" || !eventTypeStr) {
    key.eventType = "press";
  } else if (eventTypeStr === "2") {
    key.eventType = "press";
    key.repeated = true;
  } else if (eventTypeStr === "3") {
    key.eventType = "release";
  }
  return key;
}
const kittyRe = /^\x1b\[([^\x1b]+)u$/;
export function parseKittyKeyboard(sequence) {
  // Try special key format (functional letters or tilde keys with event type)
  const specialResult = parseKittySpecialKey(sequence);
  if (specialResult) return specialResult;

  // Kitty keyboard protocol: CSI unicode-key-code:alternate-key-codes ; modifiers:event-type ; text-as-codepoints u
  const match = kittyRe.exec(sequence);
  if (!match) return null;
  const params = match[1];
  if (!params) return null;
  const fields = params.split(";");
  if (fields.length < 1) return null;
  const key = {
    name: "",
    ctrl: false,
    meta: false,
    shift: false,
    option: false,
    number: false,
    sequence,
    raw: sequence,
    eventType: "press",
    source: "kitty",
    super: false,
    hyper: false,
    capsLock: false,
    numLock: false
  };
  let text = "";

  // Parse field 1: unicode-key-code:shifted_codepoint:base_layout_codepoint
  const field1 = fields[0]?.split(":") || [];
  const codepointStr = field1[0];
  if (!codepointStr) return null;
  const codepoint = parseInt(codepointStr, 10);
  if (Number.isNaN(codepoint)) return null;
  let shiftedCodepoint;
  let baseCodepoint;

  // Parse shifted and base codepoints
  if (field1[1]) {
    const shifted = parseInt(field1[1], 10);
    if (!Number.isNaN(shifted) && shifted > 0 && shifted <= 0x10ffff) {
      shiftedCodepoint = shifted;
    }
  }
  if (field1[2]) {
    const base = parseInt(field1[2], 10);
    if (!Number.isNaN(base) && base > 0 && base <= 0x10ffff) {
      baseCodepoint = base;
    }
  }
  const knownKey = kittyKeyMap[codepoint];
  if (knownKey) {
    key.name = knownKey;
    key.code = `[${codepoint}u`;
  } else if (codepoint === 0) {
    key.name = "";
  } else {
    // It's a Unicode character
    if (codepoint > 0 && codepoint <= 0x10ffff) {
      const char = String.fromCodePoint(codepoint);
      key.name = char;

      // Store base layout codepoint for keyboard layout disambiguation
      if (baseCodepoint) {
        key.baseCode = baseCodepoint;
      }
    } else {
      return null; // Invalid codepoint
    }
  }

  // Parse field 2: modifier_mask:event_type
  if (fields[1]) {
    const field2 = fields[1].split(":");
    const modifierStr = field2[0];
    const eventTypeStr = field2[1];
    if (modifierStr) {
      const modifierMask = parseInt(modifierStr, 10);
      if (!Number.isNaN(modifierMask) && modifierMask > 1) {
        const mods = fromKittyMods(modifierMask - 1); // Kitty modifiers start from 1
        key.shift = mods.shift;
        key.ctrl = mods.ctrl;
        key.meta = mods.alt || mods.meta;
        key.option = mods.alt;
        key.super = mods.super;
        key.hyper = mods.hyper;
        key.capsLock = mods.capsLock;
        key.numLock = mods.numLock;
      }
    }

    // Parse event type: 1 = press (default), 2 = repeat, 3 = release
    if (eventTypeStr === "1" || !eventTypeStr) {
      key.eventType = "press";
    } else if (eventTypeStr === "2") {
      key.eventType = "press";
      key.repeated = true;
    } else if (eventTypeStr === "3") {
      key.eventType = "release";
    } else {
      key.eventType = "press";
    }
  }

  // Parse field 3: text_as_codepoint[:text_as_codepoint]
  if (fields[2]) {
    const codepoints = fields[2].split(":");
    for (const cpStr of codepoints) {
      const cp = parseInt(cpStr, 10);
      if (!Number.isNaN(cp) && cp > 0 && cp <= 0x10ffff) {
        text += String.fromCodePoint(cp);
      }
    }
  }

  // Handle text generation for printable characters
  if (text === "") {
    // Check if this is a printable character (not a key name like "up", "f1", etc.)
    const isPrintable = key.name.length > 0 && !kittyKeyMap[codepoint];
    if (isPrintable) {
      // Use shifted codepoint if shift is active and we have one
      if (key.shift && shiftedCodepoint) {
        text = String.fromCodePoint(shiftedCodepoint);
      } else if (key.shift && key.name.length === 1) {
        // When shift is pressed but terminal didn't provide shifted codepoint,
        // convert the character to uppercase (works for Unicode including Cyrillic)
        text = key.name.toLocaleUpperCase();
      } else {
        text = key.name;
      }
    }
  }

  // Special case: shift + space should produce a space
  if (key.name === " " && key.shift && !key.ctrl && !key.meta) {
    text = " ";
  }
  if (text) {
    if (codepoint === 0) {
      key.name = text;
    }
    key.sequence = text;
  }
  if (codepoint === 0 && text === "") {
    return null;
  }
  return key;
}
//# sourceMappingURL=parse-keypress-kitty.jsx.map
