// 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/toolkit/android/hardware_buffer.h"

#include "impeller/base/validation.h"

namespace impeller::android {

static AHardwareBuffer_Format ToAHardwareBufferFormat(
    HardwareBufferFormat format) {
  switch (format) {
    case HardwareBufferFormat::kR8G8B8A8UNormInt:
      return AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
  }
  FML_UNREACHABLE();
}

static AHardwareBuffer_Desc ToAHardwareBufferDesc(
    const HardwareBufferDescriptor& desc) {
  AHardwareBuffer_Desc ahb_desc = {};
  ahb_desc.width = desc.size.width;
  ahb_desc.height = desc.size.height;
  ahb_desc.format = ToAHardwareBufferFormat(desc.format);
  ahb_desc.layers = 1u;
  if (desc.usage & HardwareBufferUsageFlags::kFrameBufferAttachment) {
    ahb_desc.usage |= AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER;
  }
  if (desc.usage & HardwareBufferUsageFlags::kCompositorOverlay) {
    ahb_desc.usage |= AHARDWAREBUFFER_USAGE_COMPOSER_OVERLAY;
  }
  if (desc.usage & HardwareBufferUsageFlags::kSampledImage) {
    ahb_desc.usage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
  }
  return ahb_desc;
}

bool HardwareBufferDescriptor::IsAllocatable() const {
  const auto desc = ToAHardwareBufferDesc(*this);
  return GetProcTable().AHardwareBuffer_isSupported(&desc) != 0u;
}

HardwareBuffer::HardwareBuffer(HardwareBufferDescriptor descriptor)
    : descriptor_(descriptor),
      android_descriptor_(ToAHardwareBufferDesc(descriptor_)) {
  if (!descriptor_.IsAllocatable()) {
    VALIDATION_LOG << "The hardware buffer descriptor is not allocatable.";
    return;
  }
  const auto& proc_table = GetProcTable();

  AHardwareBuffer* buffer = nullptr;
  if (auto result =
          proc_table.AHardwareBuffer_allocate(&android_descriptor_, &buffer);
      result != 0 || buffer == nullptr) {
    VALIDATION_LOG << "Could not allocate hardware buffer. Error: " << result;
    return;
  }
  buffer_.reset(buffer);
  is_valid_ = true;
}

HardwareBuffer::~HardwareBuffer() = default;

bool HardwareBuffer::IsValid() const {
  return is_valid_;
}

AHardwareBuffer* HardwareBuffer::GetHandle() const {
  return buffer_.get();
}

HardwareBufferDescriptor HardwareBufferDescriptor::MakeForSwapchainImage(
    const ISize& size) {
  HardwareBufferDescriptor desc;
  desc.format = HardwareBufferFormat::kR8G8B8A8UNormInt;
  // Zero sized hardware buffers cannot be allocated.
  desc.size = size.Max(ISize{1u, 1u});
  desc.usage = HardwareBufferUsageFlags::kFrameBufferAttachment |
               HardwareBufferUsageFlags::kCompositorOverlay |
               HardwareBufferUsageFlags::kSampledImage;
  return desc;
}

const HardwareBufferDescriptor& HardwareBuffer::GetDescriptor() const {
  return descriptor_;
}

const AHardwareBuffer_Desc& HardwareBuffer::GetAndroidDescriptor() const {
  return android_descriptor_;
}

bool HardwareBuffer::IsAvailableOnPlatform() {
  return GetProcTable().IsValid() && GetProcTable().AHardwareBuffer_isSupported;
}

std::optional<uint64_t> HardwareBuffer::GetSystemUniqueID() const {
  return GetSystemUniqueID(GetHandle());
}

std::optional<uint64_t> HardwareBuffer::GetSystemUniqueID(
    AHardwareBuffer* buffer) {
  if (!GetProcTable().AHardwareBuffer_getId) {
    return std::nullopt;
  }
  uint64_t out_id = 0u;
  if (GetProcTable().AHardwareBuffer_getId(buffer, &out_id) != 0) {
    return std::nullopt;
  }
  return out_id;
}

std::optional<AHardwareBuffer_Desc> HardwareBuffer::Describe(
    AHardwareBuffer* buffer) {
  if (!buffer || !GetProcTable().AHardwareBuffer_describe) {
    return std::nullopt;
  }
  AHardwareBuffer_Desc desc = {};
  GetProcTable().AHardwareBuffer_describe(buffer, &desc);
  return desc;
}

}  // namespace impeller::android
