// 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 <Foundation/Foundation.h>
#import <OCMock/OCMock.h>
#import <UIKit/UIKit.h>
#import <XCTest/XCTest.h>
#include <_types/_uint32_t.h>

#include "flutter/fml/platform/darwin/message_loop_darwin.h"
#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterMacros.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterFakeKeyEvents.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterKeyboardManager.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterUIPressProxy.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h"

FLUTTER_ASSERT_ARC;

namespace flutter {
class PointerDataPacket {};
}

/// Sometimes we have to use a custom mock to avoid retain cycles in ocmock.
@interface FlutterEnginePartialMock : FlutterEngine
@property(nonatomic, strong) FlutterBasicMessageChannel* lifecycleChannel;
@property(nonatomic, weak) FlutterViewController* viewController;
@property(nonatomic, assign) BOOL didCallNotifyLowMemory;
@end

@interface FlutterEngine ()
- (BOOL)createShell:(NSString*)entrypoint
         libraryURI:(NSString*)libraryURI
       initialRoute:(NSString*)initialRoute;
- (void)dispatchPointerDataPacket:(std::unique_ptr<flutter::PointerDataPacket>)packet;
@end

@interface FlutterEngine (TestLowMemory)
- (void)notifyLowMemory;
@end

extern NSNotificationName const FlutterViewControllerWillDealloc;

/// A simple mock class for FlutterEngine.
///
/// OCMockClass can't be used for FlutterEngine sometimes because OCMock retains arguments to
/// invocations and since the init for FlutterViewController calls a method on the
/// FlutterEngine it creates a retain cycle that stops us from testing behaviors related to
/// deleting FlutterViewControllers.
@interface MockEngine : NSObject
@end

@interface FlutterKeyboardManagerUnittestsObjC : NSObject
- (bool)nextResponderShouldThrowOnPressesEnded;
- (bool)singlePrimaryResponder;
- (bool)doublePrimaryResponder;
- (bool)singleSecondaryResponder;
- (bool)emptyNextResponder;
@end

namespace {

typedef void (^KeyCallbackSetter)(FlutterUIPressProxy* press, FlutterAsyncKeyCallback callback)
    API_AVAILABLE(ios(13.4));
typedef BOOL (^BoolGetter)();

}  // namespace

@interface FlutterKeyboardManagerTest : XCTestCase
@property(nonatomic, strong) id mockEngine;
- (FlutterViewController*)mockOwnerWithPressesBeginOnlyNext API_AVAILABLE(ios(13.4));
@end

@implementation FlutterKeyboardManagerTest

- (void)setUp {
  [super setUp];
  self.mockEngine = OCMClassMock([FlutterEngine class]);
}

- (void)tearDown {
  // We stop mocking here to avoid retain cycles that stop
  // FlutterViewControllers from deallocing.
  [self.mockEngine stopMocking];
  self.mockEngine = nil;
  [super tearDown];
}

- (id)checkKeyDownEvent:(UIKeyboardHIDUsage)keyCode API_AVAILABLE(ios(13.4)) {
  return [OCMArg checkWithBlock:^BOOL(id value) {
    if (![value isKindOfClass:[FlutterUIPressProxy class]]) {
      return NO;
    }
    FlutterUIPressProxy* press = value;
    return press.key.keyCode == keyCode;
  }];
}

- (id<FlutterKeyPrimaryResponder>)mockPrimaryResponder:(KeyCallbackSetter)callbackSetter
    API_AVAILABLE(ios(13.4)) {
  id<FlutterKeyPrimaryResponder> mock =
      OCMStrictProtocolMock(@protocol(FlutterKeyPrimaryResponder));
  OCMStub([mock handlePress:[OCMArg any] callback:[OCMArg any]])
      .andDo((^(NSInvocation* invocation) {
        FlutterUIPressProxy* press;
        FlutterAsyncKeyCallback callback;
        [invocation getArgument:&press atIndex:2];
        [invocation getArgument:&callback atIndex:3];
        CFRunLoopPerformBlock(CFRunLoopGetCurrent(),
                              fml::MessageLoopDarwin::kMessageLoopCFRunLoopMode, ^() {
                                callbackSetter(press, callback);
                              });
      }));
  return mock;
}

- (id<FlutterKeySecondaryResponder>)mockSecondaryResponder:(BoolGetter)resultGetter
    API_AVAILABLE(ios(13.4)) {
  id<FlutterKeySecondaryResponder> mock =
      OCMStrictProtocolMock(@protocol(FlutterKeySecondaryResponder));
  OCMStub([mock handlePress:[OCMArg any]]).andDo((^(NSInvocation* invocation) {
    BOOL result = resultGetter();
    [invocation setReturnValue:&result];
  }));
  return mock;
}

