// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:io';

import 'package:path/path.dart' as path;

import 'base_code_gen.dart';
import 'data.dart';
import 'logical_key_data.dart';
import 'physical_key_data.dart';
import 'utils.dart';

bool _isAsciiLetter(String? char) {
  if (char == null) {
    return false;
  }
  const int charUpperA = 0x41;
  const int charUpperZ = 0x5A;
  const int charLowerA = 0x61;
  const int charLowerZ = 0x7A;
  assert(char.length == 1);
  final int charCode = char.codeUnitAt(0);
  return (charCode >= charUpperA && charCode <= charUpperZ)
      || (charCode >= charLowerA && charCode <= charLowerZ);
}

bool _isDigit(String? char) {
  if (char == null) {
    return false;
  }
  final int charDigit0 = '0'.codeUnitAt(0);
  final int charDigit9 = '9'.codeUnitAt(0);
  assert(char.length == 1);
  final int charCode = char.codeUnitAt(0);
  return charCode >= charDigit0 && charCode <= charDigit9;
}

/// Generates the keyboard_maps.g.dart files, based on the information in the key
/// data structure given to it.
class KeyboardMapsCodeGenerator extends BaseCodeGenerator {
  KeyboardMapsCodeGenerator(super.keyData, super.logicalData);

  List<PhysicalKeyEntry> get _numpadKeyData {
    return keyData.entries.where((PhysicalKeyEntry entry) {
      return entry.constantName.startsWith('numpad') && LogicalKeyData.printable.containsKey(entry.name);
    }).toList();
  }

  List<PhysicalKeyEntry> get _functionKeyData {
    final RegExp functionKeyRe = RegExp(r'^f[0-9]+$');
    return keyData.entries.where((PhysicalKeyEntry entry) {
      return functionKeyRe.hasMatch(entry.constantName);
    }).toList();
  }

  List<LogicalKeyEntry> get _numpadLogicalKeyData {
    return logicalData.entries.where((LogicalKeyEntry entry) {
      return entry.constantName.startsWith('numpad') && LogicalKeyData.printable.containsKey(entry.name);
    }).toList();
  }

  /// This generates the map of GLFW number pad key codes to logical keys.
  String get _glfwNumpadMap {
    final OutputLines<int> lines = OutputLines<int>('GLFW numpad map');
    for (final PhysicalKeyEntry entry in _numpadKeyData) {
      final LogicalKeyEntry logicalKey = logicalData.entryByName(entry.name);
      for (final int code in logicalKey.glfwValues) {
        lines.add(code, '  $code: LogicalKeyboardKey.${entry.constantName},');
      }
    }
    return lines.sortedJoin().trimRight();
  }

  /// This generates the map of GLFW key codes to logical keys.
  String get _glfwKeyCodeMap {
    final OutputLines<int> lines = OutputLines<int>('GLFW key code map');
    for (final LogicalKeyEntry entry in logicalData.entries) {
      for (final int value in entry.glfwValues) {
        lines.add(value, '  $value: LogicalKeyboardKey.${entry.constantName},');
      }
    }
    return lines.sortedJoin().trimRight();
  }

  /// This generates the map of GTK number pad key codes to logical keys.
  String get _gtkNumpadMap {
    final OutputLines<int> lines = OutputLines<int>('GTK numpad map');
    for (final LogicalKeyEntry entry in _numpadLogicalKeyData) {
      for (final int code in entry.gtkValues) {
        lines.add(code, '  $code: LogicalKeyboardKey.${entry.constantName},');
      }
    }
    return lines.sortedJoin().trimRight();
  }

  /// This generates the map of GTK key codes to logical keys.
  String get _gtkKeyCodeMap {
    final OutputLines<int> lines = OutputLines<int>('GTK key code map');
    for (final LogicalKeyEntry entry in logicalData.entries) {
      for (final int code in entry.gtkValues) {
        lines.add(code, '  $code: LogicalKeyboardKey.${entry.constantName},');
      }
    }
    return lines.sortedJoin().trimRight();
  }

  /// This generates the map of XKB USB HID codes to physical keys.
  String get _xkbScanCodeMap {
    final OutputLines<int> lines = OutputLines<int>('GTK scancode map');
    for (final PhysicalKeyEntry entry in keyData.entries) {
      if (entry.xKbScanCode != null) {
        lines.add(entry.xKbScanCode!,
            '  ${toHex(entry.xKbScanCode)}: PhysicalKeyboardKey.${entry.constantName},');
      }
    }
    return lines.sortedJoin().trimRight();
  }

