/*
 * 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 "common/libcamera_connector/camera_client_ops.h"

#include <utility>

#include <base/bind.h>
#include <base/bind_helpers.h>
#include <base/posix/safe_strerror.h>
#include <mojo/public/cpp/system/platform_handle.h>
#include <drm_fourcc.h>
#include <hardware/camera3.h>
#include <hardware/gralloc.h>
#include <sync/sync.h>
#include <sys/mman.h>

#include "common/libcamera_connector/camera_metadata_utils.h"
#include "common/libcamera_connector/supported_formats.h"
#include "cros-camera/common.h"
#include "mojo/camera3.mojom.h"

namespace cros {

CameraClientOps::CameraClientOps() : camera3_callback_ops_(this) {}

mojom::Camera3DeviceOpsRequest CameraClientOps::Init(
    CaptureResultCallback result_callback) {
  VLOGF_ENTER();

  ops_runner_ = base::SequencedTaskRunnerHandle::Get();
  capturing_ = false;
  result_callback_ = std::move(result_callback);
  frame_number_ = 0;
  return mojo::MakeRequest(&device_ops_);
}

void CameraClientOps::StartCapture(int32_t camera_id,
                                   const cros_cam_format_info_t* format,
                                   int32_t jpeg_max_size) {
  VLOGF_ENTER();
  DCHECK(ops_runner_->RunsTasksInCurrentSequence());

  capturing_ = true;
  // TODO(b/151047930): Check whether this format info is actually supported.
  request_camera_id_ = camera_id;
  request_format_ = *format;
  jpeg_max_size_ = jpeg_max_size;
  InitializeDevice();
}

void CameraClientOps::StopCapture(IntOnceCallback close_callback) {
  VLOGF_ENTER();
  DCHECK(ops_runner_->RunsTasksInCurrentSequence());

  capturing_ = false;
  device_ops_->Close(base::BindOnce(&CameraClientOps::OnClosedDevice,
                                    base::Unretained(this),
                                    std::move(close_callback)));
}

void CameraClientOps::Reset() {
  VLOGF_ENTER();
  DCHECK(ops_runner_->RunsTasksInCurrentSequence());

  capturing_ = false;
  device_ops_.reset();
  camera3_callback_ops_.Close();
}

void CameraClientOps::ProcessCaptureResult(
    mojom::Camera3CaptureResultPtr result) {
  VLOGF_ENTER();
  DCHECK(ops_runner_->RunsTasksInCurrentSequence());

  if (!capturing_) {
    return;
  }
  if (result->output_buffers) {
    CHECK_EQ(result->output_buffers->size(), 1u);
    const auto& output_buffer = result->output_buffers->front();
    if (output_buffer->release_fence.is_valid()) {
      base::PlatformFile fence;
      CHECK_EQ(mojo::UnwrapPlatformFile(std::move(output_buffer->release_fence),
                                        &fence),
               MOJO_RESULT_OK);
      if (sync_wait(fence, 1000) != 0) {
        LOGF(ERROR) << "Failed to wait for release fence on buffer";
      }
    }
    if (output_buffer->status ==
        mojom::Camera3BufferStatus::CAMERA3_BUFFER_STATUS_ERROR) {
      return;
    }

    int64_t page_size = sysconf(_SC_PAGE_SIZE);
    const auto* buffer_handle_ptr = buffer_manager_.GetBufferHandle(
        result->output_buffers->at(0)->buffer_id);
    CHECK_NE(buffer_handle_ptr, nullptr);
    const auto& buffer_handle = *buffer_handle_ptr;
    if (buffer_handle->drm_format == DRM_FORMAT_R8) {
      CHECK_EQ(buffer_handle->fds.size(), 1);

      const auto* fds_ptr = buffer_manager_.GetFds(output_buffer->buffer_id);

      uint32_t unaligned_offset = buffer_handle->offsets[0] % page_size;
      uint32_t mapped_size = buffer_handle->sizes->at(0) + unaligned_offset;
      uint32_t aligned_offset = buffer_handle->offsets[0] - unaligned_offset;
      CHECK_NE(fds_ptr, nullptr);
      void* data = mmap(NULL, mapped_size, PROT_READ | PROT_WRITE, MAP_SHARED,
                        fds_ptr->at(0).get(), aligned_offset);
      CHECK_NE(data, MAP_FAILED);
      auto* blob = reinterpret_cast<camera3_jpeg_blob_t*>(
          static_cast<char*>(data) + unaligned_offset + jpeg_max_size_ -
          sizeof(camera3_jpeg_blob_t));
      CHECK_EQ(blob->jpeg_blob_id, CAMERA3_JPEG_BLOB_ID);

      cros_cam_frame_t frame = {
          .format = request_format_,
          .planes = {{
                         .stride = 0,
                         .size = static_cast<int>(blob->jpeg_size),
                         .data = static_cast<uint8_t*>(data) + unaligned_offset,
                     },
                     {.size = 0},
                     {.size = 0},
                     {.size = 0}}};
      SendCaptureResult(0, &frame);

      munmap(data, mapped_size);
      buffer_manager_.ReleaseBuffer(output_buffer->buffer_id);
    } else if (buffer_handle->drm_format == DRM_FORMAT_NV12) {
      CHECK_EQ(buffer_handle->fds.size(), 2);

      const auto* fds_ptr = buffer_manager_.GetFds(output_buffer->buffer_id);

      uint32_t y_unaligned_offset = buffer_handle->offsets[0] % page_size;
      uint32_t y_mapped_size = buffer_handle->sizes->at(0) + y_unaligned_offset;
      uint32_t y_aligned_offset =
          buffer_handle->offsets[0] - y_unaligned_offset;
      void* y_ptr = mmap(NULL, y_mapped_size, PROT_READ | PROT_WRITE,
                         MAP_SHARED, fds_ptr->at(0).get(), y_aligned_offset);
      CHECK_NE(y_ptr, MAP_FAILED);

      uint32_t cb_unaligned_offset = buffer_handle->offsets[1] % page_size;
      uint32_t cb_mapped_size =
          buffer_handle->sizes->at(1) + cb_unaligned_offset;
      uint32_t cb_aligned_offset =
          buffer_handle->offsets[1] - cb_unaligned_offset;
      void* cb_ptr = mmap(NULL, cb_mapped_size, PROT_READ | PROT_WRITE,
                          MAP_SHARED, fds_ptr->at(1).get(), cb_aligned_offset);
      CHECK_NE(cb_ptr, MAP_FAILED);

      cros_cam_frame_t frame = {
          .format = request_format_,
          .planes = {
              {.stride = static_cast<int>(buffer_handle->strides[0]),
               .size = static_cast<int>(buffer_handle->sizes->at(0)),
               .data = static_cast<uint8_t*>(y_ptr) + y_unaligned_offset},
              {.stride = static_cast<int>(buffer_handle->strides[1]),
               .size = static_cast<int>(buffer_handle->sizes->at(1)),
               .data = static_cast<uint8_t*>(cb_ptr) + cb_unaligned_offset},
              {.size = 0},
              {.size = 0}}};
      SendCaptureResult(0, &frame);

      munmap(y_ptr, y_mapped_size);
      munmap(cb_ptr, cb_mapped_size);
      buffer_manager_.ReleaseBuffer(output_buffer->buffer_id);
    }
  }
}

void CameraClientOps::Notify(mojom::Camera3NotifyMsgPtr msg) {
  VLOGF_ENTER();
  DCHECK(ops_runner_->RunsTasksInCurrentSequence());

  // We only need to handle error messages for libcamera_connector.
  if (msg->type != mojom::Camera3MsgType::CAMERA3_MSG_ERROR) {
    return;
  }
  int status = msg->message->get_error()->error_code ==
                       mojom::Camera3ErrorMsgCode::CAMERA3_MSG_ERROR_DEVICE
                   ? -ENODEV
                   : -EIO;
  SendCaptureResult(status, nullptr);
}

void CameraClientOps::InitializeDevice() {
  VLOGF_ENTER();
  DCHECK(ops_runner_->RunsTasksInCurrentSequence());

  mojom::Camera3CallbackOpsPtr camera3_callback_ops_ptr;
  mojom::Camera3CallbackOpsRequest camera3_callback_ops_request =
      mojo::MakeRequest(&camera3_callback_ops_ptr);
  camera3_callback_ops_.Bind(std::move(camera3_callback_ops_request));
  device_ops_->Initialize(std::move(camera3_callback_ops_ptr),
                          base::Bind(&CameraClientOps::OnInitializedDevice,
                                     base::Unretained(this)));
}

void CameraClientOps::OnInitializedDevice(int32_t result) {
  VLOGF_ENTER();
  DCHECK(ops_runner_->RunsTasksInCurrentSequence());

  if (result != 0) {
    LOGF(ERROR) << "Failed to initialize device: "
                << base::safe_strerror(-result);
    SendCaptureResult(-ENODEV, nullptr);
    return;
  }
  LOGF(INFO) << "Successfully initialized device";
  ConfigureStreams();
}

void CameraClientOps::ConfigureStreams() {
  VLOGF_ENTER();
  DCHECK(ops_runner_->RunsTasksInCurrentSequence());
  if (!capturing_) {
    return;
  }

  mojom::Camera3StreamPtr stream = mojom::Camera3Stream::New();
  stream->id = kStreamId;
  stream->stream_type = mojom::Camera3StreamType::CAMERA3_STREAM_OUTPUT;
  stream->width = request_format_.width;
  stream->height = request_format_.height;
  int hal_pixel_format = GetHalPixelFormat(request_format_.fourcc);
  CHECK_NE(hal_pixel_format, 0);
  stream->format = static_cast<mojom::HalPixelFormat>(hal_pixel_format);
  stream->data_space = 0;
  // TODO(b/151047930): Handle device rotations.
  stream->rotation = mojom::Camera3StreamRotation::CAMERA3_STREAM_ROTATION_0;

  mojom::Camera3StreamConfigurationPtr stream_config =
      mojom::Camera3StreamConfiguration::New();
  stream_config->streams.push_back(std::move(stream));
  stream_config->operation_mode = mojom::Camera3StreamConfigurationMode::
      CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE;

  device_ops_->ConfigureStreamsAndGetAllocatedBuffers(
      std::move(stream_config),
      base::Bind(&CameraClientOps::OnConfiguredStreams,
                 base::Unretained(this)));
}

void CameraClientOps::OnConfiguredStreams(
    int32_t result,
    cros::mojom::Camera3StreamConfigurationPtr updated_config,
    base::flat_map<uint64_t, std::vector<mojom::Camera3StreamBufferPtr>>
        allocated_buffers) {
  VLOGF_ENTER();
  DCHECK(ops_runner_->RunsTasksInCurrentSequence());

  if (result != 0) {
    LOGF(ERROR)
        << "Failed to configure streams. Please check your capture parameters: "
        << base::safe_strerror(-result);
    SendCaptureResult(-ENODEV, nullptr);
    return;
  }
  LOGF(INFO) << "Stream configured successfully";
  stream_config_ = std::move(updated_config);
  buffer_manager_.Init(std::move(allocated_buffers[kStreamId]));
  ConstructDefaultRequestSettings();
}

void CameraClientOps::ConstructDefaultRequestSettings() {
  VLOGF_ENTER();
  DCHECK(ops_runner_->RunsTasksInCurrentSequence());
  if (!capturing_) {
    return;
  }

  // TODO(b/151047930): Support other templates.
  mojom::Camera3RequestTemplate request_template =
      mojom::Camera3RequestTemplate::CAMERA3_TEMPLATE_PREVIEW;
  device_ops_->ConstructDefaultRequestSettings(
      request_template,
      base::Bind(&CameraClientOps::OnConstructedDefaultRequestSettings,
                 base::Unretained(this)));
}

void CameraClientOps::OnConstructedDefaultRequestSettings(
    mojom::CameraMetadataPtr settings) {
  VLOGF_ENTER();
  DCHECK(ops_runner_->RunsTasksInCurrentSequence());

  if (settings.is_null()) {
    LOGF(ERROR) << "Failed to construct the specified capture template";
    SendCaptureResult(-ENODEV, nullptr);
    return;
  }
  LOGF(INFO) << "Gotten request template for capture";
  request_settings_ = std::move(settings);
  // TODO(b/151047930): Resolve to a proper fps range.
  SetFpsRangeInMetadata(&request_settings_, request_format_.fps);
  ConstructCaptureRequestOnThread();
}

void CameraClientOps::ConstructCaptureRequest() {
  VLOGF_ENTER();
  ops_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(&CameraClientOps::ConstructCaptureRequestOnThread,
                     base::Unretained(this)));
}

void CameraClientOps::ConstructCaptureRequestOnThread() {
  VLOGF_ENTER();
  DCHECK(ops_runner_->RunsTasksInCurrentSequence());

  if (!buffer_manager_.HasFreeBuffers()) {
    buffer_manager_.SetNotifyBufferCallback(base::BindOnce(
        &CameraClientOps::ConstructCaptureRequest, base::Unretained(this)));
    return;
  }

  mojom::Camera3CaptureRequestPtr request = mojom::Camera3CaptureRequest::New();
  request->frame_number = frame_number_++;
  request->settings = request_settings_.Clone();

  auto buffer = buffer_manager_.AllocateBuffer();
  CHECK(!buffer.is_null());
  request->output_buffers.push_back(std::move(buffer));

  ProcessCaptureRequest(std::move(request));
}

void CameraClientOps::ProcessCaptureRequest(
    mojom::Camera3CaptureRequestPtr request) {
  VLOGF_ENTER();
  DCHECK(ops_runner_->RunsTasksInCurrentSequence());
  if (!capturing_) {
    return;
  }

  device_ops_->ProcessCaptureRequest(
      std::move(request),
      base::Bind(&CameraClientOps::OnProcessedCaptureRequest,
                 base::Unretained(this)));
}

void CameraClientOps::OnProcessedCaptureRequest(int32_t result) {
  VLOGF_ENTER();
  DCHECK(ops_runner_->RunsTasksInCurrentSequence());

  if (result != 0) {
    LOGF(ERROR) << "Failed to send capture request: "
                << base::safe_strerror(-result);
    SendCaptureResult(-ENODEV, nullptr);
    return;
  }
  ConstructCaptureRequestOnThread();
}

void CameraClientOps::SendCaptureResult(int status, cros_cam_frame_t* frame) {
  VLOGF_ENTER();
  DCHECK(ops_runner_->RunsTasksInCurrentSequence());

  cros_cam_capture_result_t result = {.status = status, .frame = frame};
  result_callback_.Run(result);
}

void CameraClientOps::OnClosedDevice(IntOnceCallback close_callback,
                                     int32_t result) {
  VLOGF_ENTER();
  DCHECK(ops_runner_->RunsTasksInCurrentSequence());

  device_ops_.reset();
  camera3_callback_ops_.Close();
  std::move(close_callback).Run(result);
}

}  // namespace cros
