// 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 'package:flutter/foundation.dart';

export 'package:flutter/foundation.dart' show DiagnosticPropertiesBuilder;

// DO NOT EDIT -- DO NOT EDIT -- DO NOT EDIT
// This file is generated by dev/tools/gen_keycodes/bin/gen_keycodes.dart and
// should not be edited directly.
//
// Edit the template dev/tools/gen_keycodes/data/keyboard_key.tmpl instead.
// See dev/tools/gen_keycodes/README.md for more information.

/// A base class for all keyboard key types.
///
/// See also:
///
///  * [PhysicalKeyboardKey], a class with static values that describe the keys
///    that are returned from [RawKeyEvent.physicalKey].
///  * [LogicalKeyboardKey], a class with static values that describe the keys
///    that are returned from [RawKeyEvent.logicalKey].
abstract class KeyboardKey with Diagnosticable {
  /// Abstract const constructor. This constructor enables subclasses to provide
  /// const constructors so that they can be used in const expressions.
  const KeyboardKey();
}

/// A class with static values that describe the keys that are returned from
/// [RawKeyEvent.logicalKey].
///
/// These represent *logical* keys, which are keys which are interpreted in the
/// context of any modifiers, modes, or keyboard layouts which may be in effect.
///
/// This is contrast to [PhysicalKeyboardKey], which represents a physical key
/// in a particular location on the keyboard, without regard for the modifier
/// state, mode, or keyboard layout.
///
/// As an example, if you wanted to implement an app where the "Q" key "quit"
/// something, you'd want to look at the logical key to detect this, since you
/// would like to have it match the key with "Q" on it, instead of always
/// looking for "the key next to the TAB key", since on a French keyboard,
/// the key next to the TAB key has an "A" on it.
///
/// Conversely, if you wanted a game where the key next to the CAPS LOCK (the
/// "A" key on a QWERTY keyboard) moved the player to the left, you'd want to
/// look at the physical key to make sure that regardless of the character the
/// key produces, you got the key that is in that location on the keyboard.
///
/// {@tool dartpad}
/// This example shows how to detect if the user has selected the logical "Q"
/// key and handle the key if they have.
///
/// ** See code in examples/api/lib/services/keyboard_key/logical_keyboard_key.0.dart **
/// {@end-tool}
/// See also:
///
///  * [RawKeyEvent], the keyboard event object received by widgets that listen
///    to keyboard events.
///  * [Focus.onKey], the handler on a widget that lets you handle key events.
///  * [RawKeyboardListener], a widget used to listen to keyboard events (but
///    not handle them).
@immutable
class LogicalKeyboardKey extends KeyboardKey {
  /// Creates a new LogicalKeyboardKey object for a key ID.
  const LogicalKeyboardKey(this.keyId);

  /// A unique code representing this key.
  ///
  /// This is an opaque code. It should not be unpacked to derive information
  /// from it, as the representation of the code could change at any time.
  final int keyId;

  // Returns the bits that are not included in [valueMask], shifted to the
  // right.
  //
  // For example, if the input is 0x12abcdabcd, then the result is 0x12.
  //
  // This is mostly equivalent to a right shift, resolving the problem that
  // JavaScript only support 32-bit bitwise operation and needs to use division
  // instead.
  static int _nonValueBits(int n) {
    // `n >> valueMaskWidth` is equivalent to `n / divisorForValueMask`.
    const int divisorForValueMask = valueMask + 1;
    const int valueMaskWidth = 32;

    // Equivalent to assert(divisorForValueMask == (1 << valueMaskWidth)).
    const int firstDivisorWidth = 28;
    assert(divisorForValueMask ==
      (1 << firstDivisorWidth) * (1 << (valueMaskWidth - firstDivisorWidth)));

    // JS only supports up to 2^53 - 1, therefore non-value bits can only
    // contain (maxSafeIntegerWidth - valueMaskWidth) bits.
    const int maxSafeIntegerWidth = 52;
    const int nonValueMask = (1 << (maxSafeIntegerWidth - valueMaskWidth)) - 1;

    if (kIsWeb) {
      return (n / divisorForValueMask).floor() & nonValueMask;
    } else {
      return (n >> valueMaskWidth) & nonValueMask;
    }
  }

