// Copyright 2013 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 "flutter/shell/platform/darwin/ios/framework/Source/FlutterEmbedderKeyResponder.h"
#include <objc/NSObjCRuntime.h>

#import <objc/message.h>
#include <map>
#include "fml/memory/weak_ptr.h"

#import "KeyCodeMap_Internal.h"
#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterCodecs.h"

namespace {

/**
 * Isolate the least significant 1-bit.
 *
 * For example,
 *
 *  * lowestSetBit(0x1010) returns 0x10.
 *  * lowestSetBit(0) returns 0.
 */
static NSUInteger lowestSetBit(NSUInteger bitmask) {
  // This utilizes property of two's complement (negation), which propagates a
  // carry bit from LSB to the lowest set bit.
  return bitmask & -bitmask;
}

/**
 * Whether a string represents a control character.
 */
static bool IsControlCharacter(NSUInteger length, NSString* label) {
  if (length > 1) {
    return false;
  }
  unichar codeUnit = [label characterAtIndex:0];
  return (codeUnit <= 0x1f && codeUnit >= 0x00) || (codeUnit >= 0x7f && codeUnit <= 0x9f);
}

/**
 * Whether a string represents an unprintable key.
 */
static bool IsUnprintableKey(NSUInteger length, NSString* label) {
  if (length > 1) {
    return false;
  }
  unichar codeUnit = [label characterAtIndex:0];
  return codeUnit >= 0xF700 && codeUnit <= 0xF8FF;
}

/**
 * Returns a key code composed with a base key and a plane.
 *
 * Examples of unprintable keys are "NSUpArrowFunctionKey = 0xF700" or
 * "NSHomeFunctionKey = 0xF729".
 *
 * See
 * https://developer.apple.com/documentation/appkit/1535851-function-key_unicodes?language=objc
 * for more information.
 */
static uint64_t KeyOfPlane(uint64_t baseKey, uint64_t plane) {
  return plane | (baseKey & kValueMask);
}

/**
 * Returns the physical key for a key code.
 */
static uint64_t GetPhysicalKeyForKeyCode(UInt32 keyCode) {
  auto physicalKey = keyCodeToPhysicalKey.find(keyCode);
  if (physicalKey == keyCodeToPhysicalKey.end()) {
    return KeyOfPlane(keyCode, kIosPlane);
  }
  return physicalKey->second;
}

/**
 * Returns the logical key for a modifier physical key.
 */
static uint64_t GetLogicalKeyForModifier(UInt32 keyCode, uint64_t hidCode) {
  auto fromKeyCode = keyCodeToLogicalKey.find(keyCode);
  if (fromKeyCode != keyCodeToLogicalKey.end()) {
    return fromKeyCode->second;
  }
  return KeyOfPlane(hidCode, kIosPlane);
}

/**
 * Converts upper letters to lower letters in ASCII and extended ASCII, and
 * returns as-is otherwise.
 *
 * Independent of locale.
 */
static uint64_t toLower(uint64_t n) {
  constexpr uint64_t lower_a = 0x61;
  constexpr uint64_t upper_a = 0x41;
  constexpr uint64_t upper_z = 0x5a;

  constexpr uint64_t lower_a_grave = 0xe0;
  constexpr uint64_t upper_a_grave = 0xc0;
  constexpr uint64_t upper_thorn = 0xde;
  constexpr uint64_t division = 0xf7;

  // ASCII range.
  if (n >= upper_a && n <= upper_z) {
    return n - upper_a + lower_a;
  }

  // EASCII range.
  if (n >= upper_a_grave && n <= upper_thorn && n != division) {
    return n - upper_a_grave + lower_a_grave;
  }

  return n;
}

/**
 * Filters out some special cases in the characters field on UIKey.
 */
static const char* getEventCharacters(NSString* characters, UIKeyboardHIDUsage keyCode)
    API_AVAILABLE(ios(13.4)) {
  if (characters == nil) {
    return nullptr;
  }
  if ([characters length] == 0) {
    return nullptr;
  }
  if (@available(iOS 13.4, *)) {
    // On iOS, function keys return the UTF8 string "\^P" (with a literal '/',
    // '^' and a 'P', not escaped ctrl-P) as their "characters" field. This
    // isn't a valid (single) UTF8 character. Looking at the only UTF16
    // character for a function key yields a value of "16", which is a Unicode
    // "SHIFT IN" character, which is just odd. UTF8 conversion of that string
    // is what generates the three characters "\^P".
    //
    // Anyhow, we strip them all out and replace them with empty strings, since
    // function keys shouldn't be printable.
    if (functionKeyCodes.find(keyCode) != functionKeyCodes.end()) {
      return nullptr;
    }
  }
  return [characters UTF8String];
}

/**
 * Returns the logical key of a KeyUp or KeyDown event.
 *
 * The `maybeSpecialKey` is a nullable integer, and if not nil, indicates
 * that the event key is a special key as defined by `specialKeyMapping`,
 * and is the corresponding logical key.
 *
 * For modifier keys, use GetLogicalKeyForModifier.
 */
static uint64_t GetLogicalKeyForEvent(FlutterUIPressProxy* press, NSNumber* maybeSpecialKey)
    API_AVAILABLE(ios(13.4)) {
  if (maybeSpecialKey != nil) {
    return [maybeSpecialKey unsignedLongLongValue];
  }
  // Look to see if the keyCode can be mapped from keycode.
  auto fromKeyCode = keyCodeToLogicalKey.find(press.key.keyCode);
  if (fromKeyCode != keyCodeToLogicalKey.end()) {
    return fromKeyCode->second;
  }
  const char* characters =
      getEventCharacters(press.key.charactersIgnoringModifiers, press.key.keyCode);
  NSString* keyLabel =
      characters == nullptr ? nil : [[[NSString alloc] initWithUTF8String:characters] autorelease];
  NSUInteger keyLabelLength = [keyLabel length];
  // If this key is printable, generate the logical key from its Unicode
  // value. Control keys such as ESC, CTRL, and SHIFT are not printable. HOME,
  // DEL, arrow keys, and function keys are considered modifier function keys,
  // which generate invalid Unicode scalar values.
  if (keyLabelLength != 0 && !IsControlCharacter(keyLabelLength, keyLabel) &&
      !IsUnprintableKey(keyLabelLength, keyLabel)) {
    // Given that charactersIgnoringModifiers can contain a string of arbitrary
    // length, limit to a maximum of two Unicode scalar values. It is unlikely
    // that a keyboard would produce a code point bigger than 32 bits, but it is
    // still worth defending against this case.
    NSCAssert((keyLabelLength < 2), @"Unexpected long key label: |%@|.", keyLabel);

    uint64_t codeUnit = (uint64_t)[keyLabel characterAtIndex:0];
    if (keyLabelLength == 2) {
      uint64_t secondCode = (uint64_t)[keyLabel characterAtIndex:1];
      codeUnit = (codeUnit << 16) | secondCode;
    }
    return KeyOfPlane(toLower(codeUnit), kUnicodePlane);
  }

  // This is a non-printable key that is unrecognized, so a new code is minted
  // with the autogenerated bit set.
  return KeyOfPlane(press.key.keyCode, kIosPlane);
}

/**
 * Converts NSEvent.timestamp to the timestamp for Flutter.
 */
static double GetFlutterTimestampFrom(NSTimeInterval timestamp) {
  // Timestamp in microseconds. The event.timestamp is in seconds with sub-ms precision.
  return timestamp * 1000000.0;
}

/**
 * Compute |modifierFlagOfInterestMask| out of |keyCodeToModifierFlag|.
 *
 * This is equal to the bitwise-or of all values of |keyCodeToModifierFlag|.
 */
static NSUInteger computeModifierFlagOfInterestMask() {
  NSUInteger modifierFlagOfInterestMask = kModifierFlagCapsLock | kModifierFlagShiftAny |
                                          kModifierFlagControlAny | kModifierFlagAltAny |
                                          kModifierFlagMetaAny;
  for (std::pair<UInt32, ModifierFlag> entry : keyCodeToModifierFlag) {
    modifierFlagOfInterestMask = modifierFlagOfInterestMask | entry.second;
  }
  return modifierFlagOfInterestMask;
}

static bool isKeyDown(FlutterUIPressProxy* press) API_AVAILABLE(ios(13.4)) {
  switch (press.phase) {
    case UIPressPhaseStationary:
    case UIPressPhaseChanged:
      // Not sure if this is the right thing to do for these two, but true seems
      // more correct than false.
      return true;
    case UIPressPhaseBegan:
      return true;
    case UIPressPhaseCancelled:
    case UIPressPhaseEnded:
      return false;
  }
  return false;
}

/**
 * The C-function sent to the engine's |sendKeyEvent|, wrapping
 * |FlutterEmbedderKeyResponder.handleResponse|.
 *
 * For the reason of this wrap, see |FlutterKeyPendingResponse|.
 */
void HandleResponse(bool handled, void* user_data);
}  // namespace