  /// This generates the map of Android key codes to logical keys.
  String get _androidKeyCodeMap {
    final OutputLines<int> lines = OutputLines<int>('Android key code map');
    for (final LogicalKeyEntry entry in logicalData.entries) {
      for (final int code in entry.androidValues) {
        lines.add(code, '  $code: LogicalKeyboardKey.${entry.constantName},');
      }
    }
    return lines.sortedJoin().trimRight();
  }

  /// This generates the map of Android number pad key codes to logical keys.
  String get _androidNumpadMap {
    final OutputLines<int> lines = OutputLines<int>('Android numpad map');
    for (final LogicalKeyEntry entry in _numpadLogicalKeyData) {
      for (final int code in entry.androidValues) {
        lines.add(code, '  $code: LogicalKeyboardKey.${entry.constantName},');
      }
    }
    return lines.sortedJoin().trimRight();
  }

  /// This generates the map of Android scan codes to physical keys.
  String get _androidScanCodeMap {
    final OutputLines<int> lines = OutputLines<int>('Android scancode map');
    for (final PhysicalKeyEntry entry in keyData.entries) {
      for (final int code in entry.androidScanCodes) {
        lines.add(code, '  $code: PhysicalKeyboardKey.${entry.constantName},');
      }
    }
    return lines.sortedJoin().trimRight();
  }

  /// This generates the map of Windows scan codes to physical keys.
  String get _windowsScanCodeMap {
    final OutputLines<int> lines = OutputLines<int>('Windows scancode map');
    for (final PhysicalKeyEntry entry in keyData.entries) {
      if (entry.windowsScanCode != null) {
        lines.add(entry.windowsScanCode!, '  ${entry.windowsScanCode}: PhysicalKeyboardKey.${entry.constantName},');
      }
    }
    return lines.sortedJoin().trimRight();
  }

  /// This generates the map of Windows number pad key codes to logical keys.
  String get _windowsNumpadMap {
    final OutputLines<int> lines = OutputLines<int>('Windows numpad map');
    for (final LogicalKeyEntry entry in _numpadLogicalKeyData) {
      for (final int code in entry.windowsValues) {
        lines.add(code, '  $code: LogicalKeyboardKey.${entry.constantName},');
      }
    }
    return lines.sortedJoin().trimRight();
  }

  /// This generates the map of Windows key codes to logical keys.
  String get _windowsKeyCodeMap {
    final OutputLines<int> lines = OutputLines<int>('Windows key code map');
    for (final LogicalKeyEntry entry in logicalData.entries) {
      // Letter keys on Windows are not recorded in logical_key_data.g.json,
      // because they are not used by the embedding. Add them manually.
      final List<int>? keyCodes = entry.windowsValues.isNotEmpty
        ? entry.windowsValues
        : (_isAsciiLetter(entry.keyLabel) ? <int>[entry.keyLabel!.toUpperCase().codeUnitAt(0)] :
           _isDigit(entry.keyLabel)       ? <int>[entry.keyLabel!.toUpperCase().codeUnitAt(0)] :
           null);
      if (keyCodes != null) {
        for (final int code in keyCodes) {
          lines.add(code, '  $code: LogicalKeyboardKey.${entry.constantName},');
        }
      }
    }
    return lines.sortedJoin().trimRight();
  }

  /// This generates the map of macOS key codes to physical keys.
  String get _macOSScanCodeMap {
    final OutputLines<int> lines = OutputLines<int>('macOS scancode map');
    for (final PhysicalKeyEntry entry in keyData.entries) {
      if (entry.macOSScanCode != null) {
        lines.add(entry.macOSScanCode!, '  ${toHex(entry.macOSScanCode)}: PhysicalKeyboardKey.${entry.constantName},');
      }
    }
    return lines.sortedJoin().trimRight();
  }

