// 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.

#include "flutter/testing/test_metal_context.h"

#include <Metal/Metal.h>
#include <iostream>

#include "flutter/fml/logging.h"
#include "flutter/fml/platform/darwin/scoped_nsobject.h"
#include "third_party/skia/include/core/SkSurface.h"

namespace flutter {

TestMetalContext::TestMetalContext() {
  auto device = fml::scoped_nsprotocol{[MTLCreateSystemDefaultDevice() retain]};
  if (!device) {
    FML_LOG(ERROR) << "Could not acquire Metal device.";
    return;
  }

  auto command_queue = fml::scoped_nsobject{[device.get() newCommandQueue]};
  if (!command_queue) {
    FML_LOG(ERROR) << "Could not create the default command queue.";
    return;
  }

  [command_queue.get() setLabel:@"Flutter Test Queue"];

  // Skia expect arguments to `MakeMetal` transfer ownership of the reference in for release later
  // when the GrDirectContext is collected.
  skia_context_ = GrDirectContext::MakeMetal([device.get() retain], [command_queue.get() retain]);
  if (!skia_context_) {
    FML_LOG(ERROR) << "Could not create the GrDirectContext from the Metal Device "
                      "and command queue.";
  }

  device_ = [device.get() retain];
  command_queue_ = [command_queue.get() retain];
}

TestMetalContext::~TestMetalContext() {
  std::scoped_lock lock(textures_mutex);
  textures_.clear();
  if (device_) {
    [(__bridge id)device_ release];
  }
  if (command_queue_) {
    [(__bridge id)command_queue_ release];
  }
}

void* TestMetalContext::GetMetalDevice() const {
  return device_;
}

void* TestMetalContext::GetMetalCommandQueue() const {
  return command_queue_;
}

sk_sp<GrDirectContext> TestMetalContext::GetSkiaContext() const {
  return skia_context_;
}

TestMetalContext::TextureInfo TestMetalContext::CreateMetalTexture(const SkISize& size) {
  std::scoped_lock lock(textures_mutex);
  auto texture_descriptor = fml::scoped_nsobject{
      [[MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatBGRA8Unorm
                                                          width:size.width()
                                                         height:size.height()
                                                      mipmapped:NO] retain]};

  // The most pessimistic option and disables all optimizations but allows tests
  // the most flexible access to the surface. They may read and write to the
  // surface from shaders or use as a pixel view.
  texture_descriptor.get().usage = MTLTextureUsageUnknown;

  if (!texture_descriptor) {
    FML_CHECK(false) << "Invalid texture descriptor.";
    return {.texture_id = -1, .texture = nullptr};
  }

  id<MTLDevice> device = (__bridge id<MTLDevice>)GetMetalDevice();
  sk_cf_obj<void*> texture =
      sk_cf_obj<void*>{[[device newTextureWithDescriptor:texture_descriptor.get()] retain]};

  if (!texture) {
    FML_CHECK(false) << "Could not create texture from texture descriptor.";
    return {.texture_id = -1, .texture = nullptr};
  }

  const int64_t texture_id = texture_id_ctr_++;
  textures_[texture_id] = texture;

  return {
      .texture_id = texture_id,
      .texture = texture.get(),
  };
}

// Don't remove the texture from the map here.
bool TestMetalContext::Present(int64_t texture_id) {
  std::scoped_lock lock(textures_mutex);
  if (textures_.find(texture_id) == textures_.end()) {
    return false;
  } else {
    return true;
  }
}

TestMetalContext::TextureInfo TestMetalContext::GetTextureInfo(int64_t texture_id) {
  std::scoped_lock lock(textures_mutex);
  if (textures_.find(texture_id) == textures_.end()) {
    FML_CHECK(false) << "Invalid texture id: " << texture_id;
    return {.texture_id = -1, .texture = nullptr};
  } else {
    return {
        .texture_id = texture_id,
        .texture = textures_[texture_id].get(),
    };
  }
}

}  // namespace flutter
