// Copyright 2020 The Chromium OS 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 "camera3_test/camera3_device_connector.h"

#include <linux/videodev2.h>
#include <memory>
#include <set>
#include <string>
#include <utility>
#include <vector>

#include <base/stl_util.h>
#include <base/posix/eintr_wrapper.h>
#include <drm_fourcc.h>
#include <mojo/public/cpp/system/platform_handle.h>
#include <system/camera_metadata_hidden.h>

#include "camera3_test/camera3_module_connector.h"
#include "cros-camera/camera_buffer_manager.h"
#include "cros-camera/constants.h"
#include "cros-camera/ipc_util.h"

namespace camera3_test {

HalDeviceConnector::HalDeviceConnector(int cam_id, camera3_device_t* cam_device)
    : cam_device_(cam_device),
      dev_thread_("Camera3TestHalDeviceConnectorThread") {
  DETACH_FROM_THREAD(thread_checker_);
}

HalDeviceConnector::~HalDeviceConnector() {
  int result = -EIO;
  dev_thread_.PostTaskSync(FROM_HERE,
                           base::Bind(&HalDeviceConnector::CloseOnThread,
                                      base::Unretained(this), &result));
  dev_thread_.Stop();
}

void HalDeviceConnector::CloseOnThread(int* result) {
  if (cam_device_) {
    *result = cam_device_->common.close(&cam_device_->common);
  } else {
    *result = 0;
  }
}

int HalDeviceConnector::Initialize(const camera3_callback_ops_t* callback_ops) {
  if (!dev_thread_.Start()) {
    return -EINVAL;
  }
  int result = -EIO;
  dev_thread_.PostTaskSync(
      FROM_HERE, base::Bind(&HalDeviceConnector::InitializeOnThread,
                            base::Unretained(this), callback_ops, &result));
  return result;
}

void HalDeviceConnector::InitializeOnThread(
    const camera3_callback_ops_t* callback_ops, int* result) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  if (!cam_device_) {
    *result = -ENODEV;
    return;
  }
  *result = cam_device_->ops->initialize(cam_device_, callback_ops);
  if (*result != 0) {
    cam_device_->common.close(&cam_device_->common);
    cam_device_ = nullptr;
  }
}

int HalDeviceConnector::ConfigureStreams(
    camera3_stream_configuration_t* stream_list) {
  VLOGF_ENTER();
  int32_t result = -EIO;
  dev_thread_.PostTaskSync(
      FROM_HERE, base::Bind(&HalDeviceConnector::ConfigureStreamsOnThread,
                            base::Unretained(this), stream_list, &result));
  return result;
}

void HalDeviceConnector::ConfigureStreamsOnThread(
    camera3_stream_configuration_t* stream_list, int* result) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  if (!cam_device_) {
    *result = -ENODEV;
    return;
  }
  *result = cam_device_->ops->configure_streams(cam_device_, stream_list);
}

const camera_metadata_t* HalDeviceConnector::ConstructDefaultRequestSettings(
    int type) {
  VLOGF_ENTER();
  const camera_metadata_t* metadata = nullptr;
  dev_thread_.PostTaskSync(
      FROM_HERE,
      base::Bind(&HalDeviceConnector::ConstructDefaultRequestSettingsOnThread,
                 base::Unretained(this), type, &metadata));
  return metadata;
}

void HalDeviceConnector::ConstructDefaultRequestSettingsOnThread(
    int type, const camera_metadata_t** result) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  if (cam_device_) {
    *result =
        cam_device_->ops->construct_default_request_settings(cam_device_, type);
  }
}

int HalDeviceConnector::ProcessCaptureRequest(
    camera3_capture_request_t* capture_request) {
  VLOGF_ENTER();
  int32_t result = -EIO;
  dev_thread_.PostTaskSync(
      FROM_HERE, base::Bind(&HalDeviceConnector::ProcessCaptureRequestOnThread,
                            base::Unretained(this), capture_request, &result));
  return result;
}