  /// This generates the map of macOS number pad key codes to logical keys.
  String get _macOSNumpadMap {
    final OutputLines<int> lines = OutputLines<int>('macOS numpad map');
    for (final PhysicalKeyEntry entry in _numpadKeyData) {
      if (entry.macOSScanCode != null) {
        lines.add(entry.macOSScanCode!, '  ${toHex(entry.macOSScanCode)}: LogicalKeyboardKey.${entry.constantName},');
      }
    }
    return lines.sortedJoin().trimRight();
  }

  String get _macOSFunctionKeyMap {
    final OutputLines<int> lines = OutputLines<int>('macOS function key map');
    for (final PhysicalKeyEntry entry in _functionKeyData) {
      if (entry.macOSScanCode != null) {
        lines.add(entry.macOSScanCode!, '  ${toHex(entry.macOSScanCode)}: LogicalKeyboardKey.${entry.constantName},');
      }
    }
    return lines.sortedJoin().trimRight();
  }

  /// This generates the map of macOS key codes to physical keys.
  String get _macOSKeyCodeMap {
    final OutputLines<int> lines = OutputLines<int>('MacOS key code map');
    for (final LogicalKeyEntry entry in logicalData.entries) {
      for (final int code in entry.macOSKeyCodeValues) {
        lines.add(code, '  $code: LogicalKeyboardKey.${entry.constantName},');
      }
    }
    return lines.sortedJoin().trimRight();
  }

  /// This generates the map of iOS key codes to physical keys.
  String get _iOSScanCodeMap {
    final OutputLines<int> lines = OutputLines<int>('iOS scancode map');
    for (final PhysicalKeyEntry entry in keyData.entries) {
      if (entry.iOSScanCode != null) {
        lines.add(entry.iOSScanCode!, '  ${toHex(entry.iOSScanCode)}: PhysicalKeyboardKey.${entry.constantName},');
      }
    }
    return lines.sortedJoin().trimRight();
  }

  /// This generates the map of iOS key label to logical keys for special keys.
  String get _iOSSpecialMap {
    final OutputLines<int> lines = OutputLines<int>('iOS special key mapping');
    kIosSpecialKeyMapping.forEach((String key, String logicalName) {
      final LogicalKeyEntry entry = logicalData.entryByName(logicalName);
      lines.add(entry.value, "  '$key': LogicalKeyboardKey.${entry.constantName},");
    });
    return lines.join().trimRight();
  }

  /// This generates the map of iOS number pad key codes to logical keys.
  String get _iOSNumpadMap {
    final OutputLines<int> lines = OutputLines<int>('iOS numpad map');
    for (final PhysicalKeyEntry entry in _numpadKeyData) {
      if (entry.iOSScanCode != null) {
        lines.add(entry.iOSScanCode!,'  ${toHex(entry.iOSScanCode)}: LogicalKeyboardKey.${entry.constantName},');
      }
    }
    return lines.sortedJoin().trimRight();
  }

  /// This generates the map of macOS key codes to physical keys.
  String get _iOSKeyCodeMap {
    final OutputLines<int> lines = OutputLines<int>('iOS key code map');
    for (final LogicalKeyEntry entry in logicalData.entries) {
      for (final int code in entry.iOSKeyCodeValues) {
        lines.add(code, '  $code: LogicalKeyboardKey.${entry.constantName},');
      }
    }
    return lines.sortedJoin().trimRight();
  }

  /// This generates the map of Fuchsia key codes to logical keys.
  String get _fuchsiaKeyCodeMap {
    final OutputLines<int> lines = OutputLines<int>('Fuchsia key code map');
    for (final LogicalKeyEntry entry in logicalData.entries) {
      for (final int value in entry.fuchsiaValues) {
        lines.add(value, '  ${toHex(value)}: LogicalKeyboardKey.${entry.constantName},');
      }
    }
    return lines.sortedJoin().trimRight();
  }

  /// This generates the map of Fuchsia USB HID codes to physical keys.
  String get _fuchsiaHidCodeMap {
    final StringBuffer fuchsiaScanCodeMap = StringBuffer();
    for (final PhysicalKeyEntry entry in keyData.entries) {
      fuchsiaScanCodeMap.writeln('  ${toHex(entry.usbHidCode)}: PhysicalKeyboardKey.${entry.constantName},');
    }
    return fuchsiaScanCodeMap.toString().trimRight();
  }

