// 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/macos/framework/Source/FlutterView.h"

#import <Metal/Metal.h>

#import "flutter/testing/testing.h"

constexpr int64_t kImplicitViewId = 0ll;

@interface TestFlutterViewDelegate : NSObject <FlutterViewDelegate>

@end

@implementation TestFlutterViewDelegate

- (void)viewDidReshape:(nonnull NSView*)view {
}

- (BOOL)viewShouldAcceptFirstResponder:(NSView*)view {
  return YES;
}

@end

TEST(FlutterView, ShouldInheritContentsScaleReturnsYes) {
  id<MTLDevice> device = MTLCreateSystemDefaultDevice();
  id<MTLCommandQueue> queue = [device newCommandQueue];
  TestFlutterViewDelegate* delegate = [[TestFlutterViewDelegate alloc] init];
  FlutterThreadSynchronizer* threadSynchronizer = [[FlutterThreadSynchronizer alloc] init];
  FlutterView* view = [[FlutterView alloc] initWithMTLDevice:device
                                                commandQueue:queue
                                                    delegate:delegate
                                          threadSynchronizer:threadSynchronizer
                                              viewIdentifier:kImplicitViewId];
  EXPECT_EQ([view layer:view.layer shouldInheritContentsScale:3.0 fromWindow:view.window], YES);
}

@interface TestFlutterView : FlutterView

@property(readwrite, nonatomic) NSView* (^onHitTest)(NSPoint point);

@end

@implementation TestFlutterView

@synthesize onHitTest;

- (NSView*)hitTest:(NSPoint)point {
  return self.onHitTest(point);
}

- (void)reshaped {
  // Disable resize synchronization for testing.
}

@end

@interface TestCursor : NSCursor
@property(readwrite, nonatomic) BOOL setCalled;
@end

@implementation TestCursor

- (void)set {
  self.setCalled = YES;
}

@end

TEST(FlutterView, CursorUpdateDoesHitTest) {
  id<MTLDevice> device = MTLCreateSystemDefaultDevice();
  id<MTLCommandQueue> queue = [device newCommandQueue];
  TestFlutterViewDelegate* delegate = [[TestFlutterViewDelegate alloc] init];
  FlutterThreadSynchronizer* threadSynchronizer = [[FlutterThreadSynchronizer alloc] init];
  TestFlutterView* view = [[TestFlutterView alloc] initWithMTLDevice:device
                                                        commandQueue:queue
                                                            delegate:delegate
                                                  threadSynchronizer:threadSynchronizer
                                                      viewIdentifier:kImplicitViewId];
  NSWindow* window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 800, 600)
                                                 styleMask:NSBorderlessWindowMask
                                                   backing:NSBackingStoreBuffered
                                                     defer:NO];

  TestCursor* cursor = [[TestCursor alloc] init];

  window.contentView = view;
  __weak NSView* weakView = view;
  __block BOOL hitTestCalled = NO;
  __block NSPoint hitTestCoordinate = NSZeroPoint;
  view.onHitTest = ^NSView*(NSPoint point) {
    hitTestCalled = YES;
    hitTestCoordinate = point;
    return weakView;
  };
  NSEvent* mouseEvent = [NSEvent mouseEventWithType:NSEventTypeMouseMoved
                                           location:NSMakePoint(100, 100)
                                      modifierFlags:0
                                          timestamp:0
                                       windowNumber:0
                                            context:nil
                                        eventNumber:0
                                         clickCount:0
                                           pressure:0];
  [view didUpdateMouseCursor:cursor];
  [view cursorUpdate:mouseEvent];

  EXPECT_TRUE(hitTestCalled);
  // The hit test coordinate should be in the window coordinate system.
  EXPECT_TRUE(CGPointEqualToPoint(hitTestCoordinate, CGPointMake(100, 500)));
  EXPECT_TRUE(cursor.setCalled);
}

TEST(FlutterView, CursorUpdateDoesNotOverridePlatformView) {
  id<MTLDevice> device = MTLCreateSystemDefaultDevice();
  id<MTLCommandQueue> queue = [device newCommandQueue];
  TestFlutterViewDelegate* delegate = [[TestFlutterViewDelegate alloc] init];
  FlutterThreadSynchronizer* threadSynchronizer = [[FlutterThreadSynchronizer alloc] init];
  TestFlutterView* view = [[TestFlutterView alloc] initWithMTLDevice:device
                                                        commandQueue:queue
                                                            delegate:delegate
                                                  threadSynchronizer:threadSynchronizer
                                                      viewIdentifier:kImplicitViewId];
  NSWindow* window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 800, 600)
                                                 styleMask:NSBorderlessWindowMask
                                                   backing:NSBackingStoreBuffered
                                                     defer:NO];

  TestCursor* cursor = [[TestCursor alloc] init];

  NSView* platformView = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100)];

  window.contentView = view;
  __block BOOL hitTestCalled = NO;
  __block NSPoint hitTestCoordinate = NSZeroPoint;
  view.onHitTest = ^NSView*(NSPoint point) {
    hitTestCalled = YES;
    hitTestCoordinate = point;
    return platformView;
  };
  NSEvent* mouseEvent = [NSEvent mouseEventWithType:NSEventTypeMouseMoved
                                           location:NSMakePoint(100, 100)
                                      modifierFlags:0
                                          timestamp:0
                                       windowNumber:0
                                            context:nil
                                        eventNumber:0
                                         clickCount:0
                                           pressure:0];
  [view didUpdateMouseCursor:cursor];
  [view cursorUpdate:mouseEvent];

  EXPECT_TRUE(hitTestCalled);
  // The hit test coordinate should be in the window coordinate system.
  EXPECT_TRUE(CGPointEqualToPoint(hitTestCoordinate, CGPointMake(100, 500)));
  EXPECT_FALSE(cursor.setCalled);
}