/**
 * The invocation context for |HandleResponse|, wrapping
 * |FlutterEmbedderKeyResponder.handleResponse|.
 *
 * The key responder's functions only accept C-functions as callbacks, as well
 * as arbitrary user_data. In order to send an instance method of
 * |FlutterEmbedderKeyResponder.handleResponse| to the engine's |SendKeyEvent|,
 * we wrap the invocation into a C-function |HandleResponse| and invocation
 * context |FlutterKeyPendingResponse|.
 */
@interface FlutterKeyPendingResponse : NSObject

@property(readonly) FlutterEmbedderKeyResponder* responder;

@property(nonatomic) uint64_t responseId;

- (nonnull instancetype)initWithHandler:(nonnull FlutterEmbedderKeyResponder*)responder
                             responseId:(uint64_t)responseId;

@end

@implementation FlutterKeyPendingResponse
- (instancetype)initWithHandler:(FlutterEmbedderKeyResponder*)responder
                     responseId:(uint64_t)responseId {
  self = [super init];
  if (self != nil) {
    _responder = responder;
    _responseId = responseId;
  }
  return self;
}
@end

/**
 * Guards a |FlutterAsyncKeyCallback| to make sure it's handled exactly once
 * throughout the process of handling an event in |FlutterEmbedderKeyResponder|.
 *
 * A callback can either be handled with |pendTo:withId:|, or with |resolveTo:|.
 * Either way, the callback cannot be handled again, or an assertion will be
 * thrown.
 */