void HalDeviceConnector::ProcessCaptureRequestOnThread(
    camera3_capture_request_t* request, int* result) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  VLOGF_ENTER();
  if (!cam_device_) {
    *result = -ENODEV;
    return;
  }
  *result = cam_device_->ops->process_capture_request(cam_device_, request);
}

int HalDeviceConnector::Flush() {
  VLOGF_ENTER();
  if (!cam_device_) {
    return -ENODEV;
  }
  return cam_device_->ops->flush(cam_device_);
}

ClientDeviceConnector::ClientDeviceConnector()
    : mojo_callback_ops_(this),
      user_callback_ops_(nullptr),
      dev_thread_("Camera3TestClientDeviceConnectorThread") {
  dev_thread_.Start();
}

ClientDeviceConnector::~ClientDeviceConnector() {
  auto future = cros::Future<int32_t>::Create(nullptr);
  dev_thread_.PostTaskAsync(
      FROM_HERE,
      base::Bind(&ClientDeviceConnector::CloseOnThread, base::Unretained(this),
                 cros::GetFutureCallback(future)));
  if (!future->Wait() || future->Get() != 0) {
    ADD_FAILURE() << "Camera device close failed";
  }
  dev_thread_.Stop();
}

mojo::PendingReceiver<cros::mojom::Camera3DeviceOps>
ClientDeviceConnector::GetDeviceOpsReceiver() {
  mojo::PendingReceiver<cros::mojom::Camera3DeviceOps> dev_ops_rec;
  dev_thread_.PostTaskSync(
      FROM_HERE,
      base::Bind(&ClientDeviceConnector::MakeDeviceOpsReceiverOnThread,
                 base::Unretained(this), &dev_ops_rec));
  return dev_ops_rec;
}

void ClientDeviceConnector::MakeDeviceOpsReceiverOnThread(
    mojo::PendingReceiver<cros::mojom::Camera3DeviceOps>* dev_ops_rec) {
  dev_ops_.reset();
  *dev_ops_rec = dev_ops_.BindNewPipeAndPassReceiver();
}

void ClientDeviceConnector::CloseOnThread(
    base::OnceCallback<void(int32_t)> cb) {
  dev_ops_->Close(base::BindOnce(&ClientDeviceConnector::OnClosedOnThread,
                                 base::Unretained(this), std::move(cb)));
}

void ClientDeviceConnector::OnClosedOnThread(
    base::OnceCallback<void(int32_t)> cb, int32_t result) {
  dev_ops_.reset();
  mojo_callback_ops_.reset();
  std::move(cb).Run(result);
}

int ClientDeviceConnector::Initialize(
    const camera3_callback_ops_t* callback_ops) {
  if (!callback_ops) {
    return -EINVAL;
  }
  auto future = cros::Future<int32_t>::Create(nullptr);
  dev_thread_.PostTaskAsync(
      FROM_HERE, base::Bind(&ClientDeviceConnector::InitializeOnThread,
                            base::Unretained(this), callback_ops,
                            cros::GetFutureCallback(future)));
  if (!future->Wait()) {
    LOGF(ERROR) << "Failed to initialize client camera device";
    return -EIO;
  }
  user_callback_ops_ = callback_ops;
  return future->Get();
}

void ClientDeviceConnector::InitializeOnThread(
    const camera3_callback_ops_t* callback_ops,
    base::OnceCallback<void(int32_t)> cb) {
  VLOGF_ENTER();
  dev_ops_->Initialize(mojo_callback_ops_.BindNewPipeAndPassRemote(),
                       std::move(cb));
}

