// 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 "fake_camera_controller.h"

#include <fuchsia/camera2/cpp/fidl.h>
#include <fuchsia/camera2/hal/cpp/fidl.h>
#include <fuchsia/sysmem/cpp/fidl.h>
#include <lib/fidl/cpp/binding.h>

#include <vector>

#include "src/camera/lib/stream_utils/stream_constraints.h"
#include "src/lib/syslog/cpp/logger.h"

namespace camera {

std::vector<fuchsia::camera2::hal::Config> FakeController::InvalidConfigs() {
  std::vector<fuchsia::camera2::hal::Config> configs(2);
  return configs;
}

std::vector<fuchsia::camera2::hal::Config> FakeController::StandardConfigs() {
  std::vector<fuchsia::camera2::hal::Config> configs(2);

  StreamConstraints ml_mon_stream(fuchsia::camera2::CameraStreamType::MACHINE_LEARNING |
                                  fuchsia::camera2::CameraStreamType::MONITORING);
  ml_mon_stream.AddImageFormat(640, 512, fuchsia::sysmem::PixelFormatType::NV12);
  configs[0].stream_configs.push_back(ml_mon_stream.ConvertToStreamConfig());

  StreamConstraints mon_stream(fuchsia::camera2::CameraStreamType::MONITORING);
  mon_stream.AddImageFormat(640, 512, fuchsia::sysmem::PixelFormatType::NV12);
  mon_stream.AddImageFormat(896, 1600, fuchsia::sysmem::PixelFormatType::NV12);
  configs[0].stream_configs.push_back(mon_stream.ConvertToStreamConfig());

  StreamConstraints ml_vid_stream(fuchsia::camera2::CameraStreamType::MACHINE_LEARNING |
                                  fuchsia::camera2::CameraStreamType::VIDEO_CONFERENCE);
  ml_vid_stream.AddImageFormat(640, 512, fuchsia::sysmem::PixelFormatType::NV12);
  configs[1].stream_configs.push_back(ml_vid_stream.ConvertToStreamConfig());

  StreamConstraints vid_stream(fuchsia::camera2::CameraStreamType::VIDEO_CONFERENCE);
  vid_stream.AddImageFormat(640, 512, fuchsia::sysmem::PixelFormatType::NV12);
  vid_stream.AddImageFormat(2176, 2720, fuchsia::sysmem::PixelFormatType::NV12);
  configs[1].stream_configs.push_back(vid_stream.ConvertToStreamConfig());

  return configs;
}

static bool CheckMatchingChannel(const zx::channel& client_side, const zx::channel& server_side) {
  zx_info_handle_basic_t info[2];
  zx_status_t status = client_side.get_info(ZX_INFO_HANDLE_BASIC, &info[0],
                                            sizeof(zx_info_handle_basic_t), nullptr, nullptr);
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "Failed to get client side koid.";
    return false;
  }
  status = server_side.get_info(ZX_INFO_HANDLE_BASIC, &info[1], sizeof(zx_info_handle_basic_t),
                                nullptr, nullptr);
  if (status != ZX_OK || info[1].koid == 0) {
    FX_LOGS(ERROR) << "Failed to get server side koid.";
    return false;
  }
  return (info[0].related_koid == info[1].koid) && (info[1].related_koid == info[0].koid);
}

FakeController::FakeController(std::vector<fuchsia::camera2::hal::Config> configs,
                               async_dispatcher_t* dispatcher)
    : configs_(std::move(configs)), dispatcher_(dispatcher) {}

fidl::InterfaceHandle<fuchsia::camera2::hal::Controller> FakeController::GetCameraConnection() {
  ZX_ASSERT(!binding_.is_bound());
  fidl::InterfaceHandle<fuchsia::camera2::hal::Controller> client;
  binding_.Bind(client.NewRequest(), dispatcher_);
  return client;
}

void FakeController::GetConfigs(GetConfigsCallback callback) {
  // Make up some configs:
  std::vector<fuchsia::camera2::hal::Config> empty_configs;
  switch (configs_failure_) {
    case GetConfigsFailureMode::VALID_CONFIGS:
      callback(fidl::Clone(configs_), ZX_OK);
      break;
    case GetConfigsFailureMode::RETURNS_ERROR:
      callback(fidl::Clone(configs_), ZX_ERR_INTERNAL);
      break;
    case GetConfigsFailureMode::EMPTY_VECTOR:
      callback(std::move(empty_configs), ZX_OK);
      break;
    case GetConfigsFailureMode::INVALID_CONFIG:
      callback(InvalidConfigs(), ZX_ERR_INTERNAL);
      break;
  }
}

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) {
  CameraConnection conn = {.config_index = config_index,
                           .stream_index = stream_index,
                           .image_format_index = image_format_index,
                           .buffer_collection = std::move(buffer_collection),
                           .stream = std::move(stream)};
  fbl::AutoLock lock(&connections_lock_);
  connections_.push_back(std::move(conn));
}

void FakeController::GetDeviceInfo(GetDeviceInfoCallback callback) {
  const char* kVirtualCameraVendorName = "Google Inc.";
  const char* kVirtualCameraProductName = "Fuchsia Fake Camera";
  fuchsia::camera2::DeviceInfo camera_device_info;
  camera_device_info.set_vendor_name(kVirtualCameraVendorName);
  camera_device_info.set_product_name(kVirtualCameraProductName);
  camera_device_info.set_type(fuchsia::camera2::DeviceType::VIRTUAL);
  callback(std::move(camera_device_info));
}

bool FakeController::HasMatchingChannel(const zx::channel& client_side) {
  fbl::AutoLock lock(&connections_lock_);
  for (auto& connection : connections_) {
    if (CheckMatchingChannel(connection.stream.channel(), client_side)) {
      return true;
    }
  }
  return false;
}

}  // namespace camera