@interface FlutterKeyCallbackGuard : NSObject
- (nonnull instancetype)initWithCallback:(FlutterAsyncKeyCallback)callback;

/**
 * Handle the callback by storing it to pending responses.
 */
- (void)pendTo:(nonnull NSMutableDictionary<NSNumber*, FlutterAsyncKeyCallback>*)pendingResponses
        withId:(uint64_t)responseId;

/**
 * Handle the callback by calling it with a result.
 */
- (void)resolveTo:(BOOL)handled;

@property(nonatomic) BOOL handled;
/**
 * A string indicating how the callback is handled.
 *
 * Only set in debug mode. Nil in release mode, or if the callback has not been
 * handled.
 */
@property(readonly) NSString* debugHandleSource;
@end

@implementation FlutterKeyCallbackGuard {
  // The callback is declared in the implementation block to avoid being
  // accessed directly.
  FlutterAsyncKeyCallback _callback;
}
- (nonnull instancetype)initWithCallback:(FlutterAsyncKeyCallback)callback {
  self = [super init];
  if (self != nil) {
    _callback = [callback copy];
    _handled = FALSE;
  }
  return self;
}

- (void)dealloc {
  [_callback release];
  [super dealloc];
}

- (void)pendTo:(nonnull NSMutableDictionary<NSNumber*, FlutterAsyncKeyCallback>*)pendingResponses
        withId:(uint64_t)responseId {
  NSAssert(!_handled, @"This callback has been handled by %@.", _debugHandleSource);
  if (_handled) {
    return;
  }
  pendingResponses[@(responseId)] = _callback;
  _handled = TRUE;
  NSAssert(
      ((_debugHandleSource = [NSString stringWithFormat:@"pending event %llu", responseId]), TRUE),
      @"");
}

- (void)resolveTo:(BOOL)handled {
  NSAssert(!_handled, @"This callback has been handled by %@.", _debugHandleSource);
  if (_handled) {
    return;
  }
  _callback(handled);
  _handled = TRUE;
  NSAssert(((_debugHandleSource = [NSString stringWithFormat:@"resolved with %d", _handled]), TRUE),
           @"");
}
@end

@interface FlutterEmbedderKeyResponder ()

/**
 * The function to send converted events to.
 *
 * Set by the initializer.
 */
@property(nonatomic, copy, readonly) FlutterSendKeyEvent sendEvent;

/**
 * A map of pressed keys.
 *
 * The keys of the dictionary are physical keys, while the values are the logical keys
 * of the key down event.
 */
@property(nonatomic, retain, readonly) NSMutableDictionary<NSNumber*, NSNumber*>* pressingRecords;