- (FlutterViewController*)mockOwnerWithPressesBeginOnlyNext API_AVAILABLE(ios(13.4)) {
  // The nextResponder is a strict mock and hasn't stubbed pressesEnded.
  // An error will be thrown on pressesEnded.
  UIResponder* nextResponder = OCMStrictClassMock([UIResponder class]);
  OCMStub([nextResponder pressesBegan:[OCMArg any] withEvent:[OCMArg any]]).andDo(nil);

  FlutterViewController* viewController =
      [[FlutterViewController alloc] initWithEngine:self.mockEngine nibName:nil bundle:nil];
  FlutterViewController* owner = OCMPartialMock(viewController);
  OCMStub([owner nextResponder]).andReturn(nextResponder);
  return owner;
}

// Verify that the nextResponder returned from mockOwnerWithPressesBeginOnlyNext()
// throws exception when pressesEnded is called.
- (bool)testNextResponderShouldThrowOnPressesEnded API_AVAILABLE(ios(13.4)) {
  FlutterViewController* owner = [self mockOwnerWithPressesBeginOnlyNext];
  @try {
    [owner.nextResponder pressesEnded:[NSSet init] withEvent:[[UIPressesEvent alloc] init]];
    return false;
  } @catch (...) {
    return true;
  }
}

- (void)testSinglePrimaryResponder API_AVAILABLE(ios(13.4)) {
  FlutterKeyboardManager* manager = [[FlutterKeyboardManager alloc] init];
  __block BOOL primaryResponse = FALSE;
  __block int callbackCount = 0;
  [manager addPrimaryResponder:[self mockPrimaryResponder:^(FlutterUIPressProxy* press,
                                                            FlutterAsyncKeyCallback callback) {
             callbackCount++;
             callback(primaryResponse);
           }]];
  constexpr UIKeyboardHIDUsage keyId = (UIKeyboardHIDUsage)0x50;
  // Case: The responder reports TRUE
  __block bool completeHandled = true;
  primaryResponse = TRUE;
  [manager handlePress:keyDownEvent(keyId)
            nextAction:^() {
              completeHandled = false;
            }];
  XCTAssertEqual(callbackCount, 1);
  XCTAssertTrue(completeHandled);
  completeHandled = true;
  callbackCount = 0;

  // Case: The responder reports FALSE
  primaryResponse = FALSE;
  [manager handlePress:keyUpEvent(keyId)
            nextAction:^() {
              completeHandled = false;
            }];
  XCTAssertEqual(callbackCount, 1);
  XCTAssertFalse(completeHandled);
}

- (void)testDoublePrimaryResponder API_AVAILABLE(ios(13.4)) {
  FlutterKeyboardManager* manager = [[FlutterKeyboardManager alloc] init];

  __block BOOL callback1Response = FALSE;
  __block int callback1Count = 0;
  [manager addPrimaryResponder:[self mockPrimaryResponder:^(FlutterUIPressProxy* press,
                                                            FlutterAsyncKeyCallback callback) {
             callback1Count++;
             callback(callback1Response);
           }]];

  __block BOOL callback2Response = FALSE;
  __block int callback2Count = 0;
  [manager addPrimaryResponder:[self mockPrimaryResponder:^(FlutterUIPressProxy* press,
                                                            FlutterAsyncKeyCallback callback) {
             callback2Count++;
             callback(callback2Response);
           }]];

  // Case: Both responders report TRUE.
  __block bool somethingWasHandled = true;
  constexpr UIKeyboardHIDUsage keyId = (UIKeyboardHIDUsage)0x50;
  callback1Response = TRUE;
  callback2Response = TRUE;
  [manager handlePress:keyUpEvent(keyId)
            nextAction:^() {
              somethingWasHandled = false;
            }];
  XCTAssertEqual(callback1Count, 1);
  XCTAssertEqual(callback2Count, 1);
  XCTAssertTrue(somethingWasHandled);

  somethingWasHandled = true;
  callback1Count = 0;
  callback2Count = 0;

  // Case: One responder reports TRUE.
  callback1Response = TRUE;
  callback2Response = FALSE;
  [manager handlePress:keyUpEvent(keyId)
            nextAction:^() {
              somethingWasHandled = false;
            }];
  XCTAssertEqual(callback1Count, 1);
  XCTAssertEqual(callback2Count, 1);
  XCTAssertTrue(somethingWasHandled);

  somethingWasHandled = true;
  callback1Count = 0;
  callback2Count = 0;

  // Case: Both responders report FALSE.
  callback1Response = FALSE;
  callback2Response = FALSE;
  [manager handlePress:keyDownEvent(keyId)
            nextAction:^() {
              somethingWasHandled = false;
            }];
  XCTAssertEqual(callback1Count, 1);
  XCTAssertEqual(callback2Count, 1);
  XCTAssertFalse(somethingWasHandled);
}

