/*
 *  Copyright 2022 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "modules/desktop_capture/screen_capturer_fuchsia.h"

#include <fuchsia/sysmem2/cpp/fidl.h>
#include <fuchsia/ui/composition/cpp/fidl.h>
#include <fuchsia/ui/display/singleton/cpp/fidl.h>
#include <lib/sys/cpp/component_context.h>

#include <algorithm>
#include <cstdint>
#include <memory>
#include <string>
#include <utility>

#include "modules/desktop_capture/blank_detector_desktop_capturer_wrapper.h"
#include "modules/desktop_capture/desktop_capture_options.h"
#include "modules/desktop_capture/desktop_capture_types.h"
#include "modules/desktop_capture/desktop_capturer.h"
#include "modules/desktop_capture/desktop_frame.h"
#include "modules/desktop_capture/desktop_geometry.h"
#include "modules/desktop_capture/fallback_desktop_capturer_wrapper.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
#include "rtc_base/numerics/divide_round.h"
#include "rtc_base/time_utils.h"

namespace webrtc {

namespace {

static constexpr uint32_t kMinBufferCount = 2;
static constexpr uint32_t kFuchsiaBytesPerPixel = 4;
static constexpr DesktopCapturer::SourceId kFuchsiaScreenId = 1;
// 500 milliseconds
static constexpr zx::duration kEventDelay = zx::msec(500);
static constexpr fuchsia::images2::ColorSpace kSRGBColorSpace =
    fuchsia::images2::ColorSpace::SRGB;
static constexpr fuchsia::images2::PixelFormat kBGRA32PixelFormatType =
    fuchsia::images2::PixelFormat::B8G8R8A8;

// Round |value| up to the closest multiple of |multiple|
size_t RoundUpToMultiple(size_t value, size_t multiple) {
  return DivideRoundUp(value, multiple) * multiple;
}

}  // namespace

std::unique_ptr<DesktopCapturer> DesktopCapturer::CreateRawScreenCapturer(
    const DesktopCaptureOptions& options) {
  std::unique_ptr<ScreenCapturerFuchsia> capturer(new ScreenCapturerFuchsia());
  return capturer;
}

ScreenCapturerFuchsia::ScreenCapturerFuchsia()
    : component_context_(sys::ComponentContext::Create()) {}

ScreenCapturerFuchsia::~ScreenCapturerFuchsia() {
  // unmap virtual memory mapped pointers
  uint32_t virt_mem_bytes =
      buffer_collection_info_.settings().buffer_settings().size_bytes();
  for (uint32_t buffer_index = 0;
       buffer_index < buffer_collection_info_.buffers().size();
       buffer_index++) {
    uintptr_t address =
        reinterpret_cast<uintptr_t>(virtual_memory_mapped_addrs_[buffer_index]);
    zx_status_t status = zx::vmar::root_self()->unmap(address, virt_mem_bytes);
    RTC_DCHECK(status == ZX_OK);
  }
}

void ScreenCapturerFuchsia::Start(Callback* callback) {
  RTC_DCHECK(!callback_);
  RTC_DCHECK(callback);
  callback_ = callback;

  fatal_error_ = false;

  SetupBuffers();
}

void ScreenCapturerFuchsia::CaptureFrame() {
  if (fatal_error_) {
    callback_->OnCaptureResult(Result::ERROR_PERMANENT, nullptr);
    return;
  }

  int64_t capture_start_time_nanos = TimeNanos();

  zx::event event;
  zx::event dup;
  zx_status_t status = zx::event::create(0, &event);
  if (status != ZX_OK) {
    RTC_LOG(LS_ERROR) << "Failed to create event: " << status;
    callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr);
    return;
  }
  event.duplicate(ZX_RIGHT_SAME_RIGHTS, &dup);

  fuchsia::ui::composition::GetNextFrameArgs next_frame_args;
  next_frame_args.set_event(std::move(dup));

  fuchsia::ui::composition::ScreenCapture_GetNextFrame_Result result;
  screen_capture_->GetNextFrame(std::move(next_frame_args), &result);
  if (result.is_err()) {
    RTC_LOG(LS_ERROR) << "fuchsia.ui.composition.GetNextFrame() failed: "
                      << result.err() << "\n";
    callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr);
    return;
  }

  status = event.wait_one(ZX_EVENT_SIGNALED, zx::deadline_after(kEventDelay),
                          nullptr);
  if (status != ZX_OK) {
    RTC_LOG(LS_ERROR) << "Timed out waiting for ScreenCapture to render frame: "
                      << status;
    callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr);
    return;
  }
  uint32_t buffer_index = result.response().buffer_id();

  // TODO(bugs.webrtc.org/14097): Use SharedMemoryDesktopFrame and
  // ScreenCaptureFrameQueue
  std::unique_ptr<BasicDesktopFrame> frame(
      new BasicDesktopFrame(DesktopSize(width_, height_)));

  uint32_t pixels_per_row = GetPixelsPerRow(
      buffer_collection_info_.settings().image_format_constraints());
  uint32_t stride = kFuchsiaBytesPerPixel * pixels_per_row;
  frame->CopyPixelsFrom(virtual_memory_mapped_addrs_[buffer_index], stride,
                        DesktopRect::MakeWH(width_, height_));
  // Mark the whole screen as having been updated.
  frame->mutable_updated_region()->SetRect(
      DesktopRect::MakeWH(width_, height_));

  fuchsia::ui::composition::ScreenCapture_ReleaseFrame_Result release_result;
  screen_capture_->ReleaseFrame(buffer_index, &release_result);
  if (release_result.is_err()) {
    RTC_LOG(LS_ERROR) << "fuchsia.ui.composition.ReleaseFrame() failed: "
                      << release_result.err();
  }

  int capture_time_ms =
      (TimeNanos() - capture_start_time_nanos) / kNumNanosecsPerMillisec;
  frame->set_capture_time_ms(capture_time_ms);
  callback_->OnCaptureResult(Result::SUCCESS, std::move(frame));
}

bool ScreenCapturerFuchsia::GetSourceList(SourceList* screens) {
  RTC_DCHECK(screens->size() == 0);
  // Fuchsia only supports single monitor display at this point
  screens->push_back({kFuchsiaScreenId, std::string("Fuchsia monitor")});
  return true;
}

bool ScreenCapturerFuchsia::SelectSource(SourceId id) {
  if (id == kFuchsiaScreenId || id == kFullDesktopScreenId) {
    return true;
  }
  return false;
}

fuchsia::sysmem2::BufferCollectionConstraints
ScreenCapturerFuchsia::GetBufferConstraints() {
  fuchsia::sysmem2::BufferCollectionConstraints constraints;
  constraints.mutable_usage()->set_cpu(fuchsia::sysmem2::CPU_USAGE_READ |
                                       fuchsia::sysmem2::CPU_USAGE_WRITE);
  constraints.set_min_buffer_count(kMinBufferCount);

  auto& memory_constraints = *constraints.mutable_buffer_memory_constraints();
  memory_constraints.set_ram_domain_supported(true);
  memory_constraints.set_cpu_domain_supported(true);

  fuchsia::sysmem2::ImageFormatConstraints& image_constraints =
      constraints.mutable_image_format_constraints()->emplace_back();
  image_constraints.mutable_color_spaces()->emplace_back(kSRGBColorSpace);
  image_constraints.set_pixel_format(kBGRA32PixelFormatType);
  image_constraints.set_pixel_format_modifier(
      fuchsia::images2::PixelFormatModifier::LINEAR);

  image_constraints.set_required_min_size(
      fuchsia::math::SizeU{width_, height_});
  image_constraints.set_required_max_size(
      fuchsia::math::SizeU{width_, height_});

  image_constraints.set_bytes_per_row_divisor(kFuchsiaBytesPerPixel);

  return constraints;
}

void ScreenCapturerFuchsia::SetupBuffers() {
  fuchsia::ui::display::singleton::InfoSyncPtr display_info;
  zx_status_t status =
      component_context_->svc()->Connect(display_info.NewRequest());
  if (status != ZX_OK) {
    fatal_error_ = true;
    RTC_LOG(LS_ERROR)
        << "Failed to connect to fuchsia.ui.display.singleton.Info: " << status;
    return;
  }

  fuchsia::ui::display::singleton::Metrics metrics;
  status = display_info->GetMetrics(&metrics);
  if (status != ZX_OK) {
    fatal_error_ = true;
    RTC_LOG(LS_ERROR) << "Failed to connect to get display dimensions: "
                      << status;
    return;
  }
  width_ = metrics.extent_in_px().width;
  height_ = metrics.extent_in_px().height;

  status = component_context_->svc()->Connect(sysmem_allocator_.NewRequest());
  if (status != ZX_OK) {
    fatal_error_ = true;
    RTC_LOG(LS_ERROR) << "Failed to connect to fuchsia.sysmem2.Allocator: "
                      << status;
    return;
  }

  fuchsia::sysmem2::BufferCollectionTokenSyncPtr sysmem_token;
  status = sysmem_allocator_->AllocateSharedCollection(
      std::move(fuchsia::sysmem2::AllocatorAllocateSharedCollectionRequest{}
                    .set_token_request(sysmem_token.NewRequest())));
  if (status != ZX_OK) {
    fatal_error_ = true;
    RTC_LOG(LS_ERROR)
        << "fuchsia.sysmem2.Allocator.AllocateSharedCollection() failed: "
        << status;
    return;
  }

  fuchsia::sysmem2::BufferCollectionTokenSyncPtr flatland_token;
  status = sysmem_token->Duplicate(
      std::move(fuchsia::sysmem2::BufferCollectionTokenDuplicateRequest{}
                    .set_rights_attenuation_mask(ZX_RIGHT_SAME_RIGHTS)
                    .set_token_request(flatland_token.NewRequest())));
  if (status != ZX_OK) {
    fatal_error_ = true;
    RTC_LOG(LS_ERROR)
        << "fuchsia.sysmem2.BufferCollectionToken.Duplicate() failed: "
        << status;
    return;
  }

  fuchsia::sysmem2::Node_Sync_Result sync_result;
  status = sysmem_token->Sync(&sync_result);
  if (status != ZX_OK) {
    fatal_error_ = true;
    RTC_LOG(LS_ERROR) << "fuchsia.sysmem2.BufferCollectionToken.Sync() failed: "
                      << status;
    return;
  }

  status = sysmem_allocator_->BindSharedCollection(
      std::move(fuchsia::sysmem2::AllocatorBindSharedCollectionRequest{}
                    .set_token(std::move(sysmem_token))
                    .set_buffer_collection_request(collection_.NewRequest())));
  if (status != ZX_OK) {
    fatal_error_ = true;
    RTC_LOG(LS_ERROR)
        << "fuchsia.sysmem2.Allocator.BindSharedCollection() failed: "
        << status;
    return;
  }

  status = collection_->SetConstraints(std::move(
      fuchsia::sysmem2::BufferCollectionSetConstraintsRequest{}.set_constraints(
          GetBufferConstraints())));
  if (status != ZX_OK) {
    fatal_error_ = true;
    RTC_LOG(LS_ERROR)
        << "fuchsia.sysmem2.BufferCollection.SetConstraints() failed: "
        << status;
    return;
  }

  fuchsia::ui::composition::BufferCollectionImportToken import_token;
  fuchsia::ui::composition::BufferCollectionExportToken export_token;
  status = zx::eventpair::create(0, &export_token.value, &import_token.value);
  if (status != ZX_OK) {
    fatal_error_ = true;
    RTC_LOG(LS_ERROR)
        << "Failed to create BufferCollection import and export tokens: "
        << status;
    return;
  }

  status = component_context_->svc()->Connect(flatland_allocator_.NewRequest());
  if (status != ZX_OK) {
    fatal_error_ = true;
    RTC_LOG(LS_ERROR) << "Failed to connect to Flatland Allocator: " << status;
    return;
  }

  fuchsia::ui::composition::RegisterBufferCollectionArgs buffer_collection_args;
  buffer_collection_args.set_export_token(std::move(export_token));
  buffer_collection_args.set_buffer_collection_token2(
      std::move(flatland_token));
  buffer_collection_args.set_usage(
      fuchsia::ui::composition::RegisterBufferCollectionUsage::SCREENSHOT);

  fuchsia::ui::composition::Allocator_RegisterBufferCollection_Result
      buffer_collection_result;
  flatland_allocator_->RegisterBufferCollection(
      std::move(buffer_collection_args), &buffer_collection_result);
  if (buffer_collection_result.is_err()) {
    fatal_error_ = true;
    RTC_LOG(LS_ERROR) << "fuchsia.ui.composition.Allocator."
                         "RegisterBufferCollection() failed.";
    return;
  }

  fuchsia::sysmem2::BufferCollection_WaitForAllBuffersAllocated_Result
      wait_result;
  status = collection_->WaitForAllBuffersAllocated(&wait_result);
  if (status != ZX_OK) {
    fatal_error_ = true;
    RTC_LOG(LS_ERROR) << "Failed to wait for buffer collection info: "
                      << status;
    return;
  }
  if (!wait_result.is_response()) {
    if (wait_result.is_framework_err()) {
      RTC_LOG(LS_ERROR)
          << "Failed to allocate buffer collection (framework_err): "
          << fidl::ToUnderlying(wait_result.framework_err());
    } else {
      RTC_LOG(LS_ERROR) << "Failed to allocate buffer collection (err): "
                        << static_cast<uint32_t>(wait_result.err());
    }
    fatal_error_ = true;
    return;
  }
  buffer_collection_info_ =
      std::move(*wait_result.response().mutable_buffer_collection_info());

  status = collection_->Release();
  if (status != ZX_OK) {
    fatal_error_ = true;
    RTC_LOG(LS_ERROR) << "Failed to close buffer collection token: " << status;
    return;
  }

  status = component_context_->svc()->Connect(screen_capture_.NewRequest());
  if (status != ZX_OK) {
    fatal_error_ = true;
    RTC_LOG(LS_ERROR) << "Failed to connect to Screen Capture: " << status;
    return;
  }

  // Configure buffers in ScreenCapture client.
  fuchsia::ui::composition::ScreenCaptureConfig configure_args;
  configure_args.set_import_token(std::move(import_token));
  configure_args.set_buffer_count(buffer_collection_info_.buffers().size());
  configure_args.set_size({width_, height_});

  fuchsia::ui::composition::ScreenCapture_Configure_Result configure_result;
  screen_capture_->Configure(std::move(configure_args), &configure_result);
  if (configure_result.is_err()) {
    fatal_error_ = true;
    RTC_LOG(LS_ERROR)
        << "fuchsia.ui.composition.ScreenCapture.Configure() failed: "
        << configure_result.err();
    return;
  }

  // We have a collection of virtual memory objects which the ScreenCapture
  // client will write the frame data to when requested. We map each of these
  // onto a pointer stored in virtual_memory_mapped_addrs_ which we can use to
  // access this data.
  uint32_t virt_mem_bytes =
      buffer_collection_info_.settings().buffer_settings().size_bytes();
  RTC_DCHECK(virt_mem_bytes > 0);
  for (uint32_t buffer_index = 0;
       buffer_index < buffer_collection_info_.buffers().size();
       buffer_index++) {
    const zx::vmo& virt_mem =
        buffer_collection_info_.buffers()[buffer_index].vmo();
    virtual_memory_mapped_addrs_[buffer_index] = nullptr;
    status = zx::vmar::root_self()->map(
        ZX_VM_PERM_READ, /*vmar_offset*/ 0, virt_mem,
        /*vmo_offset*/ 0, virt_mem_bytes,
        reinterpret_cast<uintptr_t*>(
            &virtual_memory_mapped_addrs_[buffer_index]));
    if (status != ZX_OK) {
      fatal_error_ = true;
      RTC_LOG(LS_ERROR) << "Failed to map virtual memory: " << status;
      return;
    }
  }
}

uint32_t ScreenCapturerFuchsia::GetPixelsPerRow(
    const fuchsia::sysmem2::ImageFormatConstraints& constraints) {
  uint32_t stride = RoundUpToMultiple(
      std::max(constraints.min_bytes_per_row(), width_ * kFuchsiaBytesPerPixel),
      constraints.bytes_per_row_divisor());
  uint32_t pixels_per_row = stride / kFuchsiaBytesPerPixel;

  return pixels_per_row;
}

}  // namespace webrtc