  static String? _unicodeKeyLabel(int keyId) {
    if (_nonValueBits(keyId) == 0) {
      return String.fromCharCode(keyId).toUpperCase();
    }
    return null;
  }

  /// A description representing the character produced by a [RawKeyEvent].
  ///
  /// This value is useful for providing readable strings for keys or keyboard
  /// shortcuts. Do not use this value to compare equality of keys; compare
  /// [keyId] instead.
  ///
  /// For printable keys, this is usually the printable character in upper case
  /// ignoring modifiers or combining keys, such as 'A', '1', or '/'. This
  /// might also return accented letters (such as 'Ù') for keys labeled as so,
  /// but not if such character is a result from preceding combining keys ('`̀'
  /// followed by key U).
  ///
  /// For other keys, [keyLabel] looks up the full key name from a predefined
  /// map, such as 'F1', 'Shift Left', or 'Media Down'. This value is an empty
  /// string if there's no key label data for a key.
  ///
  /// For the printable representation that takes into consideration the
  /// modifiers and combining keys, see [RawKeyEvent.character].
  ///
  /// {@macro flutter.services.RawKeyEventData.keyLabel}
  String get keyLabel {
    return _unicodeKeyLabel(keyId)
        ?? _keyLabels[keyId]
        ?? '';
  }

  /// The debug string to print for this keyboard key, which will be null in
  /// release mode.
  ///
  /// For printable keys, this is usually a more descriptive name related to
  /// [keyLabel], such as 'Key A', 'Digit 1', 'Backslash'. This might
  /// also return accented letters (such as 'Key Ù') for keys labeled as so.
  ///
  /// For other keys, this looks up the full key name from a predefined map (the
  /// same value as [keyLabel]), such as 'F1', 'Shift Left', or 'Media Down'. If
  /// there's no key label data for a key, this returns a name that explains the
  /// ID (such as 'Key with ID 0x00100012345').
  String? get debugName {
    String? result;
    assert(() {
      result = _keyLabels[keyId];
      if (result == null) {
        final String? unicodeKeyLabel = _unicodeKeyLabel(keyId);
        if (unicodeKeyLabel != null) {
          result = 'Key $unicodeKeyLabel';
        } else {
          result = 'Key with ID 0x${keyId.toRadixString(16).padLeft(11, '0')}';
        }
      }
      return true;
    }());
    return result;
  }

  @override
  int get hashCode => keyId.hashCode;

  @override
  bool operator ==(Object other) {
    if (identical(this, other)) {
      return true;
    }
    if (other.runtimeType != runtimeType) {
      return false;
    }
    return other is LogicalKeyboardKey
        && other.keyId == keyId;
  }

  /// Returns the [LogicalKeyboardKey] constant that matches the given ID, or
  /// null, if not found.
  static LogicalKeyboardKey? findKeyByKeyId(int keyId) => _knownLogicalKeys[keyId];

  /// Returns true if the given label represents a Unicode control character.
  ///
  /// Examples of control characters are characters like "U+000A LINE FEED (LF)"
  /// or "U+001B ESCAPE (ESC)".
  ///
  /// See <https://en.wikipedia.org/wiki/Unicode_control_characters> for more
  /// information.
  ///
  /// Used by [RawKeyEvent] subclasses to help construct IDs.
  static bool isControlCharacter(String label) {
    if (label.length != 1) {
      return false;
    }
    final int codeUnit = label.codeUnitAt(0);
    return (codeUnit <= 0x1f && codeUnit >= 0x00) || (codeUnit >= 0x7f && codeUnit <= 0x9f);
  }

