// Copyright 2020 The Fuchsia 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 "src/camera/lib/fake_controller/fake_controller.h"

#include <lib/async-loop/default.h>
#include <lib/async/cpp/task.h>
#include <lib/fidl/cpp/optional.h>
#include <lib/syslog/cpp/macros.h>
#include <zircon/errors.h>

#include "src/camera/lib/fake_legacy_stream/fake_legacy_stream.h"

static fuchsia::camera2::DeviceInfo DefaultDeviceInfo() {
  fuchsia::camera2::DeviceInfo device_info{};
  device_info.set_vendor_id(0xFFFF);
  device_info.set_vendor_name("Fake Vendor Name");
  device_info.set_product_id(0x0ABC);
  device_info.set_product_name("Fake Product Name");
  device_info.set_type(fuchsia::camera2::DeviceType::VIRTUAL);
  return device_info;
}

static std::vector<fuchsia::camera2::hal::Config> DefaultConfigs() {
  constexpr fuchsia::sysmem::BufferCollectionConstraints kBufferCollectionConstraints{
      .usage = {.cpu = fuchsia::sysmem::cpuUsageRead},
      .min_buffer_count_for_camping = 3,
      .image_format_constraints_count = 1,
      .image_format_constraints = {{{
          .pixel_format =
              {
                  .type = fuchsia::sysmem::PixelFormatType::NV12,
              },
          .color_spaces_count = 1,
          .color_space = {{{
              .type = fuchsia::sysmem::ColorSpaceType::REC601_NTSC,
          }}},
          .min_coded_width = 128,
          .max_coded_width = 4096,
          .min_coded_height = 1,
          .max_coded_height = 4096,
          .coded_width_divisor = 128,
      }}}};
  fuchsia::camera2::hal::Config config1;
  config1.stream_configs.push_back(
      {.frame_rate =
           {
               .frames_per_sec_numerator = 30,
               .frames_per_sec_denominator = 1,
           },
       .constraints = kBufferCollectionConstraints,
       .image_formats = {
           {
               .pixel_format =
                   kBufferCollectionConstraints.image_format_constraints[0].pixel_format,
               .coded_width = 1920,
               .coded_height = 1080,
               .bytes_per_row = 1920,
           },
           {
               .pixel_format =
                   kBufferCollectionConstraints.image_format_constraints[0].pixel_format,
               .coded_width = 1280,
               .coded_height = 720,
               .bytes_per_row = 1920,
           },
           {
               .pixel_format =
                   kBufferCollectionConstraints.image_format_constraints[0].pixel_format,
               .coded_width = 1024,
               .coded_height = 576,
               .bytes_per_row = 1920,
           }}});
  fuchsia::camera2::hal::Config config2;
  config2.stream_configs.push_back(
      {.frame_rate =
           {
               .frames_per_sec_numerator = 30,
               .frames_per_sec_denominator = 1,
           },
       .constraints = kBufferCollectionConstraints,
       .image_formats = {{
           .pixel_format = kBufferCollectionConstraints.image_format_constraints[0].pixel_format,
           .coded_width = 1280,
           .coded_height = 720,
           .bytes_per_row = 1280,
       }}});
  std::vector<fuchsia::camera2::hal::Config> configs;
  configs.push_back(std::move(config1));
  configs.push_back(std::move(config2));
  return configs;
}

fit::result<std::unique_ptr<FakeController>, zx_status_t> FakeController::Create(
    fidl::InterfaceRequest<fuchsia::camera2::hal::Controller> request) {
  auto controller = std::make_unique<FakeController>();

  zx_status_t status = controller->loop_.StartThread("Fake Controller Loop");
  if (status != ZX_OK) {
    FX_PLOGS(ERROR, status);
    return fit::error(status);
  }

  status = controller->binding_.Bind(std::move(request), controller->loop_.dispatcher());
  if (status != ZX_OK) {
    FX_PLOGS(ERROR, status);
    return fit::error(status);
  }

  return fit::ok(std::move(controller));
}

std::vector<fuchsia::camera2::hal::Config> FakeController::GetDefaultConfigs() {
  return DefaultConfigs();
}

FakeController::FakeController()
    : loop_(&kAsyncLoopConfigNoAttachToCurrentThread), binding_(this) {}

FakeController::~FakeController() { loop_.Shutdown(); }

bool FakeController::LegacyStreamBufferIsOutstanding(uint32_t id) {
  bool is_outstanding = false;
  zx::event event;
  zx::event::create(0, &event);
  async::PostTask(loop_.dispatcher(), [&, this, id] {
    is_outstanding = stream_->IsOutstanding(id);
    event.signal(0, ZX_USER_SIGNAL_0);
  });
  event.wait_one(ZX_USER_SIGNAL_0, zx::time::infinite(), nullptr);
  return is_outstanding;
}

zx_status_t FakeController::SendFrameViaLegacyStream(fuchsia::camera2::FrameAvailableInfo info) {
  zx_status_t status = ZX_ERR_INTERNAL;
  zx::event event;
  zx::event::create(0, &event);
  async::PostTask(loop_.dispatcher(), [this, &status, &event, info = std::move(info)]() mutable {
    if (!stream_ || !stream_->IsStreaming()) {
      status = ZX_ERR_SHOULD_WAIT;
    } else {
      status = stream_->SendFrameAvailable(std::move(info));
    }
    event.signal(0, ZX_USER_SIGNAL_0);
  });
  event.wait_one(ZX_USER_SIGNAL_0, zx::time::infinite(), nullptr);
  return status;
}

void FakeController::GetNextConfig(
    fuchsia::camera2::hal::Controller::GetNextConfigCallback callback) {
  if (get_configs_call_count_ >= DefaultConfigs().size()) {
    callback(nullptr, ZX_ERR_STOP);
    return;
  }
  callback(fidl::MakeOptional(std::move(DefaultConfigs()[get_configs_call_count_++])), ZX_OK);
}

void FakeController::CreateStream(uint32_t config_index, uint32_t stream_index,
                                  uint32_t image_format_index,
                                  fuchsia::sysmem::BufferCollectionInfo_2 buffer_collection,
                                  fidl::InterfaceRequest<fuchsia::camera2::Stream> stream) {
  auto result = camera::FakeLegacyStream::Create(std::move(stream), loop_.dispatcher());
  if (result.is_error()) {
    FX_PLOGS(ERROR, result.error());
    return;
  }
  stream_ = result.take_value();
}

void FakeController::EnableStreaming() {
  if (streaming_enabled_) {
    FX_LOGS(ERROR) << "Called EnableStreaming when already enabled.";
    binding_.Close(ZX_ERR_BAD_STATE);
    return;
  }
  streaming_enabled_ = true;
}

void FakeController::DisableStreaming() {
  if (!streaming_enabled_) {
    FX_LOGS(ERROR) << "Called DisableStreaming when already disabled.";
    binding_.Close(ZX_ERR_BAD_STATE);
    return;
  }
  streaming_enabled_ = false;
}

void FakeController::GetDeviceInfo(
    fuchsia::camera2::hal::Controller::GetDeviceInfoCallback callback) {
  callback(DefaultDeviceInfo());
}