/**
 * A constant mask for NSEvent.modifierFlags that Flutter synchronizes with.
 *
 * Flutter keeps track of the last |modifierFlags| and compares it with the
 * incoming one. Any bit within |modifierFlagOfInterestMask| that is different
 * (except for the one that corresponds to the event key) indicates that an
 * event for this modifier was missed, and Flutter synthesizes an event to make
 * up for the state difference.
 *
 * It is computed by computeModifierFlagOfInterestMask.
 */
@property(nonatomic) NSUInteger modifierFlagOfInterestMask;

/**
 * The modifier flags of the last received key event, excluding uninterested
 * bits.
 *
 * This should be kept synchronized with the last |NSEvent.modifierFlags|
 * after masking with |modifierFlagOfInterestMask|. This should also be kept
 * synchronized with the corresponding keys of |pressingRecords|.
 *
 * This is used by |synchronizeModifiers| to quickly find out modifier keys that
 * are desynchronized.
 */
@property(nonatomic) NSUInteger lastModifierFlagsOfInterest;

/**
 * A self-incrementing ID used to label key events sent to the framework.
 */
@property(nonatomic) uint64_t responseId;

/**
 * A map of unresponded key events sent to the framework.
 *
 * Its values are |responseId|s, and keys are the callback that was received
 * along with the event.
 */
@property(nonatomic, retain, readonly)
    NSMutableDictionary<NSNumber*, FlutterAsyncKeyCallback>* pendingResponses;

/**
 * Compare the last modifier flags and the current, and dispatch synthesized
 * key events for each different modifier flag bit.
 *
 * The flags compared are all flags after masking with
 * |modifierFlagOfInterestMask| and excluding |ignoringFlags|.
 */
- (void)synchronizeModifiers:(nonnull FlutterUIPressProxy*)press API_AVAILABLE(ios(13.4));

/**
 * Update the pressing state.
 *
 * If `logicalKey` is not 0, `physicalKey` is pressed as `logicalKey`.
 * Otherwise, `physicalKey` is released.
 */
- (void)updateKey:(uint64_t)physicalKey asPressed:(uint64_t)logicalKey;

/**
 * Synthesize a CapsLock down event, then a CapsLock up event.
 */
- (void)synthesizeCapsLockTapWithTimestamp:(NSTimeInterval)timestamp;

/**
 * Send an event to the framework, expecting its response.
 */
- (void)sendPrimaryFlutterEvent:(const FlutterKeyEvent&)event
                       callback:(nonnull FlutterKeyCallbackGuard*)callback;

/**
 * Send an empty key event.
 *
 * The event is never synthesized, and never expects an event result. An empty
 * event is sent when no other events should be sent, such as upon back-to-back
 * keydown events of the same key.
 */
- (void)sendEmptyEvent;

/**
 * Send a key event for a modifier key.
 */
- (void)synthesizeModifierEventOfType:(BOOL)isDownEvent
                            timestamp:(NSTimeInterval)timestamp
                              keyCode:(UInt32)keyCode;

/**
 * Processes a down event from the system.
 */
- (void)handlePressBegin:(nonnull FlutterUIPressProxy*)press
                callback:(nonnull FlutterKeyCallbackGuard*)callback API_AVAILABLE(ios(13.4));

/**
 * Processes an up event from the system.
 */
- (void)handlePressEnd:(nonnull FlutterUIPressProxy*)press
              callback:(nonnull FlutterKeyCallbackGuard*)callback API_AVAILABLE(ios(13.4));

/**
 * Processes the response from the framework.
 */
- (void)handleResponse:(BOOL)handled forId:(uint64_t)responseId;

/**
 * Fix up the modifiers for a particular type of modifier key.
 */
- (UInt32)fixSidedFlags:(ModifierFlag)anyFlag
           withLeftFlag:(ModifierFlag)leftSide
          withRightFlag:(ModifierFlag)rightSide
            withLeftKey:(UInt16)leftKeyCode
           withRightKey:(UInt16)rightKeyCode
            withKeyCode:(UInt16)keyCode
                keyDown:(BOOL)isKeyDown
               forFlags:(UInt32)modifiersPressed API_AVAILABLE(ios(13.4));

/**
 * Because iOS differs from other platforms in that the modifier flags still
 * contain the flag for the key that is being released on the keyup event, we
 * adjust the modifiers when the released key is a matching modifier key.
 */
- (UInt32)adjustModifiers:(nonnull FlutterUIPressProxy*)press API_AVAILABLE(ios(13.4));
@end

@implementation FlutterEmbedderKeyResponder

