// 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.
 *
 * For modifier keys, use GetLogicalKeyForModifier.
 */
static uint64_t GetLogicalKeyForEvent(FlutterUIPressProxy* press, uint64_t physicalKey)
    API_AVAILABLE(ios(13.4)) {
  // 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);
  uint64_t logicalKey = GetLogicalKeyForEvent(press, physicalKey);
  [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 = 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 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
