// 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/FlutterSurfaceManager.h"

#import <Metal/Metal.h>

#include <algorithm>

#include "flutter/fml/logging.h"
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterSurface.h"

@implementation FlutterSurfacePresentInfo
@end

@interface FlutterSurfaceManager () {
  id<MTLDevice> _device;
  id<MTLCommandQueue> _commandQueue;
  CALayer* _containingLayer;
  __weak id<FlutterSurfaceManagerDelegate> _delegate;

  // Available (cached) back buffer surfaces. These will be cleared during
  // present and replaced by current frong surfaces.
  FlutterBackBufferCache* _backBufferCache;

  // Surfaces currently used to back visible layers.
  NSMutableArray<FlutterSurface*>* _frontSurfaces;

  // Currently visible layers.
  NSMutableArray<CALayer*>* _layers;

  // Whether to highlight borders of overlay surfaces. Determined by
  // FLTEnableSurfaceDebugInfo value in main bundle Info.plist.
  NSNumber* _enableSurfaceDebugInfo;
  CATextLayer* _infoLayer;

  CFTimeInterval _lastPresentationTime;
}

/**
 * Updates underlying CALayers with the contents of the surfaces to present.
 */
- (void)commit:(NSArray<FlutterSurfacePresentInfo*>*)surfaces;

@end

static NSColor* GetBorderColorForLayer(int layer) {
  NSArray* colors = @[
    [NSColor yellowColor],
    [NSColor cyanColor],
    [NSColor magentaColor],
    [NSColor greenColor],
    [NSColor purpleColor],
    [NSColor orangeColor],
    [NSColor blueColor],
  ];
  return colors[layer % colors.count];
}

/// Creates sublayers for given layer, each one displaying a portion of the
/// of the surface determined by a rectangle in the provided paint region.
static void UpdateContentSubLayers(CALayer* layer,
                                   IOSurfaceRef surface,
                                   CGFloat scale,
                                   CGSize surfaceSize,
                                   NSColor* borderColor,
                                   const std::vector<FlutterRect>& paintRegion) {
  // Adjust sublayer count to paintRegion count.
  while (layer.sublayers.count > paintRegion.size()) {
    [layer.sublayers.lastObject removeFromSuperlayer];
  }

  while (layer.sublayers.count < paintRegion.size()) {
    CALayer* newLayer = [CALayer layer];
    [layer addSublayer:newLayer];
  }

  for (size_t i = 0; i < paintRegion.size(); i++) {
    CALayer* subLayer = [layer.sublayers objectAtIndex:i];
    const auto& rect = paintRegion[i];
    subLayer.frame = CGRectMake(rect.left / scale, rect.top / scale,
                                (rect.right - rect.left) / scale, (rect.bottom - rect.top) / scale);

    double width = surfaceSize.width;
    double height = surfaceSize.height;

    subLayer.contentsRect =
        CGRectMake(rect.left / width, rect.top / height, (rect.right - rect.left) / width,
                   (rect.bottom - rect.top) / height);

    if (borderColor != nil) {
      // Visualize sublayer
      subLayer.borderColor = borderColor.CGColor;
      subLayer.borderWidth = 1.0;
    }

    subLayer.contents = (__bridge id)surface;
  }
}

@implementation FlutterSurfaceManager

- (instancetype)initWithDevice:(id<MTLDevice>)device
                  commandQueue:(id<MTLCommandQueue>)commandQueue
                         layer:(CALayer*)containingLayer
                      delegate:(__weak id<FlutterSurfaceManagerDelegate>)delegate {
  if (self = [super init]) {
    _device = device;
    _commandQueue = commandQueue;
    _containingLayer = containingLayer;
    _delegate = delegate;

    _backBufferCache = [[FlutterBackBufferCache alloc] init];
    _frontSurfaces = [NSMutableArray array];
    _layers = [NSMutableArray array];
  }
  return self;
}

- (FlutterBackBufferCache*)backBufferCache {
  return _backBufferCache;
}

- (NSArray*)frontSurfaces {
  return _frontSurfaces;
}

- (NSArray*)layers {
  return _layers;
}

- (FlutterSurface*)surfaceForSize:(CGSize)size {
  FlutterSurface* surface = [_backBufferCache removeSurfaceForSize:size];
  if (surface == nil) {
    surface = [[FlutterSurface alloc] initWithSize:size device:_device];
  }
  return surface;
}

- (BOOL)enableSurfaceDebugInfo {
  if (_enableSurfaceDebugInfo == nil) {
    _enableSurfaceDebugInfo =
        [[NSBundle mainBundle] objectForInfoDictionaryKey:@"FLTEnableSurfaceDebugInfo"];
    if (_enableSurfaceDebugInfo == nil) {
      _enableSurfaceDebugInfo = @NO;
    }
  }
  return [_enableSurfaceDebugInfo boolValue];
}