int ClientDeviceConnector::ConfigureStreams(
    camera3_stream_configuration_t* stream_list) {
  if (!stream_list) {
    return -EINVAL;
  }
  auto future = cros::Future<int32_t>::Create(nullptr);
  dev_thread_.PostTaskAsync(
      FROM_HERE, base::Bind(&ClientDeviceConnector::ConfigureStreamsOnThread,
                            base::Unretained(this), stream_list,
                            cros::GetFutureCallback(future)));
  if (!future->Wait()) {
    return -ENODEV;
  }
  return future->Get();
}

void ClientDeviceConnector::ConfigureStreamsOnThread(
    camera3_stream_configuration_t* stream_list,
    base::OnceCallback<void(int32_t)> cb) {
  camera3_streams_.clear();
  for (uint32_t i = 0; i < stream_list->num_streams; i++) {
    camera3_streams_.insert(stream_list->streams[i]);
  }
  cros::mojom::Camera3StreamConfigurationPtr stream_config =
      cros::mojom::Camera3StreamConfiguration::New();
  stream_config->operation_mode =
      static_cast<cros::mojom::Camera3StreamConfigurationMode>(
          stream_list->operation_mode);
  for (const auto& s : camera3_streams_) {
    cros::mojom::Camera3StreamPtr stream = cros::mojom::Camera3Stream::New();
    stream->id = reinterpret_cast<uint64_t>(s);
    stream->stream_type =
        static_cast<cros::mojom::Camera3StreamType>(s->stream_type);
    stream->width = s->width;
    stream->height = s->height;
    stream->format = static_cast<cros::mojom::HalPixelFormat>(s->format);
    stream->usage = s->usage;
    stream->max_buffers = s->max_buffers;
    stream->data_space = static_cast<uint32_t>(s->data_space);
    stream->rotation =
        static_cast<cros::mojom::Camera3StreamRotation>(s->rotation);
    cros::mojom::CropRotateScaleInfoPtr info =
        cros::mojom::CropRotateScaleInfo::New();
    info->crop_rotate_scale_degrees =
        static_cast<cros::mojom::Camera3StreamRotation>(
            s->crop_rotate_scale_degrees);
    stream->crop_rotate_scale_info = std::move(info);
    stream_config->streams.push_back(std::move(stream));
  }
  dev_ops_->ConfigureStreams(
      std::move(stream_config),
      base::BindOnce(&ClientDeviceConnector::OnConfiguredStreams,
                     base::Unretained(this), std::move(cb)));
}

void ClientDeviceConnector::OnConfiguredStreams(
    base::OnceCallback<void(int32_t)> cb,
    int32_t result,
    cros::mojom::Camera3StreamConfigurationPtr updated_config) {
  VLOGF_ENTER();
  if (result == 0) {
    for (const auto& s : updated_config->streams) {
      camera3_stream_t* ptr = reinterpret_cast<camera3_stream_t*>(s->id);
      ASSERT_NE(camera3_streams_.find(ptr), camera3_streams_.end());
      ptr->usage = s->usage;
      ptr->max_buffers = s->max_buffers;
    }
  }
  std::move(cb).Run(result);
}

const camera_metadata_t* ClientDeviceConnector::ConstructDefaultRequestSettings(
    int type) {
  VLOGF_ENTER();
  auto future = cros::Future<const camera_metadata_t*>::Create(nullptr);
  dev_thread_.PostTaskAsync(
      FROM_HERE,
      base::Bind(
          &ClientDeviceConnector::ConstructDefaultRequestSettingsOnThread,
          base::Unretained(this), type, cros::GetFutureCallback(future)));
  if (!future->Wait()) {
    return nullptr;
  }
  return future->Get();
}

void ClientDeviceConnector::ConstructDefaultRequestSettingsOnThread(
    int type, base::OnceCallback<void(const camera_metadata_t*)> cb) {
  if (base::Contains(default_req_settings_map_, type)) {
    std::move(cb).Run(default_req_settings_map_.at(type).get());
    return;
  }
  dev_ops_->ConstructDefaultRequestSettings(
      static_cast<cros::mojom::Camera3RequestTemplate>(type),
      base::BindOnce(
          &ClientDeviceConnector::OnConstructedDefaultRequestSettings,
          base::Unretained(this), type, std::move(cb)));
}

