// 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;
  std::cout << "inserting texture with id: " << texture_id << std::endl;

  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