- (nonnull instancetype)initWithSendEvent:(FlutterSendKeyEvent)sendEvent {
  self = [super init];
  if (self != nil) {
    _sendEvent = [sendEvent copy];
    _pressingRecords = [[NSMutableDictionary alloc] init];
    _pendingResponses = [[NSMutableDictionary alloc] init];
    _responseId = 1;
    _lastModifierFlagsOfInterest = 0;
    _modifierFlagOfInterestMask = computeModifierFlagOfInterestMask();
  }
  return self;
}

- (void)dealloc {
  [_sendEvent release];
  [_pressingRecords release];
  [_pendingResponses release];
  [super dealloc];
}

- (void)handlePress:(nonnull FlutterUIPressProxy*)press
           callback:(FlutterAsyncKeyCallback)callback API_AVAILABLE(ios(13.4)) {
  if (@available(iOS 13.4, *)) {
  } else {
    return;
  }
  // The conversion algorithm relies on a non-nil callback to properly compute
  // `synthesized`.
  NSAssert(callback != nil, @"The callback must not be nil.");

  FlutterKeyCallbackGuard* guardedCallback = nil;
  switch (press.phase) {
    case UIPressPhaseBegan:
      guardedCallback = [[[FlutterKeyCallbackGuard alloc] initWithCallback:callback] autorelease];
      [self handlePressBegin:press callback:guardedCallback];
      break;
    case UIPressPhaseEnded:
      guardedCallback = [[[FlutterKeyCallbackGuard alloc] initWithCallback:callback] autorelease];
      [self handlePressEnd:press callback:guardedCallback];
      break;
    case UIPressPhaseChanged:
    case UIPressPhaseCancelled:
      // TODO(gspencergoog): Handle cancelled events as synthesized up events.
    case UIPressPhaseStationary:
      NSAssert(false, @"Unexpected press phase receieved in handlePress");
      return;
  }
  NSAssert(guardedCallback.handled, @"The callback returned without being handled.");
  NSAssert(
      (_lastModifierFlagsOfInterest & ~kModifierFlagCapsLock) ==
          ([self adjustModifiers:press] & (_modifierFlagOfInterestMask & ~kModifierFlagCapsLock)),
      @"The modifier flags are not properly updated: recorded 0x%lx, event with mask 0x%lx",
      static_cast<unsigned long>(_lastModifierFlagsOfInterest & ~kModifierFlagCapsLock),
      static_cast<unsigned long>([self adjustModifiers:press] &
                                 (_modifierFlagOfInterestMask & ~kModifierFlagCapsLock)));
}

#pragma mark - Private

- (void)synchronizeModifiers:(nonnull FlutterUIPressProxy*)press API_AVAILABLE(ios(13.4)) {
  if (@available(iOS 13.4, *)) {
  } else {
    return;
  }

  const UInt32 lastFlagsOfInterest = _lastModifierFlagsOfInterest & _modifierFlagOfInterestMask;
  const UInt32 pressedModifiers = [self adjustModifiers:press];
  const UInt32 currentFlagsOfInterest = pressedModifiers & _modifierFlagOfInterestMask;
  UInt32 flagDifference = currentFlagsOfInterest ^ lastFlagsOfInterest;
  if (flagDifference & kModifierFlagCapsLock) {
    // If the caps lock changed, and we didn't expect that, then send a
    // synthesized down and an up to simulate a toggle of the state.
    if (press.key.keyCode != UIKeyboardHIDUsageKeyboardCapsLock) {
      [self synthesizeCapsLockTapWithTimestamp:press.timestamp];
    }
    flagDifference &= ~kModifierFlagCapsLock;
  }
  while (true) {
    const UInt32 currentFlag = lowestSetBit(flagDifference);
    if (currentFlag == 0) {
      break;
    }
    flagDifference &= ~currentFlag;
    if (currentFlag & kModifierFlagAnyMask) {
      // Skip synthesizing keys for the "any" flags, since their synthesis will
      // be handled when we do the sided flags. We still want them in the flags
      // of interest, though, so we can keep their state.
      continue;
    }
    auto keyCode = modifierFlagToKeyCode.find(static_cast<ModifierFlag>(currentFlag));
    NSAssert(keyCode != modifierFlagToKeyCode.end(), @"Invalid modifier flag of interest 0x%lx",
             static_cast<unsigned long>(currentFlag));
    if (keyCode == modifierFlagToKeyCode.end()) {
      continue;
    }
    // If this press matches the modifier key in question, then don't synthesize
    // it, because it's already a "real" keypress.
    if (keyCode->second == static_cast<UInt32>(press.key.keyCode)) {
      continue;
    }
    BOOL isDownEvent = currentFlagsOfInterest & currentFlag;
    [self synthesizeModifierEventOfType:isDownEvent
                              timestamp:press.timestamp
                                keyCode:keyCode->second];
  }
  _lastModifierFlagsOfInterest =
      (_lastModifierFlagsOfInterest & ~_modifierFlagOfInterestMask) | currentFlagsOfInterest;
}

