import { macVkToKeyboardSvgKeyId } from './macos-vk-to-keyboard-svg-id';

export type KeyboardVkScheme = 'windows' | 'macos';

export function normalizeVirtualKey(vk: number): number {
  if (vk >= 0x61 && vk <= 0x7a) {
    return vk - 0x20;
  }
  return vk;
}

function buildDigitMap(): Map<number, string> {
  const ids = ['K_kb2k', 'K_kb2b', 'K_kb2c', 'K_kb2d', 'K_kb2e', 'K_kb2f', 'K_kb2g', 'K_kb2h', 'K_kb2i', 'K_kb2j'];
  const m = new Map<number, string>();
  for (let d = 0; d <= 9; d++) {
    m.set(0x30 + d, ids[d]!);
  }
  return m;
}

const DIGIT_TO_ID = buildDigitMap();

const LETTER_TO_ID: Record<string, string> = {
  A: 'K_kb4c',
  B: 'K_kb5g',
  C: 'K_kb5e',
  D: 'K_kb4e',
  E: 'K_kb3d',
  F: 'K_kb4f',
  G: 'K_kb4g',
  H: 'K_kb4h',
  I: 'K_kb3i',
  J: 'K_kb4i',
  K: 'K_kb4j',
  L: 'K_kb4k',
  M: 'K_kb5i',
  N: 'K_kb5h',
  O: 'K_kb3j',
  P: 'K_kb3k',
  Q: 'K_kb3b',
  R: 'K_kb3e',
  S: 'K_kb4d',
  T: 'K_kb3f',
  U: 'K_kb3h',
  V: 'K_kb5f',
  W: 'K_kb3c',
  X: 'K_kb5d',
  Y: 'K_kb3g',
  Z: 'K_kb5c',
};

/** Символы пунктуации и shifted-варианты цифр → физическая клавиша SVG. */
const PUNCT_CHAR_TO_ID: Record<string, string> = {
  // Ряд цифр (shifted)
  '!': 'K_kb2b', '@': 'K_kb2c', '#': 'K_kb2d', '$': 'K_kb2e',
  '%': 'K_kb2f', '^': 'K_kb2g', '&': 'K_kb2h', '*': 'K_kb2i',
  '(': 'K_kb2j', ')': 'K_kb2k',
  // Правый край ряда цифр
  '-': 'K_kb2l', '_': 'K_kb2l',
  '=': 'K_kb2m', '+': 'K_kb2m',
  '`': 'K_kb2a', '~': 'K_kb2a',
  // Q-ряд, правый край
  '[': 'K_kb3l', '{': 'K_kb3l',
  ']': 'K_kb3m', '}': 'K_kb3m',
  '\\': 'K_kb3n', '|': 'K_kb3n',
  // A-ряд, правый край
  ';': 'K_kb4l', ':': 'K_kb4l',
  "'": 'K_kb4m', '"': 'K_kb4m',
  // Z-ряд, правый край
  ',': 'K_kb5j', '<': 'K_kb5j',
  '.': 'K_kb5k', '>': 'K_kb5k',
  '/': 'K_kb5l', '?': 'K_kb5l',
};

const RU_CHAR_TO_ID: Record<string, string> = {
  ё: 'K_kb2a',
  й: 'K_kb3b',
  ц: 'K_kb3c',
  у: 'K_kb3d',
  к: 'K_kb3e',
  е: 'K_kb3f',
  н: 'K_kb3g',
  г: 'K_kb3h',
  ш: 'K_kb3i',
  щ: 'K_kb3j',
  з: 'K_kb3k',
  х: 'K_kb3l',
  ъ: 'K_kb3m',
  ф: 'K_kb4c',
  ы: 'K_kb4d',
  в: 'K_kb4e',
  а: 'K_kb4f',
  п: 'K_kb4g',
  р: 'K_kb4h',
  о: 'K_kb4i',
  л: 'K_kb4j',
  д: 'K_kb4k',
  ж: 'K_kb4l',
  э: 'K_kb4m',
  я: 'K_kb5c',
  ч: 'K_kb5d',
  с: 'K_kb5e',
  м: 'K_kb5f',
  и: 'K_kb5g',
  т: 'K_kb5h',
  ь: 'K_kb5i',
  б: 'K_kb5j',
  ю: 'K_kb5k',
  /** ЙЦУКЕН, верхний ряд (Windows) */
  '№': 'K_kb2d',
};