void ClientDeviceConnector::OnConstructedDefaultRequestSettings(
    int type,
    base::OnceCallback<void(const camera_metadata_t*)> cb,
    cros::mojom::CameraMetadataPtr settings) {
  VLOGF_ENTER();
  if (!base::Contains(default_req_settings_map_, type)) {
    default_req_settings_map_[type] =
        cros::internal::DeserializeCameraMetadata(settings);
  }
  std::move(cb).Run(default_req_settings_map_.at(type).get());
}

int ClientDeviceConnector::ProcessCaptureRequest(
    camera3_capture_request_t* capture_request) {
  VLOGF_ENTER();
  if (!capture_request) {
    return -EINVAL;
  }
  auto future = cros::Future<int32_t>::Create(nullptr);
  dev_thread_.PostTaskAsync(
      FROM_HERE,
      base::Bind(&ClientDeviceConnector::ProcessCaptureRequestOnThread,
                 base::Unretained(this), capture_request,
                 cros::GetFutureCallback(future)));
  if (!future->Wait()) {
    return -EIO;
  }
  return future->Get();
}

void ClientDeviceConnector::ProcessCaptureRequestOnThread(
    camera3_capture_request_t* capture_request,
    base::OnceCallback<void(int32_t)> cb) {
  cros::mojom::Camera3CaptureRequestPtr request =
      cros::mojom::Camera3CaptureRequest::New();
  request->frame_number = capture_request->frame_number;
  request->settings =
      cros::internal::SerializeCameraMetadata(capture_request->settings);
  if (capture_request->input_buffer) {
    cros::mojom::Camera3StreamBufferPtr input_buffer =
        PrepareStreamBufferPtr(capture_request->input_buffer);
    ASSERT_FALSE(input_buffer.is_null());
    request->input_buffer = std::move(input_buffer);
  }
  for (uint32_t i = 0; i < capture_request->num_output_buffers; i++) {
    cros::mojom::Camera3StreamBufferPtr output_buffer =
        PrepareStreamBufferPtr(capture_request->output_buffers + i);
    ASSERT_FALSE(output_buffer.is_null());
    request->output_buffers.push_back(std::move(output_buffer));
  }
  dev_ops_->ProcessCaptureRequest(std::move(request), std::move(cb));
}

