// 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 <Metal/Metal.h>
#import <OCMock/OCMock.h>

#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterCompositor.h"
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterView.h"
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterViewProvider.h"
#import "flutter/testing/testing.h"

@interface FlutterViewMockProvider : NSObject <FlutterViewProvider> {
  FlutterView* _defaultView;
}
/**
 * Create a FlutterViewMockProvider with the provided view as the default view.
 */
- (nonnull instancetype)initWithDefaultView:(nonnull FlutterView*)view;
@end

@implementation FlutterViewMockProvider

- (nonnull instancetype)initWithDefaultView:(nonnull FlutterView*)view {
  self = [super init];
  if (self != nil) {
    _defaultView = view;
  }
  return self;
}

- (nullable FlutterView*)viewForId:(FlutterViewId)viewId {
  if (viewId == kFlutterDefaultViewId) {
    return _defaultView;
  }
  return nil;
}

@end

namespace flutter::testing {
namespace {

typedef void (^PresentBlock)(NSArray<FlutterSurfacePresentInfo*>*);

id<FlutterViewProvider> MockViewProvider(PresentBlock onPresent = nil) {
  FlutterView* viewMock = OCMClassMock([FlutterView class]);
  FlutterSurfaceManager* surfaceManagerMock = OCMClassMock([FlutterSurfaceManager class]);
  FlutterSurface* surfaceMock = OCMClassMock([FlutterSurface class]);
  __block id<MTLTexture> textureMock = OCMProtocolMock(@protocol(MTLTexture));

  OCMStub([viewMock surfaceManager]).andReturn(surfaceManagerMock);

  OCMStub([surfaceManagerMock surfaceForSize:CGSize{}])
      .ignoringNonObjectArgs()
      .andDo(^(NSInvocation* invocation) {
        CGSize size;
        [invocation getArgument:&size atIndex:2];
        OCMStub([textureMock width]).andReturn(size.width);
        OCMStub([textureMock height]).andReturn(size.height);
      })
      .andReturn(surfaceMock);

  FlutterMetalTexture texture = {
      .struct_size = sizeof(FlutterMetalTexture),
      .texture_id = 1,
      .texture = (__bridge void*)textureMock,
      .user_data = (__bridge void*)surfaceMock,
      .destruction_callback = nullptr,
  };

  OCMStub([surfaceManagerMock present:[OCMArg any] notify:[OCMArg any]])
      .andDo(^(NSInvocation* invocation) {
        NSArray<FlutterSurfacePresentInfo*>* info;
        [invocation getArgument:&info atIndex:2];
        if (onPresent != nil) {
          onPresent(info);
        }
      });

  OCMStub([surfaceMock asFlutterMetalTexture]).andReturn(texture);

  return [[FlutterViewMockProvider alloc] initWithDefaultView:viewMock];
}
}  // namespace

TEST(FlutterCompositorTest, TestCreate) {
  std::unique_ptr<flutter::FlutterCompositor> macos_compositor =
      std::make_unique<FlutterCompositor>(MockViewProvider(),
                                          /*platform_view_controller*/ nullptr);

  FlutterBackingStore backing_store;
  FlutterBackingStoreConfig config;
  config.struct_size = sizeof(FlutterBackingStoreConfig);
  config.size.width = 800;
  config.size.height = 600;
  macos_compositor->CreateBackingStore(&config, &backing_store);

  ASSERT_EQ(backing_store.type, kFlutterBackingStoreTypeMetal);
  ASSERT_NE(backing_store.metal.texture.texture, nil);
  id<MTLTexture> texture = (__bridge id<MTLTexture>)backing_store.metal.texture.texture;
  ASSERT_EQ(texture.width, 800ul);
  ASSERT_EQ(texture.height, 600ul);
}

TEST(FlutterCompositorTest, TestPresent) {
  __block NSArray<FlutterSurfacePresentInfo*>* presentedSurfaces = nil;

  auto onPresent = ^(NSArray<FlutterSurfacePresentInfo*>* info) {
    presentedSurfaces = info;
  };

  std::unique_ptr<flutter::FlutterCompositor> macos_compositor =
      std::make_unique<FlutterCompositor>(MockViewProvider(onPresent),
                                          /*platform_view_controller*/ nullptr);

  FlutterBackingStore backing_store;
  FlutterBackingStoreConfig config;
  config.struct_size = sizeof(FlutterBackingStoreConfig);
  config.size.width = 800;
  config.size.height = 600;
  macos_compositor->CreateBackingStore(&config, &backing_store);

  FlutterLayer layers[] = {{
      .struct_size = sizeof(FlutterLayer),
      .type = kFlutterLayerContentTypeBackingStore,
      .backing_store = &backing_store,
      .offset = {0, 0},
      .size = {800, 600},
  }};
  const FlutterLayer* layers_ptr = layers;

  macos_compositor->Present(kFlutterDefaultViewId, &layers_ptr, 1);

  ASSERT_EQ(presentedSurfaces.count, 1ul);
}

}  // namespace flutter::testing
