// Copyright 2020 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 <XCTest/XCTest.h>

static const NSInteger kSecondsToWaitForFlutterView = 30;

@interface iPadGestureTests : XCTestCase

@end

@implementation iPadGestureTests

- (void)setUp {
  [super setUp];
  self.continueAfterFailure = NO;
}

static BOOL performBoolSelector(id target, SEL selector) {
  NSInvocation* invocation = [NSInvocation
      invocationWithMethodSignature:[[target class] instanceMethodSignatureForSelector:selector]];
  [invocation setSelector:selector];
  [invocation setTarget:target];
  [invocation invoke];
  BOOL returnValue;
  [invocation getReturnValue:&returnValue];
  return returnValue;
}

static int assertOneMessageAndGetSequenceNumber(NSMutableDictionary* messages, NSString* message) {
  NSMutableArray<NSNumber*>* matchingMessages = messages[message];
  XCTAssertNotNil(matchingMessages, @"Did not receive \"%@\" message", message);
  XCTAssertEqual(matchingMessages.count, 1, @"More than one \"%@\" message", message);
  return matchingMessages.firstObject.intValue;
}

// TODO(85810): Remove reflection in this test when Xcode version is upgraded to 13.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wundeclared-selector"
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
- (void)testPointerButtons {
  BOOL supportsPointerInteraction = NO;
  SEL supportsPointerInteractionSelector = @selector(supportsPointerInteraction);
  if ([XCUIDevice.sharedDevice respondsToSelector:supportsPointerInteractionSelector]) {
    supportsPointerInteraction =
        performBoolSelector(XCUIDevice.sharedDevice, supportsPointerInteractionSelector);
  }
  XCTSkipUnless(supportsPointerInteraction, "Device does not support pointer interaction.");
  XCUIApplication* app = [[XCUIApplication alloc] init];
  app.launchArguments = @[ @"--pointer-events" ];
  [app launch];

  NSPredicate* predicateToFindFlutterView =
      [NSPredicate predicateWithFormat:@"identifier BEGINSWITH 'flutter_view'"];
  XCUIElement* flutterView = [[app descendantsMatchingType:XCUIElementTypeAny]
      elementMatchingPredicate:predicateToFindFlutterView];
  if (![flutterView waitForExistenceWithTimeout:kSecondsToWaitForFlutterView]) {
    NSLog(@"%@", app.debugDescription);
    XCTFail(@"Failed due to not able to find any flutterView with %@ seconds",
            @(kSecondsToWaitForFlutterView));
  }

  XCTAssertNotNil(flutterView);

  [flutterView tap];
  // Initial add event should have buttons = 0
  XCTAssertTrue(
      [app.textFields[@"0,PointerChange.add,device=0,buttons=0"] waitForExistenceWithTimeout:1],
      @"PointerChange.add event did not occur for a normal tap");
  // Normal tap should have buttons = 0, the flutter framework will ensure it has buttons = 1
  XCTAssertTrue(
      [app.textFields[@"1,PointerChange.down,device=0,buttons=0"] waitForExistenceWithTimeout:1],
      @"PointerChange.down event did not occur for a normal tap");
  XCTAssertTrue(
      [app.textFields[@"2,PointerChange.up,device=0,buttons=0"] waitForExistenceWithTimeout:1],
      @"PointerChange.up event did not occur for a normal tap");
  XCTAssertTrue(
      [app.textFields[@"3,PointerChange.remove,device=0,buttons=0"] waitForExistenceWithTimeout:1],
      @"PointerChange.remove event did not occur for a normal tap");
  SEL rightClick = @selector(rightClick);
  XCTAssertTrue([flutterView respondsToSelector:rightClick],
                @"If supportsPointerInteraction is true, this should be true too.");
  [flutterView performSelector:rightClick];
  // On simulated right click, a hover also occurs, so the hover pointer is added
  XCTAssertTrue(
      [app.textFields[@"4,PointerChange.add,device=1,buttons=0"] waitForExistenceWithTimeout:1],
      @"PointerChange.add event did not occur for a right-click's hover pointer");

  // The hover pointer is removed after ~3.5 seconds, this ensures that all events are received
  XCTestExpectation* sleepExpectation = [self expectationWithDescription:@"never fires"];
  sleepExpectation.inverted = true;
  [self waitForExpectations:@[ sleepExpectation ] timeout:5.0];

  // The hover events are interspersed with the right-click events in a varying order.
  // Ensure the individual orderings are respected without hardcoding the absolute sequence.
  NSMutableDictionary<NSString*, NSMutableArray<NSNumber*>*>* messages =
      [[NSMutableDictionary alloc] init];
  for (XCUIElement* element in [app.textFields allElementsBoundByIndex]) {
    NSString* rawMessage = element.value;
    // Parse out the sequence number
    NSUInteger commaIndex = [rawMessage rangeOfString:@","].location;
    NSInteger messageSequenceNumber =
        [rawMessage substringWithRange:NSMakeRange(0, commaIndex)].integerValue;
    // Parse out the rest of the message
    NSString* message = [rawMessage
        substringWithRange:NSMakeRange(commaIndex + 1, rawMessage.length - (commaIndex + 1))];
    NSMutableArray<NSNumber*>* messageSequenceNumberList = messages[message];
    if (messageSequenceNumberList == nil) {
      messageSequenceNumberList = [[NSMutableArray alloc] init];
      messages[message] = messageSequenceNumberList;
    }
    [messageSequenceNumberList addObject:@(messageSequenceNumber)];
  }
  // The number of hover events is not consistent, there could be one or many.
  NSMutableArray<NSNumber*>* hoverSequenceNumbers =
      messages[@"PointerChange.hover,device=1,buttons=0"];
  int hoverRemovedSequenceNumber =
      assertOneMessageAndGetSequenceNumber(messages, @"PointerChange.remove,device=1,buttons=0");
  // Right click should have buttons = 2
  int rightClickAddedSequenceNumber;
  int rightClickDownSequenceNumber;
  int rightClickUpSequenceNumber;
  if (messages[@"PointerChange.add,device=2,buttons=0"] == nil) {
    // Sometimes the tap pointer has the same device as the right-click (the UITouch is reused)
    rightClickAddedSequenceNumber = 0;
    rightClickDownSequenceNumber =
        assertOneMessageAndGetSequenceNumber(messages, @"PointerChange.down,device=0,buttons=2");
    rightClickUpSequenceNumber =
        assertOneMessageAndGetSequenceNumber(messages, @"PointerChange.up,device=0,buttons=2");
  } else {
    rightClickAddedSequenceNumber =
        assertOneMessageAndGetSequenceNumber(messages, @"PointerChange.add,device=2,buttons=0");
    rightClickDownSequenceNumber =
        assertOneMessageAndGetSequenceNumber(messages, @"PointerChange.down,device=2,buttons=2");
    rightClickUpSequenceNumber =
        assertOneMessageAndGetSequenceNumber(messages, @"PointerChange.up,device=2,buttons=2");
  }
  XCTAssertGreaterThan(rightClickDownSequenceNumber, rightClickAddedSequenceNumber,
                       @"Right-click pointer was pressed before it was added");
  XCTAssertGreaterThan(rightClickUpSequenceNumber, rightClickDownSequenceNumber,
                       @"Right-click pointer was released before it was pressed");
  XCTAssertGreaterThan([[hoverSequenceNumbers firstObject] intValue], 4,
                       @"Hover occured before hover pointer was added");
  XCTAssertGreaterThan(hoverRemovedSequenceNumber, [[hoverSequenceNumbers lastObject] intValue],
                       @"Hover occured after hover pointer was removed");
}

