// 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:ui' show hashValues;

import 'package:flutter/foundation.dart';

import 'keyboard_key.dart';
import 'keyboard_maps.dart';
import 'raw_keyboard.dart';

// Virtual key VK_PROCESSKEY in Win32 API.
//
// Key down events related to IME operations use this as keyCode.
const int _vkProcessKey = 0xe5;

/// Platform-specific key event data for Windows.
///
/// This object contains information about key events obtained from Windows's
/// win32 API.
///
/// See also:
///
///  * [RawKeyboard], which uses this interface to expose key data.
class RawKeyEventDataWindows extends RawKeyEventData {
  /// Creates a key event data structure specific for Windows.
  ///
  /// The [keyCode], [scanCode], [characterCodePoint], and [modifiers], arguments
  /// must not be null.
  const RawKeyEventDataWindows({
    this.keyCode = 0,
    this.scanCode = 0,
    this.characterCodePoint = 0,
    this.modifiers = 0,
  }) : assert(keyCode != null),
       assert(scanCode != null),
       assert(characterCodePoint != null),
       assert(modifiers != null);

  /// The hardware key code corresponding to this key event.
  ///
  /// This is the physical key that was pressed, not the Unicode character.
  /// See [characterCodePoint] for the Unicode character.
  final int keyCode;

  /// The hardware scan code id corresponding to this key event.
  ///
  /// These values are not reliable and vary from device to device, so this
  /// information is mainly useful for debugging.
  final int scanCode;

  /// The Unicode code point represented by the key event, if any.
  ///
  /// If there is no Unicode code point, this value is zero.
  final int characterCodePoint;

  /// A mask of the current modifiers. The modifier values must be in sync with
  /// the ones defined in https://github.com/flutter/engine/blob/master/shell/platform/windows/key_event_handler.cc
  final int modifiers;

  @override
  String get keyLabel => characterCodePoint == 0 ? '' : String.fromCharCode(characterCodePoint);

  @override
  PhysicalKeyboardKey get physicalKey => kWindowsToPhysicalKey[scanCode] ?? PhysicalKeyboardKey(LogicalKeyboardKey.windowsPlane + scanCode);

  @override
  LogicalKeyboardKey get logicalKey {
    // Look to see if the keyCode is a printable number pad key, so that a
    // difference between regular keys (e.g. "=") and the number pad version
    // (e.g. the "=" on the number pad) can be determined.
    final LogicalKeyboardKey? numPadKey = kWindowsNumPadMap[keyCode];
    if (numPadKey != null) {
      return numPadKey;
    }

    // If it has a non-control-character label, then either return the existing
    // constant, or construct a new Unicode-based key from it. Don't mark it as
    // autogenerated, since the label uniquely identifies an ID from the Unicode
    // plane.
    if (keyLabel.isNotEmpty && !LogicalKeyboardKey.isControlCharacter(keyLabel)) {
      final int keyId = LogicalKeyboardKey.unicodePlane | (characterCodePoint & LogicalKeyboardKey.valueMask);
      return LogicalKeyboardKey.findKeyByKeyId(keyId) ?? LogicalKeyboardKey(keyId);
    }
    // Look to see if the keyCode is one we know about and have a mapping for.
    final LogicalKeyboardKey? newKey = kWindowsToLogicalKey[keyCode];
    if (newKey != null) {
      return newKey;
    }

    // This is a non-printable key that we don't know about, so we mint a new
    // code.
    return LogicalKeyboardKey(keyCode | LogicalKeyboardKey.windowsPlane);
  }

  bool _isLeftRightModifierPressed(KeyboardSide side, int anyMask, int leftMask, int rightMask) {
    if (modifiers & anyMask == 0 &&
        modifiers & leftMask == 0 &&
        modifiers & rightMask == 0) {
      return false;
    }
    // If only the "anyMask" bit is set, then we respond true for requests of
    // whether either left or right is pressed. Handles the case where Windows
    // supplies just the "either" modifier flag, but not the left/right flag.
    // (e.g. modifierShift but not modifierLeftShift).
    final bool anyOnly = modifiers & (leftMask | rightMask | anyMask) == anyMask;
    switch (side) {
      case KeyboardSide.any:
        return true;
      case KeyboardSide.all:
        return modifiers & leftMask != 0 && modifiers & rightMask != 0 || anyOnly;
      case KeyboardSide.left:
        return modifiers & leftMask != 0 || anyOnly;
      case KeyboardSide.right:
        return modifiers & rightMask != 0 || anyOnly;
    }
  }

