// 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/ddk/debug.h>
#include <lib/fit/defer.h>
#include <lib/trace/event.h>

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

namespace camera {

ControllerImpl::ControllerImpl(async_dispatcher_t* dispatcher,
                               fuchsia::sysmem2::AllocatorSyncPtr sysmem_allocator,
                               const ddk::IspProtocolClient& isp, const ddk::GdcProtocolClient& gdc,
                               const ddk::Ge2dProtocolClient& ge2d,
                               LoadFirmwareCallback load_firmware)
    : dispatcher_(dispatcher),
      binding_(this),
      pipeline_manager_(dispatcher, std::move(sysmem_allocator), isp, gdc, ge2d,
                        std::move(load_firmware)),
      product_config_(ProductConfig::Create()) {
  binding_.set_error_handler(
      [](zx_status_t status) { zxlogf(INFO, "controller client disconnected"); });
  configs_ = product_config_->ExternalConfigs();
  internal_configs_ = product_config_->InternalConfigs();
}

void ControllerImpl::Connect(fidl::InterfaceRequest<fuchsia::camera2::hal::Controller> request) {
  if (binding_.is_bound()) {
    zxlogf(WARNING, "ControllerImpl::Connect(): Camera controller is already bound");
    request.Close(ZX_ERR_ALREADY_BOUND);
    return;
  }

  zx_status_t status = binding_.Bind(std::move(request), dispatcher_);
  zxlogf(INFO, "ControllerImpl::Connect(): Bind() -> %d", status);
}

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_++;
}

zx_koid_t GetRelatedKoid(zx_handle_t handle) {
  zx_info_handle_basic_t info;
  zx_status_t status =
      zx_object_get_info(handle, ZX_INFO_HANDLE_BASIC, &info, sizeof(info), nullptr, nullptr);
  return status == ZX_OK ? info.related_koid : ZX_KOID_INVALID;
}

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");

  zxlogf(INFO, "new request from remote channel koid %lu for c%us%uf%u",
         GetRelatedKoid(stream.channel().get()), config_index, stream_index, image_format_index);

  if (config_index >= configs_.size()) {
    stream.Close(ZX_ERR_INVALID_ARGS);
    return;
  }
  const auto& config = configs_[config_index];

  if (stream_index >= config.stream_configs.size()) {
    stream.Close(ZX_ERR_INVALID_ARGS);
    return;
  }
  const auto& stream_config = config.stream_configs[stream_index];

  if (image_format_index >= stream_config.image_formats.size()) {
    stream.Close(ZX_ERR_INVALID_ARGS);
    return;
  }

  // The presence of the requests queue indicates the pipeline manager is in transition.
  if (requests_) {
    // If a new config request arrives before the previous shutdown completed, discard any pending
    // requests received in the interim period and just start tracking requests for the new config.
    if (config_index != pipeline_config_index_) {
      pipeline_config_index_ = config_index;
      requests_ = RequestQueue{};
    }
    requests_->emplace(stream_index, image_format_index, std::move(stream));
    return;
  }

  // TODO(https://fxbug.dev/42051249): Move config index management into the pipeline manager, then
  // delete shutdown/queueing in this component.
  //
  // If the requested config is different from the current
  // config, handling it requires shutting down the current pipeline first.
  if (config_index != pipeline_config_index_) {
    pipeline_config_index_ = config_index;
    requests_ = RequestQueue{};
    requests_->emplace(stream_index, image_format_index, std::move(stream));
    pipeline_manager_.Shutdown([this]() mutable {
      TRACE_DURATION("camera", "ControllerImpl::CreateStream.shutdown.callback");
      pipeline_manager_.SetRoots(
          internal_configs_.configs_info[pipeline_config_index_].streams_info);
      auto requests = std::move(*requests_);
      requests_.reset();
      while (!requests.empty()) {
        auto [stream_index, image_format_index, stream] = std::move(requests.front());
        requests.pop();
        CreateStream(pipeline_config_index_, stream_index, image_format_index, std::move(stream));
      }
    });
    return;
  }

  auto& internal_config = internal_configs_.configs_info[config_index];

  StreamCreationData info{.roots = internal_config.streams_info};
  info.image_format_index = image_format_index;
  info.stream_config = fidl::Clone(stream_config);
  info.frame_rate_range = internal_config.frame_rate_range;

  // 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_.SetStreamingEnabled(true); }

void ControllerImpl::DisableStreaming() { pipeline_manager_.SetStreamingEnabled(false); }

void ControllerImpl::GetDeviceInfo(GetDeviceInfoCallback callback) {
  callback(ProductConfig::DeviceInfo());
}

}  // namespace camera