  /// Returns true if the [keyId] of this object is one that is auto-generated by
  /// Flutter.
  ///
  /// Auto-generated key IDs are generated in response to platform key codes
  /// which Flutter doesn't recognize, and their IDs shouldn't be used in a
  /// persistent way.
  ///
  /// Auto-generated IDs should be a rare occurrence: Flutter supports most keys.
  ///
  /// Keys that generate Unicode characters (even if unknown to Flutter) will
  /// not return true for `isAutogenerated`, since they will be assigned a
  /// Unicode-based code that will remain stable.
  ///
  /// If Flutter adds support for a previously unsupported key code, the ID it
  /// reports will change, but the ID will remain stable on the platform it is
  /// produced on until Flutter adds support for recognizing it.
  ///
  /// So, hypothetically, if Android added a new key code of 0xffff,
  /// representing a new "do what I mean" key, then the auto-generated code
  /// would be 0x1020000ffff, but once Flutter added the "doWhatIMean" key to
  /// the definitions below, the new code would be 0x0020000ffff for all
  /// platforms that had a "do what I mean" key from then on.
  bool get isAutogenerated => (keyId & planeMask) >= startOfPlatformPlanes;

  /// Returns a set of pseudo-key synonyms for the given `key`.
  ///
  /// This allows finding the pseudo-keys that also represents a concrete
  /// `key` so that a class with a key map can match pseudo-keys as well as the
  /// actual generated keys.
  ///
  /// The pseudo-keys returned in the set are typically used to represent keys
  /// which appear in multiple places on the keyboard, such as the [shift],
  /// [alt], [control], and [meta] keys. The keys in the returned set won't ever
  /// be generated directly, but if a more specific key event is received, then
  /// this set can be used to find the more general pseudo-key. For example, if
  /// this is a [shiftLeft] key, this accessor will return the set
  /// `<LogicalKeyboardKey>{ shift }`.
  Set<LogicalKeyboardKey> get synonyms {
    final LogicalKeyboardKey? result = _synonyms[this];
    return result == null ? <LogicalKeyboardKey>{} : <LogicalKeyboardKey>{result};
  }

  /// Takes a set of keys, and returns the same set, but with any keys that have
  /// synonyms replaced.
  ///
  /// It is used, for example, to make sets of keys with members like
  /// [controlRight] and [controlLeft] and convert that set to contain just
  /// [control], so that the question "is any control key down?" can be asked.
  static Set<LogicalKeyboardKey> collapseSynonyms(Set<LogicalKeyboardKey> input) {
    final Set<LogicalKeyboardKey> result = <LogicalKeyboardKey>{};
    for (final LogicalKeyboardKey key in input) {
      final LogicalKeyboardKey? synonym = _synonyms[key];
      result.add(synonym ?? key);
    }
    return result;
  }

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(StringProperty('keyId', '0x${keyId.toRadixString(16).padLeft(8, '0')}'));
    properties.add(StringProperty('keyLabel', keyLabel));
    properties.add(StringProperty('debugName', debugName, defaultValue: null));
  }

@@@MASK_CONSTANTS@@@

@@@LOGICAL_KEY_DEFINITIONS@@@

  /// A list of all predefined constant [LogicalKeyboardKey]s.
  static Iterable<LogicalKeyboardKey> get knownLogicalKeys => _knownLogicalKeys.values;

  // A list of all predefined constant LogicalKeyboardKeys so they can be
  // searched.
  static const Map<int, LogicalKeyboardKey> _knownLogicalKeys = <int, LogicalKeyboardKey>{
@@@LOGICAL_KEY_MAP@@@
  };

  // A map of keys to the pseudo-key synonym for that key. Used by getSynonyms.
  static final Map<LogicalKeyboardKey, LogicalKeyboardKey> _synonyms = <LogicalKeyboardKey, LogicalKeyboardKey>{
@@@LOGICAL_KEY_SYNONYMS@@@  };

  static const Map<int, String> _keyLabels = <int, String>{
@@@LOGICAL_KEY_KEY_LABELS@@@
  };
}