  @override
  bool isModifierPressed(ModifierKey key, {KeyboardSide side = KeyboardSide.any}) {
    final bool result;
    switch (key) {
      case ModifierKey.controlModifier:
        result = _isLeftRightModifierPressed(side, modifierControl, modifierLeftControl, modifierRightControl);
        break;
      case ModifierKey.shiftModifier:
        result = _isLeftRightModifierPressed(side, modifierShift, modifierLeftShift, modifierRightShift);
        break;
      case ModifierKey.altModifier:
        result = _isLeftRightModifierPressed(side, modifierAlt, modifierLeftAlt, modifierRightAlt);
        break;
      case ModifierKey.metaModifier:
        // Windows does not provide an "any" key for win key press.
        result = _isLeftRightModifierPressed(side, modifierLeftMeta | modifierRightMeta , modifierLeftMeta, modifierRightMeta);
        break;
      case ModifierKey.capsLockModifier:
        result = modifiers & modifierCaps != 0;
        break;
      case ModifierKey.scrollLockModifier:
        result = modifiers & modifierScrollLock != 0;
        break;
      case ModifierKey.numLockModifier:
        result = modifiers & modifierNumLock != 0;
        break;
      // The OS does not expose the Fn key to the drivers, it doesn't generate a key message.
      case ModifierKey.functionModifier:
      case ModifierKey.symbolModifier:
        // These modifier masks are not used in Windows keyboards.
        result = false;
        break;
    }
    assert(!result || getModifierSide(key) != null, "$runtimeType thinks that a modifier is pressed, but can't figure out what side it's on.");
    return result;
  }


  @override
  KeyboardSide? getModifierSide(ModifierKey key) {
    KeyboardSide? findSide(int leftMask, int rightMask, int anyMask) {
      final int combinedMask = leftMask | rightMask;
      final int combined = modifiers & combinedMask;
      if (combined == leftMask) {
        return KeyboardSide.left;
      } else if (combined == rightMask) {
        return KeyboardSide.right;
      } else if (combined == combinedMask || modifiers & (combinedMask | anyMask) == anyMask) {
        // Handles the case where Windows supplies just the "either" modifier
        // flag, but not the left/right flag. (e.g. modifierShift but not
        // modifierLeftShift).
        return KeyboardSide.all;
      }
      return null;
    }

    switch (key) {
      case ModifierKey.controlModifier:
        return findSide(modifierLeftControl, modifierRightControl, modifierControl);
      case ModifierKey.shiftModifier:
        return findSide(modifierLeftShift, modifierRightShift, modifierShift);
      case ModifierKey.altModifier:
        return findSide(modifierLeftAlt, modifierRightAlt, modifierAlt);
      case ModifierKey.metaModifier:
        return findSide(modifierLeftMeta, modifierRightMeta, 0);
      case ModifierKey.capsLockModifier:
      case ModifierKey.numLockModifier:
      case ModifierKey.scrollLockModifier:
      case ModifierKey.functionModifier:
      case ModifierKey.symbolModifier:
        return KeyboardSide.all;
    }
  }