cros::mojom::Camera3StreamBufferPtr
ClientDeviceConnector::PrepareStreamBufferPtr(
    const camera3_stream_buffer_t* buffer) {
  VLOGF_ENTER();
  uint32_t drm_format = 0;
  switch (cros::CameraBufferManager::GetV4L2PixelFormat(*buffer->buffer)) {
    case V4L2_PIX_FMT_JPEG:
    case V4L2_PIX_FMT_MJPEG:
      drm_format = DRM_FORMAT_R8;
      break;
    case V4L2_PIX_FMT_NV12:
    case V4L2_PIX_FMT_NV12M:
      drm_format = DRM_FORMAT_NV12;
      break;
    case V4L2_PIX_FMT_NV21:
    case V4L2_PIX_FMT_NV21M:
      drm_format = DRM_FORMAT_NV21;
      break;
    case V4L2_PIX_FMT_YUV420:
    case V4L2_PIX_FMT_YUV420M:
      drm_format = DRM_FORMAT_YUV420;
      break;
    case V4L2_PIX_FMT_YVU420:
    case V4L2_PIX_FMT_YVU420M:
      drm_format = DRM_FORMAT_YVU420;
      break;
    default:
      ADD_FAILURE() << "Unsupported V4L2 format: 0x" << std::hex
                    << cros::CameraBufferManager::GetV4L2PixelFormat(
                           *buffer->buffer);
      return nullptr;
  }
  uint32_t num_planes =
      cros::CameraBufferManager::GetNumPlanes(*buffer->buffer);
  std::vector<uint32_t> strides;
  std::vector<uint32_t> offsets;
  for (uint32_t i = 0; i < num_planes; i++) {
    strides.push_back(
        cros::CameraBufferManager::GetPlaneStride(*buffer->buffer, i));
    offsets.push_back(
        cros::CameraBufferManager::GetPlaneOffset(*buffer->buffer, i));
  }
  buffer_handle_t* native_handle = buffer->buffer;
  std::vector<mojo::ScopedHandle> fds;
  for (uint32_t i = 0; i < num_planes; i++) {
    int dup_fd = HANDLE_EINTR(dup((*native_handle)->data[i]));
    fds.emplace_back(mojo::WrapPlatformFile(base::ScopedPlatformFile(dup_fd)));
  }
  uint64_t buffer_id = reinterpret_cast<uint64_t>(native_handle);
  base::AutoLock bufferLock(buffer_handle_map_lock_);
  buffer_handle_map_[buffer_id] = native_handle;
  cros::mojom::Camera3StreamBufferPtr buffer_ptr =
      cros::mojom::Camera3StreamBuffer::New();
  buffer_ptr->stream_id = reinterpret_cast<uint64_t>(buffer->stream);
  buffer_ptr->buffer_id = buffer_id;
  buffer_ptr->status =
      static_cast<cros::mojom::Camera3BufferStatus>(buffer->status);
  cros::mojom::CameraBufferHandlePtr handle_ptr =
      cros::mojom::CameraBufferHandle::New();
  handle_ptr->buffer_id = buffer_id;
  handle_ptr->fds = std::move(fds);
  handle_ptr->drm_format = drm_format;
  handle_ptr->hal_pixel_format =
      static_cast<cros::mojom::HalPixelFormat>(buffer->stream->format);
  handle_ptr->width = cros::CameraBufferManager::GetWidth(*buffer->buffer);
  handle_ptr->height = cros::CameraBufferManager::GetHeight(*buffer->buffer);
  handle_ptr->strides = std::move(strides);
  handle_ptr->offsets = std::move(offsets);
  buffer_ptr->buffer_handle = std::move(handle_ptr);
  return buffer_ptr;
}

int ClientDeviceConnector::Flush() {
  VLOGF_ENTER();
  auto future = cros::Future<int32_t>::Create(nullptr);
  dev_ops_->Flush(cros::GetFutureCallback(future));
  if (!future->Wait()) {
    return -ENODEV;
  }
  return future->Get();
}

void ClientDeviceConnector::Notify(cros::mojom::Camera3NotifyMsgPtr message) {
  VLOGF_ENTER();
  camera3_notify_msg_t notify_msg;
  notify_msg.type = static_cast<int32_t>(message->type);
  if (message->type == cros::mojom::Camera3MsgType::CAMERA3_MSG_ERROR) {
    cros::mojom::Camera3ErrorMsgPtr& error = message->message->get_error();
    notify_msg.message.error.frame_number = error->frame_number;
    if (!error->error_stream_id) {
      notify_msg.message.error.error_stream = nullptr;
    } else {
      notify_msg.message.error.error_stream =
          reinterpret_cast<camera3_stream_t*>(error->error_stream_id);
    }
    notify_msg.message.error.error_code = static_cast<int>(error->error_code);
  } else {  // message->type ==
            // cros::mojom::Camera3MsgType::CAMERA3_MSG_SHUTTER)
    cros::mojom::Camera3ShutterMsgPtr& shutter =
        message->message->get_shutter();
    notify_msg.message.shutter.frame_number = shutter->frame_number;
    notify_msg.message.shutter.timestamp = shutter->timestamp;
  }
  user_callback_ops_->notify(user_callback_ops_, &notify_msg);
}

