// 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/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(std::make_unique<fuchsia::camera2::hal::Config>(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,
                                  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;
  }
  // 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.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