  @override
  bool shouldDispatchEvent() {
    // In Win32 API, down events related to IME operations use VK_PROCESSKEY as
    // keyCode. This event, as well as the following key up event (which uses a
    // normal keyCode), should be skipped, because the effect of IME operations
    // will be handled by the text input API.
    return keyCode != _vkProcessKey;
  }

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(DiagnosticsProperty<int>('keyCode', keyCode));
    properties.add(DiagnosticsProperty<int>('scanCode', scanCode));
    properties.add(DiagnosticsProperty<int>('characterCodePoint', characterCodePoint));
    properties.add(DiagnosticsProperty<int>('modifiers', modifiers));
  }

  @override
  bool operator==(Object other) {
    if (identical(this, other))
      return true;
    if (other.runtimeType != runtimeType)
      return false;
    return other is RawKeyEventDataWindows
        && other.keyCode == keyCode
        && other.scanCode == scanCode
        && other.characterCodePoint == characterCodePoint
        && other.modifiers == modifiers;
  }

  @override
  int get hashCode => hashValues(
    keyCode,
    scanCode,
    characterCodePoint,
    modifiers,
  );

  // These are not the values defined by the Windows header for each modifier. Since they
  // can't be packaged into a single int, we are re-defining them here to reduce the size
  // of the message from the embedder. Embedders should map these values to the native key codes.
  // Keep this in sync with https://github.com/flutter/engine/blob/master/shell/platform/windows/key_event_handler.cc

  /// This mask is used to check the [modifiers] field to test whether one of the
  /// SHIFT modifier keys is pressed.
  ///
  /// {@template flutter.services.RawKeyEventDataWindows.modifierShift}
  /// Use this value if you need to decode the [modifiers] field yourself, but
  /// it's much easier to use [isModifierPressed] if you just want to know if
  /// a modifier is pressed.
  /// {@endtemplate}
  static const int modifierShift = 1 << 0;

  /// This mask is used to check the [modifiers] field to test whether the left
  /// SHIFT modifier key is pressed.
  ///
  /// {@macro flutter.services.RawKeyEventDataWindows.modifierShift}
  static const int modifierLeftShift = 1 << 1;

  /// This mask is used to check the [modifiers] field to test whether the right
  /// SHIFT modifier key is pressed.
  ///
  /// {@macro flutter.services.RawKeyEventDataWindows.modifierShift}
  static const int modifierRightShift = 1 << 2;

  /// This mask is used to check the [modifiers] field to test whether one of the
  /// CTRL modifier keys is pressed.
  ///
  /// {@macro flutter.services.RawKeyEventDataWindows.modifierShift}
  static const int modifierControl = 1 << 3;

  /// This mask is used to check the [modifiers] field to test whether the left
  /// CTRL modifier key is pressed.
  ///
  /// {@macro flutter.services.RawKeyEventDataWindows.modifierShift}
  static const int modifierLeftControl = 1 << 4;

  /// This mask is used to check the [modifiers] field to test whether the right
  /// CTRL modifier key is pressed.
  ///
  /// {@macro flutter.services.RawKeyEventDataWindows.modifierShift}
  static const int modifierRightControl = 1 << 5;

  /// This mask is used to check the [modifiers] field to test whether one of the
  /// ALT modifier keys is pressed.
  ///
  /// {@macro flutter.services.RawKeyEventDataWindows.modifierShift}
  static const int modifierAlt = 1 << 6;

  /// This mask is used to check the [modifiers] field to test whether the left
  /// ALT modifier key is pressed.
  ///
  /// {@macro flutter.services.RawKeyEventDataWindows.modifierShift}
  static const int modifierLeftAlt = 1 << 7;

  /// This mask is used to check the [modifiers] field to test whether the right
  /// ALT modifier key is pressed.
  ///
  /// {@macro flutter.services.RawKeyEventDataWindows.modifierShift}
  static const int modifierRightAlt = 1 << 8;

  /// This mask is used to check the [modifiers] field to test whether the left
  /// WIN modifier keys is pressed.
  ///
  /// {@macro flutter.services.RawKeyEventDataWindows.modifierShift}
  static const int modifierLeftMeta = 1 << 9;

  /// This mask is used to check the [modifiers] field to test whether the right
  /// WIN modifier keys is pressed.
  ///
  /// {@macro flutter.services.RawKeyEventDataWindows.modifierShift}
  static const int modifierRightMeta = 1 << 10;

  /// This mask is used to check the [modifiers] field to test whether the CAPS LOCK key
  /// is pressed.
  ///
  /// {@macro flutter.services.RawKeyEventDataWindows.modifierShift}
  static const int modifierCaps = 1 << 11;

  /// This mask is used to check the [modifiers] field to test whether the NUM LOCK key
  /// is pressed.
  ///
  /// {@macro flutter.services.RawKeyEventDataWindows.modifierShift}
  static const int modifierNumLock = 1 << 12;

  /// This mask is used to check the [modifiers] field to test whether the SCROLL LOCK key
  /// is pressed.
  ///
  /// {@macro flutter.services.RawKeyEventDataWindows.modifierShift}
  static const int modifierScrollLock = 1 << 13;
}