- (void)synthesizeCapsLockTapWithTimestamp:(NSTimeInterval)timestamp {
  // The assumption when the app starts is that caps lock is off, but if that
  // turns out to be untrue (according to the modifier flags), then this is used
  // to simulate a key down and a key up of the caps lock key, to simulate
  // toggling of that state in the framework.
  FlutterKeyEvent flutterEvent = {
      .struct_size = sizeof(FlutterKeyEvent),
      .timestamp = GetFlutterTimestampFrom(timestamp),
      .type = kFlutterKeyEventTypeDown,
      .physical = kCapsLockPhysicalKey,
      .logical = kCapsLockLogicalKey,
      .character = nil,
      .synthesized = true,
  };
  _sendEvent(flutterEvent, nullptr, nullptr);

  flutterEvent.type = kFlutterKeyEventTypeUp;
  _sendEvent(flutterEvent, nullptr, nullptr);
}

- (void)updateKey:(uint64_t)physicalKey asPressed:(uint64_t)logicalKey {
  if (logicalKey == 0) {
    [_pressingRecords removeObjectForKey:@(physicalKey)];
  } else {
    _pressingRecords[@(physicalKey)] = @(logicalKey);
  }
}

- (void)sendPrimaryFlutterEvent:(const FlutterKeyEvent&)event
                       callback:(FlutterKeyCallbackGuard*)callback {
  _responseId += 1;
  uint64_t responseId = _responseId;
  FlutterKeyPendingResponse* pending =
      [[[FlutterKeyPendingResponse alloc] initWithHandler:self responseId:responseId] autorelease];
  [callback pendTo:_pendingResponses withId:responseId];
  _sendEvent(event, HandleResponse, pending);
}

- (void)sendEmptyEvent {
  FlutterKeyEvent event = {
      .struct_size = sizeof(FlutterKeyEvent),
      .timestamp = 0,
      .type = kFlutterKeyEventTypeDown,
      .physical = 0,
      .logical = 0,
      .character = nil,
      .synthesized = false,
  };
  _sendEvent(event, nil, nil);
}

- (void)synthesizeModifierEventOfType:(BOOL)isDownEvent
                            timestamp:(NSTimeInterval)timestamp
                              keyCode:(UInt32)keyCode {
  uint64_t physicalKey = GetPhysicalKeyForKeyCode(keyCode);
  uint64_t logicalKey = GetLogicalKeyForModifier(keyCode, physicalKey);
  if (physicalKey == 0 || logicalKey == 0) {
    return;
  }
  FlutterKeyEvent flutterEvent = {
      .struct_size = sizeof(FlutterKeyEvent),
      .timestamp = GetFlutterTimestampFrom(timestamp),
      .type = isDownEvent ? kFlutterKeyEventTypeDown : kFlutterKeyEventTypeUp,
      .physical = physicalKey,
      .logical = logicalKey,
      .character = nil,
      .synthesized = true,
  };
  [self updateKey:physicalKey asPressed:isDownEvent ? logicalKey : 0];
  _sendEvent(flutterEvent, nullptr, nullptr);
}

