// 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 <objc/message.h>

#import "FlutterChannelKeyResponder.h"
#import "KeyCodeMap_Internal.h"
#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterCodecs.h"
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterViewController_Internal.h"
#import "flutter/shell/platform/embedder/embedder.h"

@interface FlutterChannelKeyResponder ()

/**
 * The channel used to communicate with Flutter.
 */
@property(nonatomic) FlutterBasicMessageChannel* channel;

/**
 * The |NSEvent.modifierFlags| of the last event received.
 *
 * Used to determine whether a FlagsChanged event should count as a keydown or
 * a keyup event.
 */
@property(nonatomic) uint64_t previouslyPressedFlags;

@end

@implementation FlutterChannelKeyResponder

@synthesize layoutMap;

- (nonnull instancetype)initWithChannel:(nonnull FlutterBasicMessageChannel*)channel {
  self = [super init];
  if (self != nil) {
    _channel = channel;
    _previouslyPressedFlags = 0;
  }
  return self;
}

/// Checks single modifier flag from event flags and sends appropriate key event
/// if it is different from the previous state.
- (void)checkModifierFlag:(NSUInteger)targetMask
            forEventFlags:(NSEventModifierFlags)eventFlags
                  keyCode:(NSUInteger)keyCode
                timestamp:(NSTimeInterval)timestamp {
  NSAssert((targetMask & (targetMask - 1)) == 0, @"targetMask must only have one bit set");
  if ((eventFlags & targetMask) != (_previouslyPressedFlags & targetMask)) {
    uint64_t newFlags = (_previouslyPressedFlags & ~targetMask) | (eventFlags & targetMask);

    // Sets combined flag if either left or right modifier is pressed, unsets otherwise.
    auto updateCombinedFlag = [&](uint64_t side1, uint64_t side2, NSEventModifierFlags flag) {
      if (newFlags & (side1 | side2)) {
        newFlags |= flag;
      } else {
        newFlags &= ~flag;
      }
    };
    updateCombinedFlag(flutter::kModifierFlagShiftLeft, flutter::kModifierFlagShiftRight,
                       NSEventModifierFlagShift);
    updateCombinedFlag(flutter::kModifierFlagControlLeft, flutter::kModifierFlagControlRight,
                       NSEventModifierFlagControl);
    updateCombinedFlag(flutter::kModifierFlagAltLeft, flutter::kModifierFlagAltRight,
                       NSEventModifierFlagOption);
    updateCombinedFlag(flutter::kModifierFlagMetaLeft, flutter::kModifierFlagMetaRight,
                       NSEventModifierFlagCommand);

    NSEvent* event = [NSEvent keyEventWithType:NSEventTypeFlagsChanged
                                      location:NSZeroPoint
                                 modifierFlags:newFlags
                                     timestamp:timestamp
                                  windowNumber:0
                                       context:nil
                                    characters:@""
                   charactersIgnoringModifiers:@""
                                     isARepeat:NO
                                       keyCode:keyCode];
    [self handleEvent:event
             callback:^(BOOL){
             }];
  };
}

- (void)syncModifiersIfNeeded:(NSEventModifierFlags)modifierFlags
                    timestamp:(NSTimeInterval)timestamp {
  modifierFlags = modifierFlags & ~0x100;
  if (_previouslyPressedFlags == modifierFlags) {
    return;
  }

  [flutter::modifierFlagToKeyCode
      enumerateKeysAndObjectsUsingBlock:^(NSNumber* flag, NSNumber* keyCode, BOOL* stop) {
        [self checkModifierFlag:[flag unsignedShortValue]
                  forEventFlags:modifierFlags
                        keyCode:[keyCode unsignedShortValue]
                      timestamp:timestamp];
      }];

  // Caps lock is not included in the modifierFlagToKeyCode map.
  [self checkModifierFlag:NSEventModifierFlagCapsLock
            forEventFlags:modifierFlags
                  keyCode:0x00000039  // kVK_CapsLock
                timestamp:timestamp];

  // At the end we should end up with the same modifier flags as the event.
  FML_DCHECK(_previouslyPressedFlags == modifierFlags);
}

- (void)handleEvent:(NSEvent*)event callback:(FlutterAsyncKeyCallback)callback {
  // Remove the modifier bits that Flutter is not interested in.
  NSEventModifierFlags modifierFlags = event.modifierFlags & ~0x100;
  NSString* type;
  switch (event.type) {
    case NSEventTypeKeyDown:
      type = @"keydown";
      break;
    case NSEventTypeKeyUp:
      type = @"keyup";
      break;
    case NSEventTypeFlagsChanged:
      if (modifierFlags < _previouslyPressedFlags) {
        type = @"keyup";
      } else if (modifierFlags > _previouslyPressedFlags) {
        type = @"keydown";
      } else {
        // ignore duplicate modifiers; This can happen in situations like switching
        // between application windows when MacOS only sends the up event to new window.
        callback(true);
        return;
      }
      break;
    default: {
      NSAssert(false, @"Unexpected key event type (got %lu).", event.type);
      callback(false);
    }
  }
  _previouslyPressedFlags = modifierFlags;
  NSMutableDictionary* keyMessage = [@{
    @"keymap" : @"macos",
    @"type" : type,
    @"keyCode" : @(event.keyCode),
    @"modifiers" : @(modifierFlags),
  } mutableCopy];
  // Calling these methods on any other type of event
  // (e.g NSEventTypeFlagsChanged) will raise an exception.
  if (event.type == NSEventTypeKeyDown || event.type == NSEventTypeKeyUp) {
    keyMessage[@"characters"] = event.characters;
    keyMessage[@"charactersIgnoringModifiers"] = event.charactersIgnoringModifiers;
  }
  NSNumber* specifiedLogicalKey = layoutMap[@(event.keyCode)];
  if (specifiedLogicalKey != nil) {
    keyMessage[@"specifiedLogicalKey"] = specifiedLogicalKey;
  }
  [self.channel sendMessage:keyMessage
                      reply:^(id reply) {
                        if (!reply) {
                          return callback(true);
                        }
                        // Only propagate the event to other responders if the framework didn't
                        // handle it.
                        callback([[reply valueForKey:@"handled"] boolValue]);
                      }];
}

#pragma mark - Private

@end
