// 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/FlutterFakeKeyEvents.h"
#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterMacros.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/KeyCodeMap_Internal.h"

FLUTTER_ASSERT_ARC;

@implementation FakeUIPressProxy
- (instancetype)initWithData:(UIPressPhase)phase
                         key:(UIKey*)key
                        type:(UIEventType)type
                   timestamp:(NSTimeInterval)timestamp API_AVAILABLE(ios(13.4)) {
  self = [super init];
  if (self) {
    _dataPhase = phase;
    _dataKey = [key copy];
    _dataType = type;
    _dataTimestamp = timestamp;
  }
  return self;
}

- (UIPressPhase)phase API_AVAILABLE(ios(13.4)) {
  return _dataPhase;
}

- (UIKey*)key API_AVAILABLE(ios(13.4)) {
  return _dataKey;
}

- (UIEventType)type API_AVAILABLE(ios(13.4)) {
  return _dataType;
}

- (NSTimeInterval)timestamp API_AVAILABLE(ios(13.4)) {
  return _dataTimestamp;
}
@end

@implementation FakeUIKey
- (instancetype)initWithData:(UIKeyboardHIDUsage)keyCode
                  modifierFlags:(UIKeyModifierFlags)modifierFlags
                     characters:(NSString*)characters
    charactersIgnoringModifiers:(NSString*)charactersIgnoringModifiers API_AVAILABLE(ios(13.4)) {
  self = [super init];
  if (self) {
    _dataKeyCode = keyCode;
    _dataModifierFlags = modifierFlags;
    _dataCharacters = characters;
    _dataCharactersIgnoringModifiers = charactersIgnoringModifiers;
  }
  return self;
}

- (id)copyWithZone:(NSZone*)zone {
  FakeUIKey* another = [super copyWithZone:zone];
  another.dataKeyCode = _dataKeyCode;
  another.dataModifierFlags = _dataModifierFlags;
  another.dataCharacters = [_dataCharacters copyWithZone:zone];
  another.dataCharactersIgnoringModifiers = [_dataCharactersIgnoringModifiers copyWithZone:zone];

  return another;
}

- (UIKeyboardHIDUsage)keyCode API_AVAILABLE(ios(13.4)) {
  return _dataKeyCode;
}

- (UIKeyModifierFlags)modifierFlags API_AVAILABLE(ios(13.4)) {
  return _dataModifierFlags;
}

- (NSString*)characters API_AVAILABLE(ios(13.4)) {
  return _dataCharacters;
}

- (NSString*)charactersIgnoringModifiers API_AVAILABLE(ios(13.4)) {
  return _dataCharactersIgnoringModifiers;
}
@end

FlutterUIPressProxy* keyDownEvent(UIKeyboardHIDUsage keyCode,
                                  UIKeyModifierFlags modifierFlags,
                                  NSTimeInterval timestamp,
                                  const char* characters,
                                  const char* charactersIgnoringModifiers)
    API_AVAILABLE(ios(13.4)) {
  return keyEventWithPhase(UIPressPhaseBegan, keyCode, modifierFlags, timestamp, characters,
                           charactersIgnoringModifiers);
}

FlutterUIPressProxy* keyUpEvent(UIKeyboardHIDUsage keyCode,
                                UIKeyModifierFlags modifierFlags,
                                NSTimeInterval timestamp) API_AVAILABLE(ios(13.4)) {
  return keyEventWithPhase(UIPressPhaseEnded, keyCode, modifierFlags, timestamp);
}

FlutterUIPressProxy* keyEventWithPhase(UIPressPhase phase,
                                       UIKeyboardHIDUsage keyCode,
                                       UIKeyModifierFlags modifierFlags,
                                       NSTimeInterval timestamp,
                                       const char* characters,
                                       const char* charactersIgnoringModifiers)
    API_AVAILABLE(ios(13.4)) {
  assert(!(modifierFlags & kModifierFlagSidedMask) &&
         "iOS doesn't supply modifier side flags, so don't create events with them.");
  UIKey* key =
      [[FakeUIKey alloc] initWithData:keyCode
                        modifierFlags:modifierFlags
                           characters:[NSString stringWithUTF8String:characters]
          charactersIgnoringModifiers:[NSString stringWithUTF8String:charactersIgnoringModifiers]];

  return [[FakeUIPressProxy alloc] initWithData:phase
                                            key:key
                                           type:UIEventTypePresses
                                      timestamp:timestamp];
}