- (void)testPointerHover {
  BOOL supportsPointerInteraction = NO;
  SEL supportsPointerInteractionSelector = @selector(supportsPointerInteraction);
  if ([XCUIDevice.sharedDevice respondsToSelector:supportsPointerInteractionSelector]) {
    supportsPointerInteraction =
        performBoolSelector(XCUIDevice.sharedDevice, supportsPointerInteractionSelector);
  }
  XCTSkipUnless(supportsPointerInteraction, "Device does not support pointer interaction.");
  XCUIApplication* app = [[XCUIApplication alloc] init];
  app.launchArguments = @[ @"--pointer-events" ];
  [app launch];

  NSPredicate* predicateToFindFlutterView =
      [NSPredicate predicateWithFormat:@"identifier BEGINSWITH 'flutter_view'"];
  XCUIElement* flutterView = [[app descendantsMatchingType:XCUIElementTypeAny]
      elementMatchingPredicate:predicateToFindFlutterView];
  if (![flutterView waitForExistenceWithTimeout:kSecondsToWaitForFlutterView]) {
    NSLog(@"%@", app.debugDescription);
    XCTFail(@"Failed due to not able to find any flutterView with %@ seconds",
            @(kSecondsToWaitForFlutterView));
  }

  XCTAssertNotNil(flutterView);

  SEL hover = @selector(hover);
  XCTAssertTrue([flutterView respondsToSelector:hover],
                @"If supportsPointerInteraction is true, this should be true too.");
  [flutterView performSelector:hover];
  XCTAssertTrue(
      [app.textFields[@"0,PointerChange.add,device=0,buttons=0"] waitForExistenceWithTimeout:1],
      @"PointerChange.add event did not occur for a hover");
  XCTAssertTrue(
      [app.textFields[@"1,PointerChange.hover,device=0,buttons=0"] waitForExistenceWithTimeout:1],
      @"PointerChange.hover event did not occur for a hover");
  // The number of hover events fired is not always the same
  NSInteger lastHoverSequenceNumber = -1;
  NSPredicate* predicateToFindHoverEvents =
      [NSPredicate predicateWithFormat:@"value ENDSWITH ',PointerChange.hover,device=0,buttons=0'"];
  for (XCUIElement* textField in
       [[app.textFields matchingPredicate:predicateToFindHoverEvents] allElementsBoundByIndex]) {
    NSInteger messageSequenceNumber =
        [[textField.value componentsSeparatedByString:@","] firstObject].integerValue;
    if (messageSequenceNumber > lastHoverSequenceNumber) {
      lastHoverSequenceNumber = messageSequenceNumber;
    }
  }
  XCTAssertNotEqual(lastHoverSequenceNumber, -1,
                    @"PointerChange.hover event did not occur for a hover");
  NSString* removeMessage = [NSString
      stringWithFormat:@"%ld,PointerChange.remove,device=0,buttons=0", lastHoverSequenceNumber + 1];
  XCTAssertTrue([app.textFields[removeMessage] waitForExistenceWithTimeout:1],
                @"PointerChange.remove event did not occur for a hover");
}