/// A class with static values that describe the keys that are returned from
/// [RawKeyEvent.physicalKey].
///
/// These represent *physical* keys, which are keys which represent a particular
/// key location on a QWERTY keyboard. It ignores any modifiers, modes, or
/// keyboard layouts which may be in effect. This is contrast to
/// [LogicalKeyboardKey], which represents a logical key interpreted in the
/// context of modifiers, modes, and/or keyboard layouts.
///
/// As an example, if you wanted a game where the key next to the CAPS LOCK (the
/// "A" key on a QWERTY keyboard) moved the player to the left, you'd want to
/// look at the physical key to make sure that regardless of the character the
/// key produces, you got the key that is in that location on the keyboard.
///
/// Conversely, if you wanted to implement an app where the "Q" key "quit"
/// something, you'd want to look at the logical key to detect this, since you
/// would like to have it match the key with "Q" on it, instead of always
/// looking for "the key next to the TAB key", since on a French keyboard,
/// the key next to the TAB key has an "A" on it.
///
/// {@tool dartpad}
/// This example shows how to detect if the user has selected the physical key
/// to the right of the CAPS LOCK key.
///
/// ** See code in examples/api/lib/services/keyboard_key/physical_keyboard_key.0.dart **
/// {@end-tool}
///
/// See also:
///
///  * [RawKeyEvent], the keyboard event object received by widgets that listen
///    to keyboard events.
///  * [Focus.onKey], the handler on a widget that lets you handle key events.
///  * [RawKeyboardListener], a widget used to listen to keyboard events (but
///    not handle them).
@immutable
class PhysicalKeyboardKey extends KeyboardKey {
  /// Creates a new PhysicalKeyboardKey object for a USB HID usage.
  const PhysicalKeyboardKey(this.usbHidUsage);

  /// The unique USB HID usage ID of this physical key on the keyboard.
  ///
  /// Due to the variations in platform APIs, this may not be the actual HID
  /// usage code from the hardware, but a value derived from available
  /// information on the platform.
  ///
  /// See <https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf>
  /// for the HID usage values and their meanings.
  final int usbHidUsage;

  /// The debug string to print for this keyboard key, which will be null in
  /// release mode.
  String? get debugName {
    String? result;
    assert(() {
      result = _debugNames[usbHidUsage] ??
        'Key with ID 0x${usbHidUsage.toRadixString(16).padLeft(8, '0')}';
      return true;
    }());
    return result;
  }

  @override
  int get hashCode => usbHidUsage.hashCode;

  @override
  bool operator ==(Object other) {
    if (identical(this, other)) {
      return true;
    }
    if (other.runtimeType != runtimeType) {
      return false;
    }
    return other is PhysicalKeyboardKey
        && other.usbHidUsage == usbHidUsage;
  }

  /// Finds a known [PhysicalKeyboardKey] that matches the given USB HID usage
  /// code.
  static PhysicalKeyboardKey? findKeyByCode(int usageCode) => _knownPhysicalKeys[usageCode];

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(StringProperty('usbHidUsage', '0x${usbHidUsage.toRadixString(16).padLeft(8, '0')}'));
    properties.add(StringProperty('debugName', debugName, defaultValue: null));
  }

  // Key constants for all keyboard keys in the USB HID specification at the
  // time Flutter was built.

@@@PHYSICAL_KEY_DEFINITIONS@@@

  /// A list of all predefined constant [PhysicalKeyboardKey]s.
  static Iterable<PhysicalKeyboardKey> get knownPhysicalKeys => _knownPhysicalKeys.values;

  // A list of all the predefined constant PhysicalKeyboardKeys so that they
  // can be searched.
  static const Map<int, PhysicalKeyboardKey> _knownPhysicalKeys = <int, PhysicalKeyboardKey>{
@@@PHYSICAL_KEY_MAP@@@
  };

  static const Map<int, String> _debugNames = kReleaseMode ?
    <int, String>{} :
    <int, String>{
@@@PHYSICAL_KEY_DEBUG_NAMES@@@
    };
}