- (void)commit:(NSArray<FlutterSurfacePresentInfo*>*)surfaces {
  FML_DCHECK([NSThread isMainThread]);

  // Release all unused back buffer surfaces and replace them with front surfaces.
  [_backBufferCache replaceSurfaces:_frontSurfaces];

  // Front surfaces will be replaced by currently presented surfaces.
  [_frontSurfaces removeAllObjects];
  for (FlutterSurfacePresentInfo* info in surfaces) {
    [_frontSurfaces addObject:info.surface];
  }

  // Add or remove layers to match the count of surfaces to present.
  while (_layers.count > _frontSurfaces.count) {
    [_layers.lastObject removeFromSuperlayer];
    [_layers removeLastObject];
  }
  while (_layers.count < _frontSurfaces.count) {
    CALayer* layer = [CALayer layer];
    [_containingLayer addSublayer:layer];
    [_layers addObject:layer];
  }

  bool enableSurfaceDebugInfo = self.enableSurfaceDebugInfo;

  // Update contents of surfaces.
  for (size_t i = 0; i < surfaces.count; ++i) {
    FlutterSurfacePresentInfo* info = surfaces[i];
    CALayer* layer = _layers[i];
    CGFloat scale = _containingLayer.contentsScale;
    if (i == 0) {
      layer.frame = CGRectMake(info.offset.x / scale, info.offset.y / scale,
                               info.surface.size.width / scale, info.surface.size.height / scale);
      layer.contents = (__bridge id)info.surface.ioSurface;
    } else {
      layer.frame = CGRectZero;
      NSColor* borderColor = enableSurfaceDebugInfo ? GetBorderColorForLayer(i - 1) : nil;
      UpdateContentSubLayers(layer, info.surface.ioSurface, scale, info.surface.size, borderColor,
                             info.paintRegion);
    }
    layer.zPosition = info.zIndex;
  }

  if (enableSurfaceDebugInfo) {
    if (_infoLayer == nil) {
      _infoLayer = [[CATextLayer alloc] init];
      [_containingLayer addSublayer:_infoLayer];
      _infoLayer.fontSize = 15;
      _infoLayer.foregroundColor = [NSColor yellowColor].CGColor;
      _infoLayer.frame = CGRectMake(15, 15, 300, 100);
      _infoLayer.contentsScale = _containingLayer.contentsScale;
      _infoLayer.zPosition = 100000;
    }
    _infoLayer.string = [NSString stringWithFormat:@"Surface count: %li", _layers.count];
  }
}

static CGSize GetRequiredFrameSize(NSArray<FlutterSurfacePresentInfo*>* surfaces) {
  CGSize size = CGSizeZero;
  for (FlutterSurfacePresentInfo* info in surfaces) {
    size = CGSizeMake(std::max(size.width, info.offset.x + info.surface.size.width),
                      std::max(size.height, info.offset.y + info.surface.size.height));
  }
  return size;
}

- (void)presentSurfaces:(NSArray<FlutterSurfacePresentInfo*>*)surfaces
                 atTime:(CFTimeInterval)presentationTime
                 notify:(dispatch_block_t)notify {
  id<MTLCommandBuffer> commandBuffer = [_commandQueue commandBuffer];
  [commandBuffer commit];
  [commandBuffer waitUntilScheduled];

  dispatch_block_t presentBlock = ^{
    // Get the actual dimensions of the frame (relevant for thread synchronizer).
    CGSize size = GetRequiredFrameSize(surfaces);
    [_delegate onPresent:size
               withBlock:^{
                 _lastPresentationTime = presentationTime;
                 [self commit:surfaces];
                 if (notify != nil) {
                   notify();
                 }
               }];
  };

  if (presentationTime > 0) {
    // Enforce frame pacing. It seems that the target timestamp of CVDisplayLink does not
    // exactly correspond to core animation deadline. Especially with 120hz, setting the frame
    // contents too close after previous target timestamp will result in uneven frame pacing.
    // Empirically setting the content in the second half of frame interval seems to work
    // well for both 60hz and 120hz.
    //
    // This schedules a timer on current (raster) thread runloop. Raster thread at
    // this point should be idle (the next frame vsync has not been signalled yet).
    //
    // Alternative could be simply blocking the raster thread, but that would show
    // as a average_frame_rasterizer_time_millis regresson.
    CFTimeInterval minPresentationTime = (presentationTime + _lastPresentationTime) / 2.0;
    CFTimeInterval now = CACurrentMediaTime();
    if (now < minPresentationTime) {
      NSTimer* timer = [NSTimer timerWithTimeInterval:minPresentationTime - now
                                              repeats:NO
                                                block:^(NSTimer* timer) {
                                                  presentBlock();
                                                }];
      [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
      return;
    }
  }
  presentBlock();
}

@end

// Cached back buffers will be released after kIdleDelay if there is no activity.
static const double kIdleDelay = 1.0;

@interface FlutterBackBufferCache () {
  NSMutableArray<FlutterSurface*>* _surfaces;
}

@end

@implementation FlutterBackBufferCache

- (instancetype)init {
  if (self = [super init]) {
    self->_surfaces = [[NSMutableArray alloc] init];
  }
  return self;
}

- (nullable FlutterSurface*)removeSurfaceForSize:(CGSize)size {
  @synchronized(self) {
    for (FlutterSurface* surface in _surfaces) {
      if (CGSizeEqualToSize(surface.size, size)) {
        // By default ARC doesn't retain enumeration iteration variables.
        FlutterSurface* res = surface;
        [_surfaces removeObject:surface];
        return res;
      }
    }
    return nil;
  }
}

- (void)replaceSurfaces:(nonnull NSArray<FlutterSurface*>*)surfaces {
  @synchronized(self) {
    [_surfaces removeAllObjects];
    [_surfaces addObjectsFromArray:surfaces];
  }

  // performSelector:withObject:afterDelay needs to be performed on RunLoop thread
  [self performSelectorOnMainThread:@selector(reschedule) withObject:nil waitUntilDone:NO];
}

- (NSUInteger)count {
  @synchronized(self) {
    return _surfaces.count;
  }
}

- (void)onIdle {
  @synchronized(self) {
    [_surfaces removeAllObjects];
  }
}

- (void)reschedule {
  [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(onIdle) object:nil];
  [self performSelector:@selector(onIdle) withObject:nil afterDelay:kIdleDelay];
}

- (void)dealloc {
  [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(onIdle) object:nil];
}

@end