- (void)handlePressBegin:(nonnull FlutterUIPressProxy*)press
                callback:(nonnull FlutterKeyCallbackGuard*)callback API_AVAILABLE(ios(13.4)) {
  if (@available(iOS 13.4, *)) {
  } else {
    return;
  }
  uint64_t physicalKey = GetPhysicalKeyForKeyCode(press.key.keyCode);
  // Some unprintable keys on iOS have literal names on their key label, such as
  // @"UIKeyInputEscape". They are called the "special keys" and have predefined
  // logical keys and empty characters.
  NSNumber* specialKey = [specialKeyMapping objectForKey:press.key.charactersIgnoringModifiers];
  uint64_t logicalKey = GetLogicalKeyForEvent(press, specialKey);
  [self synchronizeModifiers:press];

  NSNumber* pressedLogicalKey = nil;
  if ([_pressingRecords count] > 0) {
    pressedLogicalKey = _pressingRecords[@(physicalKey)];
    if (pressedLogicalKey != nil) {
      // Normally the key up events won't be missed since iOS always sends the
      // key up event to the view where the corresponding key down occurred.
      // However this might happen in add-to-app scenarios if the focus is changed
      // from the native view to the Flutter view amid the key tap.
      [callback resolveTo:TRUE];
      [self sendEmptyEvent];
      return;
    }
  }

  if (pressedLogicalKey == nil) {
    [self updateKey:physicalKey asPressed:logicalKey];
  }

  FlutterKeyEvent flutterEvent = {
      .struct_size = sizeof(FlutterKeyEvent),
      .timestamp = GetFlutterTimestampFrom(press.timestamp),
      .type = kFlutterKeyEventTypeDown,
      .physical = physicalKey,
      .logical = pressedLogicalKey == nil ? logicalKey : [pressedLogicalKey unsignedLongLongValue],
      .character =
          specialKey != nil ? nil : getEventCharacters(press.key.characters, press.key.keyCode),
      .synthesized = false,
  };
  [self sendPrimaryFlutterEvent:flutterEvent callback:callback];
}

- (void)handlePressEnd:(nonnull FlutterUIPressProxy*)press
              callback:(nonnull FlutterKeyCallbackGuard*)callback API_AVAILABLE(ios(13.4)) {
  if (@available(iOS 13.4, *)) {
  } else {
    return;
  }
  [self synchronizeModifiers:press];

  uint64_t physicalKey = GetPhysicalKeyForKeyCode(press.key.keyCode);
  NSNumber* pressedLogicalKey = _pressingRecords[@(physicalKey)];
  if (pressedLogicalKey == nil) {
    // Normally the key up events won't be missed since iOS always sends the
    // key up event to the view where the corresponding key down occurred.
    // However this might happen in add-to-app scenarios if the focus is changed
    // from the native view to the Flutter view amid the key tap.
    [callback resolveTo:TRUE];
    [self sendEmptyEvent];
    return;
  }
  [self updateKey:physicalKey asPressed:0];

  FlutterKeyEvent flutterEvent = {
      .struct_size = sizeof(FlutterKeyEvent),
      .timestamp = GetFlutterTimestampFrom(press.timestamp),
      .type = kFlutterKeyEventTypeUp,
      .physical = physicalKey,
      .logical = [pressedLogicalKey unsignedLongLongValue],
      .character = nil,
      .synthesized = false,
  };
  [self sendPrimaryFlutterEvent:flutterEvent callback:callback];
}

- (void)handleResponse:(BOOL)handled forId:(uint64_t)responseId {
  FlutterAsyncKeyCallback callback = _pendingResponses[@(responseId)];
  callback(handled);
  [_pendingResponses removeObjectForKey:@(responseId)];
}

- (UInt32)fixSidedFlags:(ModifierFlag)anyFlag
           withLeftFlag:(ModifierFlag)leftSide
          withRightFlag:(ModifierFlag)rightSide
            withLeftKey:(UInt16)leftKeyCode
           withRightKey:(UInt16)rightKeyCode
            withKeyCode:(UInt16)keyCode
                keyDown:(BOOL)isKeyDown
               forFlags:(UInt32)modifiersPressed API_AVAILABLE(ios(13.4)) {
  UInt32 newModifiers = modifiersPressed;
  if (isKeyDown) {
    // Add in the modifier flags that correspond to this key code, if any.
    if (keyCode == leftKeyCode) {
      newModifiers |= leftSide | anyFlag;
    } else if (keyCode == rightKeyCode) {
      newModifiers |= rightSide | anyFlag;
    }
  } else {
    // If this is a key up, then remove any modifier that matches the keycode in
    // the event from the flags, and the anyFlag if the other side isn't also
    // pressed.
    if (keyCode == leftKeyCode) {
      newModifiers &= ~leftSide;
      if (!(newModifiers & rightSide)) {
        newModifiers &= ~anyFlag;
      }
    } else if (keyCode == rightKeyCode) {
      newModifiers &= ~rightSide;
      if (!(newModifiers & leftSide)) {
        newModifiers &= ~anyFlag;
      }
    }
  }

  if (!(newModifiers & anyFlag)) {
    // Turn off any sided flags, since the "any" flag is gone.
    newModifiers &= ~(leftSide | rightSide);
  }

  return newModifiers;
}