const EXTRA_VK: Record<number, string> = {
  0x08: 'K_kb2n',
  0x09: 'K_kb3a',
  0x0d: 'K_kb4n',
  /** Windows VK_LEFT / UP / RIGHT / DOWN — отдельный блок стрелок в UI */
  0x25: 'K_kb7l',
  0x26: 'K_kb7u',
  0x27: 'K_kb7r',
  0x28: 'K_kb7d',
  0x10: 'K_kb5a',
  0x11: 'K_kb6a',
  0x12: 'K_kb6c',
  0x14: 'K_kb4a',
  0x20: 'K_kb6d',
  0x5b: 'K_kb6b',
  0x5c: 'K_kb6l',
  0x5d: 'K_kb6m',
  0xa0: 'K_kb5a',
  0xa1: 'K_kb5m',
  0xa2: 'K_kb6a',
  0xa3: 'K_kb6n',
  0xa4: 'K_kb6c',
  0xa5: 'K_kb6k',
  0xba: 'K_kb4l',
  0xbb: 'K_kb2m',
  0xbc: 'K_kb5j',
  0xbd: 'K_kb2l',
  0xbe: 'K_kb5k',
  0xbf: 'K_kb5l',
  0xc0: 'K_kb2a',
  0xdb: 'K_kb3l',
  0xdc: 'K_kb3n',
  0xdd: 'K_kb3m',
  0xde: 'K_kb4m',
};

function windowsVkToKeyboardSvgKeyId(vk: number): string | null {
  const k = normalizeVirtualKey(vk);
  const fromExtra = EXTRA_VK[k];
  if (fromExtra) {
    return fromExtra;
  }
  const digit = DIGIT_TO_ID.get(k);
  if (digit) {
    return digit;
  }
  if (k >= 0x41 && k <= 0x5a) {
    const ch = String.fromCharCode(k);
    return LETTER_TO_ID[ch] ?? null;
  }
  return null;
}

/**
 * @param vk — Windows virtual-key (по умолчанию) либо macOS kVK при `scheme: 'macos'`.
 */
export function vkToKeyboardSvgKeyId(vk: number, scheme: KeyboardVkScheme = 'windows'): string | null {
  if (scheme === 'macos') {
    return macVkToKeyboardSvgKeyId(vk);
  }
  return windowsVkToKeyboardSvgKeyId(vk);
}

export function charKeyNameToSvgKeyId(name: string): string | null {
  const c = name.trim();
  if (c.length !== 1) {
    return null;
  }
  if (c >= '0' && c <= '9') {
    return DIGIT_TO_ID.get(c.charCodeAt(0)) ?? null;
  }
  const ch = c.toUpperCase();
  if (ch >= 'A' && ch <= 'Z') {
    return LETTER_TO_ID[ch] ?? null;
  }
  const ru = c.toLowerCase();
  if (ru in RU_CHAR_TO_ID) {
    return RU_CHAR_TO_ID[ru] ?? null;
  }
  if (c in PUNCT_CHAR_TO_ID) {
    return PUNCT_CHAR_TO_ID[c] ?? null;
  }
  return null;
}

/** US QWERTY без Shift по физическому id клавиши (эвристика для восстановления текста). */
const SVG_ID_TO_US_UNSHIFTED_CHAR: Record<string, string> = (() => {
  const m: Record<string, string> = {
    K_kb3a: '\t',
    K_kb4n: '\n',
    K_kb6d: ' ',
    K_kb2a: '`',
    K_kb2l: '-',
    K_kb2m: '=',
    K_kb3l: '[',
    K_kb3m: ']',
    K_kb3n: '\\',
    K_kb4l: ';',
    K_kb4m: "'",
    K_kb5j: ',',
    K_kb5k: '.',
    K_kb5l: '/',
  };
  for (const [letter, id] of Object.entries(LETTER_TO_ID)) {
    m[id] = letter.toLowerCase();
  }
  DIGIT_TO_ID.forEach((id, code) => {
    m[id] = String.fromCharCode(code);
  });
  return m;
})();

export function svgKeyboardKeyIdToUsUnshiftedChar(id: string): string | null {
  const c = SVG_ID_TO_US_UNSHIFTED_CHAR[id];
  return c ?? null;
}