- (void)testSingleSecondaryResponder API_AVAILABLE(ios(13.4)) {
  FlutterKeyboardManager* manager = [[FlutterKeyboardManager alloc] init];

  __block BOOL primaryResponse = FALSE;
  __block int callbackCount = 0;
  [manager addPrimaryResponder:[self mockPrimaryResponder:^(FlutterUIPressProxy* press,
                                                            FlutterAsyncKeyCallback callback) {
             callbackCount++;
             callback(primaryResponse);
           }]];

  __block BOOL secondaryResponse;
  [manager addSecondaryResponder:[self mockSecondaryResponder:^() {
             return secondaryResponse;
           }]];

  // Case: Primary responder responds TRUE. The event shouldn't be handled by
  // the secondary responder.
  constexpr UIKeyboardHIDUsage keyId = (UIKeyboardHIDUsage)0x50;
  secondaryResponse = FALSE;
  primaryResponse = TRUE;
  __block bool completeHandled = true;
  [manager handlePress:keyUpEvent(keyId)
            nextAction:^() {
              completeHandled = false;
            }];
  XCTAssertEqual(callbackCount, 1);
  XCTAssertTrue(completeHandled);
  completeHandled = true;
  callbackCount = 0;

  // Case: Primary responder responds FALSE. The secondary responder returns
  // TRUE.
  secondaryResponse = TRUE;
  primaryResponse = FALSE;
  [manager handlePress:keyUpEvent(keyId)
            nextAction:^() {
              completeHandled = false;
            }];
  XCTAssertEqual(callbackCount, 1);
  XCTAssertTrue(completeHandled);
  completeHandled = true;
  callbackCount = 0;

  // Case: Primary responder responds FALSE. The secondary responder returns FALSE.
  secondaryResponse = FALSE;
  primaryResponse = FALSE;
  [manager handlePress:keyDownEvent(keyId)
            nextAction:^() {
              completeHandled = false;
            }];
  XCTAssertEqual(callbackCount, 1);
  XCTAssertFalse(completeHandled);
}

- (void)testEventsProcessedSequentially API_AVAILABLE(ios(13.4)) {
  constexpr UIKeyboardHIDUsage keyId1 = (UIKeyboardHIDUsage)0x50;
  constexpr UIKeyboardHIDUsage keyId2 = (UIKeyboardHIDUsage)0x51;
  FlutterUIPressProxy* event1 = keyDownEvent(keyId1);
  FlutterUIPressProxy* event2 = keyDownEvent(keyId2);
  __block FlutterAsyncKeyCallback key1Callback;
  __block FlutterAsyncKeyCallback key2Callback;
  __block bool key1Handled = true;
  __block bool key2Handled = true;

  FlutterKeyboardManager* manager = [[FlutterKeyboardManager alloc] init];
  [manager addPrimaryResponder:[self mockPrimaryResponder:^(FlutterUIPressProxy* press,
                                                            FlutterAsyncKeyCallback callback) {
             if (press == event1) {
               key1Callback = callback;
             } else if (press == event2) {
               key2Callback = callback;
             }
           }]];

  // Add both presses into the main CFRunLoop queue
  CFRunLoopTimerRef timer0 = CFRunLoopTimerCreateWithHandler(
      kCFAllocatorDefault, CFAbsoluteTimeGetCurrent(), 0, 0, 0, ^(CFRunLoopTimerRef timerRef) {
        [manager handlePress:event1
                  nextAction:^() {
                    key1Handled = false;
                  }];
      });
  CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer0, kCFRunLoopCommonModes);
  CFRunLoopTimerRef timer1 = CFRunLoopTimerCreateWithHandler(
      kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + 1, 0, 0, 0, ^(CFRunLoopTimerRef timerRef) {
        // key1 should be completely finished by now
        XCTAssertFalse(key1Handled);
        [manager handlePress:event2
                  nextAction:^() {
                    key2Handled = false;
                  }];
        // End the nested CFRunLoop
        CFRunLoopStop(CFRunLoopGetCurrent());
      });
  CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer1, kCFRunLoopCommonModes);

  // Add the callbacks to the CFRunLoop with mode kMessageLoopCFRunLoopMode
  // This allows them to interrupt the loop started within handlePress
  CFRunLoopTimerRef timer2 = CFRunLoopTimerCreateWithHandler(
      kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + 2, 0, 0, 0, ^(CFRunLoopTimerRef timerRef) {
        // No processing should be done on key2 yet
        XCTAssertTrue(key1Callback != nil);
        XCTAssertTrue(key2Callback == nil);
        key1Callback(false);
      });
  CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer2,
                    fml::MessageLoopDarwin::kMessageLoopCFRunLoopMode);
  CFRunLoopTimerRef timer3 = CFRunLoopTimerCreateWithHandler(
      kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + 3, 0, 0, 0, ^(CFRunLoopTimerRef timerRef) {
        // Both keys should be processed by now
        XCTAssertTrue(key1Callback != nil);
        XCTAssertTrue(key2Callback != nil);
        key2Callback(false);
      });
  CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer3,
                    fml::MessageLoopDarwin::kMessageLoopCFRunLoopMode);

  // Start a nested CFRunLoop so we can wait for both presses to complete before exiting the test
  CFRunLoopRun();
  XCTAssertFalse(key2Handled);
  XCTAssertFalse(key1Handled);
}

@end