// This fixes a few cases where iOS provides modifier flags differently from how
// the framework would like to receive them.
//
// 1) iOS turns off the flag associated with a modifier key AFTER the modifier
//    key up event, so when the key up event arrives, the flags must be modified
//    before synchronizing so they do not include the modifier that arrived in
//    the key up event.
// 2) Modifier flags can be set even when that modifier is not being pressed.
//    One example of this is when a special character is produced with the Alt
//    (Option) key, and the Alt key is released before the letter key: the
//    letter key's key up event still contains the Alt key flag.
// 3) iOS doesn't provide information about which side modifier was pressed,
//    except through the keycode of the pressed key, so we look at the pressed
//    key code to decide which side to indicate in the flags. If we can't know
//    (in the case of a non-modifier key event having an "any" modifier set, but
//    we don't know already that the modifier is down), then we just pick the
//    left one arbitrarily.
- (UInt32)adjustModifiers:(nonnull FlutterUIPressProxy*)press API_AVAILABLE(ios(13.4)) {
  if (@available(iOS 13.4, *)) {
    // no-op
  } else {
    return press.key.modifierFlags;
  }

  bool keyDown = isKeyDown(press);

  // Start with the current modifier flags, along with any sided flags that we
  // already know are down.
  UInt32 pressedModifiers =
      press.key.modifierFlags | (_lastModifierFlagsOfInterest & kModifierFlagSidedMask);

  pressedModifiers = [self fixSidedFlags:kModifierFlagShiftAny
                            withLeftFlag:kModifierFlagShiftLeft
                           withRightFlag:kModifierFlagShiftRight
                             withLeftKey:UIKeyboardHIDUsageKeyboardLeftShift
                            withRightKey:UIKeyboardHIDUsageKeyboardRightShift
                             withKeyCode:press.key.keyCode
                                 keyDown:keyDown
                                forFlags:pressedModifiers];
  pressedModifiers = [self fixSidedFlags:kModifierFlagControlAny
                            withLeftFlag:kModifierFlagControlLeft
                           withRightFlag:kModifierFlagControlRight
                             withLeftKey:UIKeyboardHIDUsageKeyboardLeftControl
                            withRightKey:UIKeyboardHIDUsageKeyboardRightControl
                             withKeyCode:press.key.keyCode
                                 keyDown:keyDown
                                forFlags:pressedModifiers];
  pressedModifiers = [self fixSidedFlags:kModifierFlagAltAny
                            withLeftFlag:kModifierFlagAltLeft
                           withRightFlag:kModifierFlagAltRight
                             withLeftKey:UIKeyboardHIDUsageKeyboardLeftAlt
                            withRightKey:UIKeyboardHIDUsageKeyboardRightAlt
                             withKeyCode:press.key.keyCode
                                 keyDown:keyDown
                                forFlags:pressedModifiers];
  pressedModifiers = [self fixSidedFlags:kModifierFlagMetaAny
                            withLeftFlag:kModifierFlagMetaLeft
                           withRightFlag:kModifierFlagMetaRight
                             withLeftKey:UIKeyboardHIDUsageKeyboardLeftGUI
                            withRightKey:UIKeyboardHIDUsageKeyboardRightGUI
                             withKeyCode:press.key.keyCode
                                 keyDown:keyDown
                                forFlags:pressedModifiers];

  if (press.key.keyCode == UIKeyboardHIDUsageKeyboardCapsLock) {
    // The caps lock modifier needs to be unset only if it was already on
    // and this is a key up. This is because it indicates the lock state, and
    // not the key press state. The caps lock state should be on between the
    // first down, and the second up (i.e. while the lock in effect), and
    // this code turns it off at the second up event. The OS leaves it on still
    // because of iOS's weird late processing of modifier states. Synthesis of
    // the appropriate synthesized key events happens in synchronizeModifiers.
    if (!keyDown && _lastModifierFlagsOfInterest & kModifierFlagCapsLock) {
      pressedModifiers &= ~kModifierFlagCapsLock;
    }
  }
  return pressedModifiers;
}

@end

namespace {
void HandleResponse(bool handled, void* user_data) {
  FlutterKeyPendingResponse* pending = reinterpret_cast<FlutterKeyPendingResponse*>(user_data);
  [pending.responder handleResponse:handled forId:pending.responseId];
}
}  // namespace