- (void)testPointerScroll {
  BOOL supportsPointerInteraction = NO;
  SEL supportsPointerInteractionSelector = @selector(supportsPointerInteraction);
  if ([XCUIDevice.sharedDevice respondsToSelector:supportsPointerInteractionSelector]) {
    supportsPointerInteraction =
        performBoolSelector(XCUIDevice.sharedDevice, supportsPointerInteractionSelector);
  }
  XCTSkipUnless(supportsPointerInteraction, "Device does not support pointer interaction.");
  XCUIApplication* app = [[XCUIApplication alloc] init];
  app.launchArguments = @[ @"--pointer-events" ];
  [app launch];

  NSPredicate* predicateToFindFlutterView =
      [NSPredicate predicateWithFormat:@"identifier BEGINSWITH 'flutter_view'"];
  XCUIElement* flutterView = [[app descendantsMatchingType:XCUIElementTypeAny]
      elementMatchingPredicate:predicateToFindFlutterView];
  if (![flutterView waitForExistenceWithTimeout:kSecondsToWaitForFlutterView]) {
    XCTFail(@"Failed due to not able to find any flutterView with %@ seconds",
            @(kSecondsToWaitForFlutterView));
  }

  XCTAssertNotNil(flutterView);

  SEL scroll = @selector(scrollByDeltaX:deltaY:);
  XCTAssertTrue([flutterView respondsToSelector:scroll],
                @"If supportsPointerInteraction is true, this should be true too.");
  // Need to use NSInvocation in order to send primitive arguments to selector.
  NSInvocation* invocation = [NSInvocation
      invocationWithMethodSignature:[XCUIElement instanceMethodSignatureForSelector:scroll]];
  [invocation setSelector:scroll];
  CGFloat deltaX = 0.0;
  CGFloat deltaY = 1000.0;
  [invocation setArgument:&deltaX atIndex:2];
  [invocation setArgument:&deltaY atIndex:3];
  [invocation invokeWithTarget:flutterView];

  // The hover pointer is observed to be removed by the system after ~3.5 seconds of inactivity.
  // While this is not a documented behavior, it is the only way to test for the removal of the
  // hover pointer. Waiting for 5 seconds will ensure that all events are received before
  // processing.
  XCTestExpectation* sleepExpectation = [self expectationWithDescription:@"never fires"];
  sleepExpectation.inverted = true;
  [self waitForExpectations:@[ sleepExpectation ] timeout:5.0];

  // There are hover events interspersed with the scroll events in a varying order.
  // Ensure the individual orderings are respected without hardcoding the absolute sequence.
  NSMutableDictionary<NSString*, NSMutableArray<NSNumber*>*>* messages =
      [[NSMutableDictionary alloc] init];
  for (XCUIElement* element in [app.textFields allElementsBoundByIndex]) {
    NSString* rawMessage = element.value;
    // Parse out the sequence number
    NSUInteger commaIndex = [rawMessage rangeOfString:@","].location;
    NSInteger messageSequenceNumber =
        [rawMessage substringWithRange:NSMakeRange(0, commaIndex)].integerValue;
    // Parse out the rest of the message
    NSString* message = [rawMessage
        substringWithRange:NSMakeRange(commaIndex + 1, rawMessage.length - (commaIndex + 1))];
    NSMutableArray<NSNumber*>* messageSequenceNumberList = messages[message];
    if (messageSequenceNumberList == nil) {
      messageSequenceNumberList = [[NSMutableArray alloc] init];
      messages[message] = messageSequenceNumberList;
    }
    [messageSequenceNumberList addObject:@(messageSequenceNumber)];
  }
  // The number of hover events is not consistent, there could be one or many.
  int hoverAddedSequenceNumber =
      assertOneMessageAndGetSequenceNumber(messages, @"PointerChange.add,device=0,buttons=0");
  NSMutableArray<NSNumber*>* hoverSequenceNumbers =
      messages[@"PointerChange.hover,device=0,buttons=0"];
  int hoverRemovedSequenceNumber =
      assertOneMessageAndGetSequenceNumber(messages, @"PointerChange.remove,device=0,buttons=0");
  int panZoomAddedSequenceNumber =
      assertOneMessageAndGetSequenceNumber(messages, @"PointerChange.add,device=1,buttons=0");
  int panZoomStartSequenceNumber = assertOneMessageAndGetSequenceNumber(
      messages, @"PointerChange.panZoomStart,device=1,buttons=0");
  // The number of pan/zoom update events is not consistent, there could be one or many.
  NSMutableArray<NSNumber*>* panZoomUpdateSequenceNumbers =
      messages[@"PointerChange.panZoomUpdate,device=1,buttons=0"];
  int panZoomEndSequenceNumber = assertOneMessageAndGetSequenceNumber(
      messages, @"PointerChange.panZoomEnd,device=1,buttons=0");

  XCTAssertGreaterThan(panZoomStartSequenceNumber, panZoomAddedSequenceNumber,
                       @"PanZoomStart occured before pointer was added");
  XCTAssertGreaterThan([[panZoomUpdateSequenceNumbers firstObject] intValue],
                       panZoomStartSequenceNumber, @"PanZoomUpdate occured before PanZoomStart");
  XCTAssertGreaterThan(panZoomEndSequenceNumber,
                       [[panZoomUpdateSequenceNumbers lastObject] intValue],
                       @"PanZoomUpdate occured after PanZoomUpdate");

  XCTAssertGreaterThan([[hoverSequenceNumbers firstObject] intValue], hoverAddedSequenceNumber,
                       @"Hover occured before pointer was added");
  XCTAssertGreaterThan(hoverRemovedSequenceNumber, [[hoverSequenceNumbers lastObject] intValue],
                       @"Hover occured after pointer was removed");
}
#pragma clang diagnostic pop

@end
