// 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/syslog/cpp/macros.h>
#include <lib/trace/event.h>

#include <fbl/auto_call.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 = fbl::MakeAutoCall([&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
