// 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 "impeller/renderer/backend/vulkan/swapchain_vk.h"

#include "fml/logging.h"
#include "impeller/base/validation.h"
#include "impeller/renderer/backend/vulkan/formats_vk.h"

namespace impeller {

std::unique_ptr<SwapchainVK> SwapchainVK::Create(vk::Device device,
                                                 vk::SurfaceKHR surface,
                                                 SwapchainDetailsVK& details) {
  vk::SurfaceFormatKHR surface_format = details.PickSurfaceFormat();
  vk::PresentModeKHR present_mode = details.PickPresentationMode();
  vk::Extent2D extent = details.PickExtent();

  vk::SwapchainCreateInfoKHR create_info;
  create_info.surface = surface;
  create_info.imageFormat = surface_format.format;
  create_info.imageColorSpace = surface_format.colorSpace;
  create_info.presentMode = present_mode;
  create_info.imageExtent = extent;

  create_info.minImageCount = details.GetImageCount();
  create_info.imageArrayLayers = 1;
  create_info.imageUsage = vk::ImageUsageFlagBits::eColorAttachment;
  create_info.preTransform = details.GetTransform();
  create_info.compositeAlpha = details.PickCompositeAlpha();
  create_info.clipped = VK_TRUE;

  create_info.imageSharingMode = vk::SharingMode::eExclusive;
  {
    // TODO (kaushikiska): This needs to change if graphics queue is not the
    // same as present queue which is rare.
    create_info.queueFamilyIndexCount = 0;
    create_info.pQueueFamilyIndices = nullptr;
  }

  create_info.oldSwapchain = nullptr;

  auto swapchain_res = device.createSwapchainKHRUnique(create_info);
  if (swapchain_res.result != vk::Result::eSuccess) {
    VALIDATION_LOG << "Failed to create swapchain: "
                   << vk::to_string(swapchain_res.result);
    return nullptr;
  }

  auto swapchain = std::make_unique<SwapchainVK>(
      device, std::move(swapchain_res.value), surface_format.format, extent);
  if (!swapchain->CreateSwapchainImages()) {
    VALIDATION_LOG << "Failed to create swapchain images.";
    return nullptr;
  }

  return swapchain;
}

bool SwapchainVK::CreateSwapchainImages() {
  FML_DCHECK(swapchain_images_.empty()) << "Swapchain images already created";
  auto res = device_.getSwapchainImagesKHR(*swapchain_);
  if (res.result != vk::Result::eSuccess) {
    FML_CHECK(false) << "Failed to get swapchain images: "
                     << vk::to_string(res.result);
    return false;
  }

  std::vector<vk::Image> images = res.value;
  for (const auto& image : images) {
    vk::ImageViewCreateInfo create_info;
    create_info.image = image;
    create_info.viewType = vk::ImageViewType::e2D;
    create_info.format = image_format_;

    create_info.components.r = vk::ComponentSwizzle::eIdentity;
    create_info.components.g = vk::ComponentSwizzle::eIdentity;
    create_info.components.b = vk::ComponentSwizzle::eIdentity;
    create_info.components.a = vk::ComponentSwizzle::eIdentity;

    // TODO (kaushikiska): This has to match up to the texture we will be
    // rendering to (TextureVK).
    create_info.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor;
    create_info.subresourceRange.baseMipLevel = 0;
    create_info.subresourceRange.levelCount = 1;
    create_info.subresourceRange.baseArrayLayer = 0;
    create_info.subresourceRange.layerCount = 1;

    auto img_view_res = device_.createImageViewUnique(create_info);
    if (img_view_res.result != vk::Result::eSuccess) {
      VALIDATION_LOG << "Failed to create image view: "
                     << vk::to_string(img_view_res.result);
      return false;
    }

    swapchain_images_.push_back(std::make_unique<SwapchainImageVK>(
        image, std::move(img_view_res.value), image_format_, extent_));
  }

  return true;
}

SwapchainVK::SwapchainVK(vk::Device device,
                         vk::UniqueSwapchainKHR swapchain,
                         vk::Format image_format,
                         vk::Extent2D extent)
    : device_(device),
      swapchain_(std::move(swapchain)),
      image_format_(image_format),
      extent_(extent) {}

SwapchainVK::~SwapchainVK() = default;

SwapchainImageVK::SwapchainImageVK(vk::Image image,
                                   vk::UniqueImageView image_view,
                                   vk::Format image_format,
                                   vk::Extent2D extent)
    : image_(image),
      image_view_(std::move(image_view)),
      image_format_(image_format),
      extent_(extent) {}

vk::SwapchainKHR SwapchainVK::GetSwapchain() const {
  return *swapchain_;
}

SwapchainImageVK* SwapchainVK::GetSwapchainImage(uint32_t image_index) const {
  FML_DCHECK(image_index < swapchain_images_.size());
  return swapchain_images_[image_index].get();
}

PixelFormat SwapchainImageVK::GetPixelFormat() const {
  return ToPixelFormat(image_format_);
}

ISize SwapchainImageVK::GetSize() const {
  return ISize(extent_.width, extent_.height);
}

vk::Image SwapchainImageVK::GetImage() const {
  return image_;
}

vk::ImageView SwapchainImageVK::GetImageView() const {
  return image_view_.get();
}

SwapchainImageVK::~SwapchainImageVK() = default;

}  // namespace impeller