  /// This generates the map of Web KeyboardEvent codes to logical keys.
  String get _webLogicalKeyMap {
    final OutputLines<String> lines = OutputLines<String>('Web logical key map');
    for (final LogicalKeyEntry entry in logicalData.entries) {
      for (final String name in entry.webNames) {
        lines.add(name, "  '$name': LogicalKeyboardKey.${entry.constantName},");
      }
    }
    return lines.sortedJoin().trimRight();
  }

  /// This generates the map of Web KeyboardEvent codes to physical keys.
  String get _webPhysicalKeyMap {
    final OutputLines<String> lines = OutputLines<String>('Web physical key map', behavior: DeduplicateBehavior.kKeep);
    for (final PhysicalKeyEntry entry in keyData.entries) {
      for (final String webCodes in entry.webCodes()) {
        lines.add(entry.name, "  '$webCodes': PhysicalKeyboardKey.${entry.constantName},");
      }
    }
    return lines.sortedJoin().trimRight();
  }

  String get _webNumpadMap {
    final OutputLines<String> lines = OutputLines<String>('Web numpad map');
    for (final LogicalKeyEntry entry in _numpadLogicalKeyData) {
      lines.add(entry.name, "  '${entry.name}': LogicalKeyboardKey.${entry.constantName},");
    }
    return lines.sortedJoin().trimRight();
  }

  /// This generates the map of Web number pad codes to logical keys.
  String get _webLocationMap {
    final String jsonRaw = File(path.join(dataRoot, 'web_logical_location_mapping.json')).readAsStringSync();
    final Map<String, List<String?>> locationMap = parseMapOfListOfNullableString(jsonRaw);
    final OutputLines<String> lines = OutputLines<String>('Web location map');
    locationMap.forEach((String key, List<String?> keyNames) {
      final String keyStrings = keyNames.map((String? keyName) {
        final String? constantName = keyName == null ? null : logicalData.entryByName(keyName).constantName;
        return constantName != null ? 'LogicalKeyboardKey.$constantName' : 'null';
      }).join(', ');
      lines.add(key, "  '$key': <LogicalKeyboardKey?>[$keyStrings],");
    });
    return lines.sortedJoin().trimRight();
  }

  @override
  String get templatePath => path.join(dataRoot, 'keyboard_maps.tmpl');

  @override
  Map<String, String> mappings() {
    return <String, String>{
      'ANDROID_SCAN_CODE_MAP': _androidScanCodeMap,
      'ANDROID_KEY_CODE_MAP': _androidKeyCodeMap,
      'ANDROID_NUMPAD_MAP': _androidNumpadMap,
      'FUCHSIA_SCAN_CODE_MAP': _fuchsiaHidCodeMap,
      'FUCHSIA_KEY_CODE_MAP': _fuchsiaKeyCodeMap,
      'MACOS_SCAN_CODE_MAP': _macOSScanCodeMap,
      'MACOS_NUMPAD_MAP': _macOSNumpadMap,
      'MACOS_FUNCTION_KEY_MAP': _macOSFunctionKeyMap,
      'MACOS_KEY_CODE_MAP': _macOSKeyCodeMap,
      'IOS_SCAN_CODE_MAP': _iOSScanCodeMap,
      'IOS_SPECIAL_MAP': _iOSSpecialMap,
      'IOS_NUMPAD_MAP': _iOSNumpadMap,
      'IOS_KEY_CODE_MAP': _iOSKeyCodeMap,
      'GLFW_KEY_CODE_MAP': _glfwKeyCodeMap,
      'GLFW_NUMPAD_MAP': _glfwNumpadMap,
      'GTK_KEY_CODE_MAP': _gtkKeyCodeMap,
      'GTK_NUMPAD_MAP': _gtkNumpadMap,
      'XKB_SCAN_CODE_MAP': _xkbScanCodeMap,
      'WEB_LOGICAL_KEY_MAP': _webLogicalKeyMap,
      'WEB_PHYSICAL_KEY_MAP': _webPhysicalKeyMap,
      'WEB_NUMPAD_MAP': _webNumpadMap,
      'WEB_LOCATION_MAP': _webLocationMap,
      'WINDOWS_LOGICAL_KEY_MAP': _windowsKeyCodeMap,
      'WINDOWS_PHYSICAL_KEY_MAP': _windowsScanCodeMap,
      'WINDOWS_NUMPAD_MAP': _windowsNumpadMap,
    };
  }
}