void ClientDeviceConnector::ProcessCaptureResult(
    cros::mojom::Camera3CaptureResultPtr result) {
  VLOGF_ENTER();
  camera3_capture_result_t capture_result;

  capture_result.frame_number = result->frame_number;
  capture_result.partial_result = result->partial_result;

  cros::internal::ScopedCameraMetadata metadata;
  if (!result->result->entries.has_value()) {
    capture_result.result = nullptr;
  } else {
    metadata = cros::internal::DeserializeCameraMetadata(result->result);
    capture_result.result = metadata.get();
  }

  size_t num_output_buffers = result->output_buffers.has_value()
                                  ? result->output_buffers.value().size()
                                  : 0u;
  capture_result.num_output_buffers = num_output_buffers;

  std::vector<camera3_stream_buffer_t> output_buffers(num_output_buffers);
  if (!result->output_buffers.has_value()) {
    capture_result.output_buffers = nullptr;
  } else {
    for (size_t i = 0; i < num_output_buffers; i++) {
      cros::mojom::Camera3StreamBufferPtr& buffer_ptr =
          result->output_buffers.value()[i];
      camera3_stream_buffer_t* buffer = &output_buffers.at(i);
      int ret = DecodeStreamBufferPtr(buffer_ptr, buffer);
      if (ret) {
        LOGF(ERROR) << "Failed to decode output stream buffer";
        return;
      }
      if (camera3_streams_.count(buffer->stream) == 0) {
        LOGF(ERROR) << "Invalid stream";
        return;
      }
      base::AutoLock bufferLock(buffer_handle_map_lock_);
      buffer_handle_map_.erase(buffer_ptr->buffer_id);
    }
    capture_result.output_buffers =
        const_cast<const camera3_stream_buffer_t*>(output_buffers.data());
  }

  camera3_stream_buffer_t input_buffer;
  if (result->input_buffer.is_null()) {
    capture_result.input_buffer = nullptr;
  } else {
    int ret = DecodeStreamBufferPtr(result->input_buffer, &input_buffer);
    if (ret) {
      LOGF(ERROR) << "Failed to decode input stream buffer";
      return;
    }
    if (camera3_streams_.count(input_buffer.stream) == 0) {
      LOGF(ERROR) << "Invalid stream";
      return;
    }
    base::AutoLock bufferLock(buffer_handle_map_lock_);
    buffer_handle_map_.erase(result->input_buffer->buffer_id);
    capture_result.input_buffer = &input_buffer;
  }

  user_callback_ops_->process_capture_result(user_callback_ops_,
                                             &capture_result);
}

int ClientDeviceConnector::DecodeStreamBufferPtr(
    const cros::mojom::Camera3StreamBufferPtr& buffer_ptr,
    camera3_stream_buffer_t* buffer) {
  base::AutoLock bufferLock(buffer_handle_map_lock_);
  buffer->stream = reinterpret_cast<camera3_stream_t*>(buffer_ptr->stream_id);
  uint64_t buffer_id = buffer_ptr->buffer_id;
  if (buffer_handle_map_.count(buffer_id) == 0) {
    return -EINVAL;
  }
  buffer->buffer = buffer_handle_map_[buffer_id];
  buffer->status = static_cast<int>(buffer_ptr->status);
  if (buffer_ptr->acquire_fence.is_valid()) {
    buffer->acquire_fence =
        mojo::UnwrapPlatformHandle(std::move(buffer_ptr->acquire_fence))
            .ReleaseFD();
  } else {
    buffer->acquire_fence = -1;
  }

  if (buffer_ptr->release_fence.is_valid()) {
    buffer->acquire_fence =
        mojo::UnwrapPlatformHandle(std::move(buffer_ptr->release_fence))
            .ReleaseFD();
  } else {
    buffer->release_fence = -1;
  }
  return 0;
}

}  // namespace camera3_test
