// Copyright 2019 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/drivers/controller/controller_protocol.h"

#include <fuchsia/camera2/cpp/fidl.h>
#include <lib/fidl/cpp/optional.h>
#include <lib/fit/defer.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/trace/event.h>

#include "src/camera/drivers/controller/configs/product_config.h"

namespace camera {

namespace {
constexpr auto kTag = "camera_controller";
}  // namespace

ControllerImpl::ControllerImpl(zx_device_t* device,
                               fidl::InterfaceRequest<fuchsia::camera2::hal::Controller> control,
                               async_dispatcher_t* dispatcher, const ddk::IspProtocolClient& isp,
                               const ddk::GdcProtocolClient& gdc,
                               const ddk::Ge2dProtocolClient& ge2d,
                               fit::closure on_connection_closed,
                               fuchsia::sysmem::AllocatorSyncPtr sysmem_allocator,
                               const zx::event& shutdown_event)
    : binding_(this),
      pipeline_manager_(device, dispatcher, isp, gdc, ge2d, std::move(sysmem_allocator),
                        shutdown_event),
      product_config_(ProductConfig::Create()) {
  binding_.set_error_handler(
      [occ = std::move(on_connection_closed)](zx_status_t /*status*/) { occ(); });
  PopulateConfigurations();
  binding_.Bind(std::move(control), dispatcher);
}

zx_status_t ControllerImpl::GetInternalConfiguration(uint32_t config_index,
                                                     InternalConfigInfo** internal_config) {
  if (config_index >= internal_configs_.configs_info.size() || internal_config == nullptr) {
    return ZX_ERR_INVALID_ARGS;
  }

  *internal_config = &internal_configs_.configs_info[config_index];
  return ZX_OK;
}

void ControllerImpl::GetNextConfig(GetNextConfigCallback callback) {
  fuchsia::camera2::hal::Config config;

  if (config_count_ >= configs_.size()) {
    callback(nullptr, ZX_ERR_STOP);
    return;
  }
  config = fidl::Clone(configs_.at(config_count_));
  callback(fidl::MakeOptional(std::move(config)), ZX_OK);
  config_count_++;
}

static InternalConfigNode* GetStreamConfigNode(
    InternalConfigInfo* internal_config, fuchsia::camera2::CameraStreamType stream_config_type) {
  // Internal API, assuming the pointer will be valid always.
  for (auto& stream_info : internal_config->streams_info) {
    auto supported_streams = stream_info.supported_streams;
    if (std::any_of(supported_streams.begin(), supported_streams.end(),
                    [stream_config_type](auto& supported_stream) {
                      return supported_stream.type == stream_config_type;
                    })) {
      return &stream_info;
    }
  }
  return nullptr;
}

void ControllerImpl::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) {
  TRACE_DURATION("camera", "ControllerImpl::CreateStream");
  zx_status_t status = ZX_OK;
  auto cleanup = fit::defer([&stream, &status]() { stream.Close(status); });
  auto external_configs = product_config_->ExternalConfigs();

  // Input Validations
  if (config_index >= configs_.size()) {
    FX_LOGST(DEBUG, kTag) << "Invalid config index " << config_index;
    status = ZX_ERR_INVALID_ARGS;
    return;
  }
  const auto& config = configs_[config_index];

  if (stream_index >= config.stream_configs.size()) {
    FX_LOGST(DEBUG, kTag) << "Invalid stream index " << stream_index;
    status = ZX_ERR_INVALID_ARGS;
    return;
  }
  const auto& stream_config = config.stream_configs[stream_index];

  if (image_format_index >= stream_config.image_formats.size()) {
    FX_LOGST(DEBUG, kTag) << "Invalid image format index " << image_format_index;
    status = ZX_ERR_INVALID_ARGS;
    return;
  }

  if (buffer_collection.buffer_count == 0) {
    FX_LOGST(DEBUG, kTag) << "Invalid buffer count " << buffer_collection.buffer_count;
    status = ZX_ERR_INVALID_ARGS;
    return;
  }

  // Get Internal Configuration
  InternalConfigInfo* internal_config;
  status = GetInternalConfiguration(config_index, &internal_config);
  if (status != ZX_OK) {
    FX_PLOGST(DEBUG, kTag, status) << "Unable to get Internal configuration";
    return;
  }

  // Check the Input Stream Type and see if it is already created
  auto* stream_config_node =
      GetStreamConfigNode(internal_config, stream_config.properties.stream_type());
  if (stream_config_node == nullptr) {
    FX_LOGST(DEBUG, kTag) << "Unable to get Internal stream config node";
    return;
  }

  StreamCreationData info;
  info.output_buffers = std::move(buffer_collection);
  info.image_format_index = image_format_index;
  info.node = *stream_config_node;
  info.stream_config = fidl::Clone(stream_config);
  info.frame_rate_range = internal_config->frame_rate_range;

  cleanup.cancel();

  // We now have the stream_config_node which needs to be configured
  // Configure the stream pipeline
  pipeline_manager_.ConfigureStreamPipeline(std::move(info), std::move(stream));
}

void ControllerImpl::EnableStreaming() { pipeline_manager_.StartStreaming(); }

void ControllerImpl::DisableStreaming() { pipeline_manager_.StopStreaming(); }

void ControllerImpl::GetDeviceInfo(GetDeviceInfoCallback callback) {
  fuchsia::camera2::DeviceInfo camera_device_info;
  camera_device_info.set_vendor_name(kCameraVendorName);
  camera_device_info.set_vendor_id(kCameraVendorId);
  camera_device_info.set_product_name(kCameraProductName);
  camera_device_info.set_product_id(kCameraProductId);
  camera_device_info.set_type(fuchsia::camera2::DeviceType::BUILTIN);
  callback(std::move(camera_device_info));
}

}  // namespace camera
