/* Copyright 2019 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 <cctype>
#include <libyuv.h>
#include <linux/videodev2.h>
#include <memory>
#include <mojo/core/embedder/embedder.h>
#include <mojo/public/cpp/system/platform_handle.h>
#include <utility>

#include "cros-camera/common.h"
#include "cros-camera/ipc_util.h"
#include "hal/ip/camera_device.h"
#include "hal/ip/camera_hal.h"
#include "hal/ip/metadata_handler.h"

namespace cros {

static int initialize(const camera3_device_t* dev,
                      const camera3_callback_ops_t* callback_ops) {
  CameraDevice* device = reinterpret_cast<CameraDevice*>(dev->priv);
  if (!device) {
    LOGF(ERROR) << "Camera device is NULL";
    return -ENODEV;
  }
  return device->Initialize(callback_ops);
}

static int configure_streams(const camera3_device_t* dev,
                             camera3_stream_configuration_t* stream_list) {
  CameraDevice* device = reinterpret_cast<CameraDevice*>(dev->priv);
  if (!device) {
    LOGF(ERROR) << "Camera device is NULL";
    return -ENODEV;
  }
  return device->ConfigureStreams(stream_list);
}

static const camera_metadata_t* construct_default_request_settings(
    const camera3_device_t* dev, int type) {
  CameraDevice* device = reinterpret_cast<CameraDevice*>(dev->priv);
  if (!device) {
    LOGF(ERROR) << "Camera device is NULL";
    return nullptr;
  }
  return device->ConstructDefaultRequestSettings(type);
}

static int process_capture_request(const camera3_device_t* dev,
                                   camera3_capture_request_t* request) {
  CameraDevice* device = reinterpret_cast<CameraDevice*>(dev->priv);
  if (!device) {
    LOGF(ERROR) << "Camera device is NULL";
    return -ENODEV;
  }
  return device->ProcessCaptureRequest(request);
}

static void dump(const camera3_device_t* dev, int fd) {}

static int flush(const camera3_device_t* dev) {
  CameraDevice* device = reinterpret_cast<CameraDevice*>(dev->priv);
  if (!device) {
    LOGF(ERROR) << "Camera device is NULL";
    return -ENODEV;
  }
  return device->Flush();
}

}  // namespace cros

static camera3_device_ops_t g_camera_device_ops = {
    .initialize = cros::initialize,
    .configure_streams = cros::configure_streams,
    .register_stream_buffers = nullptr,
    .construct_default_request_settings =
        cros::construct_default_request_settings,
    .process_capture_request = cros::process_capture_request,
    .get_metadata_vendor_tag_ops = nullptr,
    .dump = cros::dump,
    .flush = cros::flush,
    .reserved = {},
};

namespace cros {

static int camera_device_close(struct hw_device_t* hw_device) {
  camera3_device_t* dev = reinterpret_cast<camera3_device_t*>(hw_device);
  CameraDevice* device = static_cast<CameraDevice*>(dev->priv);
  if (!device) {
    LOGF(ERROR) << "Camera device is NULL";
    return -EIO;
  }

  device->Close();
  return 0;
}

CameraDevice::CameraDevice(int id)
    : open_(false),
      id_(id),
      camera3_device_(),
      callback_ops_(nullptr),
      format_(0),
      width_(0),
      height_(0),
      binding_(this),
      buffer_manager_(nullptr),
      jpeg_(false),
      jpeg_thread_("JPEG Processing") {
  memset(&camera3_device_, 0, sizeof(camera3_device_));
  camera3_device_.common.tag = HARDWARE_DEVICE_TAG;
  camera3_device_.common.version = CAMERA_DEVICE_API_VERSION_3_3;
  camera3_device_.common.close = cros::camera_device_close;
  camera3_device_.common.module = nullptr;
  camera3_device_.ops = &g_camera_device_ops;
  camera3_device_.priv = this;

  buffer_manager_ = CameraBufferManager::GetInstance();
}

int CameraDevice::Init(mojom::IpCameraDevicePtr ip_device,
                       const std::string& ip,
                       const std::string& name,
                       mojom::PixelFormat format,
                       int32_t width,
                       int32_t height,
                       double fps) {
  ipc_task_runner_ = mojo::core::GetIOTaskRunner();
  DCHECK(ipc_task_runner_->RunsTasksInCurrentSequence());

  ip_device_ = std::move(ip_device);
  width_ = width;
  height_ = height;

  switch (format) {
    case mojom::PixelFormat::JPEG:
      jpeg_ = true;
      FALLTHROUGH;
    case mojom::PixelFormat::YUV_420:
      format_ = HAL_PIXEL_FORMAT_YCbCr_420_888;
      break;
    default:
      LOGF(ERROR) << "Unrecognized pixel format: " << format;
      return -EINVAL;
  }

  static_metadata_ = MetadataHandler::CreateStaticMetadata(
      ip, name, format_, width_, height_, fps);

  if (jpeg_) {
    if (!jpeg_thread_.StartWithOptions(
            base::Thread::Options(base::MessagePumpType::IO, 0))) {
      LOGF(ERROR) << "Failed to start jpeg processing thread";
      return -ENODEV;
    }
    jpeg_thread_.task_runner()->PostTask(
        FROM_HERE, base::BindOnce(&CameraDevice::StartJpegProcessor,
                                  base::Unretained(this)));
  }

  mojom::IpCameraFrameListenerPtr listener;
  binding_.Bind(mojo::MakeRequest(&listener));

  binding_.set_connection_error_handler(
      base::Bind(&CameraDevice::OnConnectionError, base::Unretained(this)));
  ip_device_.set_connection_error_handler(
      base::Bind(&CameraDevice::OnConnectionError, base::Unretained(this)));

  ip_device_->RegisterFrameListener(std::move(listener));

  return 0;
}

void CameraDevice::Open(const hw_module_t* module, hw_device_t** hw_device) {
  camera3_device_.common.module = const_cast<hw_module_t*>(module);
  *hw_device = &camera3_device_.common;
  open_ = true;
}

CameraDevice::~CameraDevice() {
  DCHECK(ipc_task_runner_->RunsTasksInCurrentSequence());

  if (jpeg_thread_.IsRunning()) {
    jpeg_thread_.Stop();
  }
  jda_.reset();

  ip_device_.reset();
  binding_.Close();
}

bool CameraDevice::IsOpen() {
  return open_;
}

android::CameraMetadata* CameraDevice::GetStaticMetadata() {
  return &static_metadata_;
}

int CameraDevice::Initialize(const camera3_callback_ops_t* callback_ops) {
  callback_ops_ = callback_ops;
  request_queue_.SetCallbacks(callback_ops_);

  return 0;
}

void CameraDevice::Close() {
  open_ = false;
  request_queue_.Flush();

  // If called from the HAL it won't be on the IPC thread, and we should tell
  // the IP camera to stop streaming. If called from the IPC thread, it's
  // because the connection was lost or the device was reported as disconnected,
  // so no need to tell it to stop streaming (the pointer probably isn't valid
  // anyway).
  if (!ipc_task_runner_->RunsTasksInCurrentSequence()) {
    auto return_val = Future<void>::Create(nullptr);
    ipc_task_runner_->PostTask(
        FROM_HERE, base::BindOnce(&CameraDevice::StopStreamingOnIpcThread,
                                  base::Unretained(this), return_val));
    return_val->Wait(-1);
  }
}

void CameraDevice::StopStreamingOnIpcThread(
    scoped_refptr<Future<void>> return_val) {
  DCHECK(ipc_task_runner_->RunsTasksInCurrentSequence());
  ip_device_->StopStreaming();
  return_val->Set();
}

bool CameraDevice::ValidateStream(camera3_stream_t* stream) {
  if (!stream) {
    LOGFID(ERROR, id_) << "NULL stream";
    return false;
  }

  if (stream->stream_type != CAMERA3_STREAM_OUTPUT) {
    LOGFID(ERROR, id_) << "Unsupported stream type: " << stream->stream_type;
    return false;
  }

  if (stream->width != width_) {
    LOGFID(ERROR, id_) << "Unsupported stream width: " << stream->width;
    return false;
  }

  if (stream->height != height_) {
    LOGFID(ERROR, id_) << "Unsupported stream height: " << stream->height;
    return false;
  }

  if (stream->format != format_) {
    LOGFID(ERROR, id_) << "Unsupported stream format: " << stream->format;
    return false;
  }

  if (stream->rotation != CAMERA3_STREAM_ROTATION_0) {
    LOGFID(ERROR, id_) << "Unsupported stream rotation: " << stream->rotation;
    return false;
  }

  return true;
}

int CameraDevice::ConfigureStreams(
    camera3_stream_configuration_t* stream_list) {
  DCHECK(!ipc_task_runner_->RunsTasksInCurrentSequence());

  if (callback_ops_ == nullptr) {
    LOGFID(ERROR, id_) << "Device is not initialized";
    return -EINVAL;
  }

  if (stream_list == nullptr) {
    LOGFID(ERROR, id_) << "Null stream list array";
    return -EINVAL;
  }

  if (stream_list->num_streams != 1) {
    LOGFID(ERROR, id_) << "Unsupported number of streams: "
                       << stream_list->num_streams;
    return -EINVAL;
  }

  if (stream_list->operation_mode != CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE) {
    LOGFID(ERROR, id_) << "Unsupported operation mode: "
                       << stream_list->operation_mode;
    return -EINVAL;
  }

  if (!ValidateStream(stream_list->streams[0])) {
    return -EINVAL;
  }

  // TODO(pceballos): revisit these two values, the number of buffers may need
  // to be adjusted by each different device
  stream_list->streams[0]->usage |= GRALLOC_USAGE_SW_WRITE_OFTEN;
  stream_list->streams[0]->max_buffers = 4;

  auto return_val = Future<void>::Create(nullptr);
  ipc_task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&CameraDevice::StartStreamingOnIpcThread,
                                base::Unretained(this), return_val));

  return_val->Wait(-1);
  return 0;
}

void CameraDevice::StartStreamingOnIpcThread(
    scoped_refptr<Future<void>> return_val) {
  DCHECK(ipc_task_runner_->RunsTasksInCurrentSequence());
  ip_device_->StartStreaming();
  return_val->Set();
}

const camera_metadata_t* CameraDevice::ConstructDefaultRequestSettings(
    int type) {
  if (type != CAMERA3_TEMPLATE_PREVIEW) {
    LOGFID(ERROR, id_) << "Unsupported request template:" << type;
    return nullptr;
  }
  return MetadataHandler::GetDefaultRequestSettings();
}

int CameraDevice::ProcessCaptureRequest(camera3_capture_request_t* request) {
  if (!request) {
    LOGFID(ERROR, id_) << "Received a NULL request";
    return -EINVAL;
  }

  if (request->input_buffer) {
    LOGFID(ERROR, id_) << "Input buffers are not supported";
    return -EINVAL;
  }

  if (request->num_output_buffers != 1) {
    LOGFID(ERROR, id_) << "Invalid number of output buffers: "
                       << request->num_output_buffers;
    return -EINVAL;
  }

  const camera3_stream_buffer_t* buffer = request->output_buffers;

  if (!ValidateStream(buffer->stream)) {
    return -EINVAL;
  }

  if (!open_) {
    LOGFID(ERROR, id_) << "Device is not open";
    return -ENODEV;
  }

  request_queue_.Push(request);

  return 0;
}

int CameraDevice::Flush() {
  request_queue_.Flush();
  return 0;
}

void CameraDevice::CopyFromMappingToOutputBuffer(
    base::ReadOnlySharedMemoryMapping* mapping, buffer_handle_t* buffer) {
  buffer_manager_->Register(*buffer);
  struct android_ycbcr ycbcr;

  if (buffer_manager_->GetV4L2PixelFormat(*buffer) != V4L2_PIX_FMT_NV12) {
    LOGF(FATAL)
        << "Output buffer is wrong pixel format, only NV12 is supported";
  }

  buffer_manager_->LockYCbCr(*buffer, 0, 0, 0, width_, height_, &ycbcr);

  // Convert from I420 to NV12 while copying the buffer since the buffer manager
  // allocates an NV12 buffer
  const uint8_t* in_y = reinterpret_cast<const uint8_t*>(mapping->memory());
  const uint8_t* in_u =
      reinterpret_cast<const uint8_t*>(mapping->memory()) + width_ * height_;
  const uint8_t* in_v = reinterpret_cast<const uint8_t*>(mapping->memory()) +
                        width_ * height_ * 5 / 4;
  uint8_t* out_y = reinterpret_cast<uint8_t*>(ycbcr.y);
  uint8_t* out_uv = reinterpret_cast<uint8_t*>(ycbcr.cb);

  int res = libyuv::I420ToNV12(in_y, width_, in_u, width_ / 4, in_v, width_ / 4,
                               out_y, ycbcr.ystride, out_uv, ycbcr.cstride,
                               width_, height_);
  if (res != 0) {
    LOGF(ERROR) << "Conversion from I420 to NV12 returned error: " << res;
  }

  buffer_manager_->Unlock(*buffer);
  buffer_manager_->Deregister(*buffer);
}

void CameraDevice::ReturnBufferOnIpcThread(int32_t id) {
  ip_device_->ReturnBuffer(id);
}

void CameraDevice::DecodeJpeg(base::ReadOnlySharedMemoryRegion shm,
                              int32_t id,
                              uint32_t size) {
  std::unique_ptr<CaptureRequest> request = request_queue_.Pop();
  if (!request) {
    ipc_task_runner_->PostTask(
        FROM_HERE, base::BindOnce(&CameraDevice::ReturnBufferOnIpcThread,
                                  base::Unretained(this), id));
    return;
  }
  buffer_handle_t* buffer = request->GetOutputBuffer()->buffer;

  base::subtle::ScopedFDPair fd =
      base::ReadOnlySharedMemoryRegion::TakeHandleForSerialization(
          std::move(shm))
          .PassPlatformHandle();
  JpegDecodeAccelerator::Error err =
      jda_->DecodeSync(fd.get().fd, size, 0, *buffer);
  if (err == JpegDecodeAccelerator::Error::TRY_START_AGAIN) {
    LOGFID(WARNING, id_) << "Restarting JPEG processor";
    if (!jda_->Start()) {
      LOGFID(ERROR, id_) << "Failed to restart JPEG processor";
    } else {
      err = jda_->DecodeSync(fd.get().fd, size, 0, *buffer);
    }
  }
  if (err != JpegDecodeAccelerator::Error::NO_ERRORS) {
    LOGFID(ERROR, id_) << "Jpeg decoder returned error";
    request_queue_.NotifyError(std::move(request));
    ipc_task_runner_->PostTask(
        FROM_HERE, base::BindOnce(&CameraDevice::ReturnBufferOnIpcThread,
                                  base::Unretained(this), id));
    return;
  }
  ipc_task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&CameraDevice::ReturnBufferOnIpcThread,
                                base::Unretained(this), id));

  // TODO(pceballos): Currently the JPEG decoder doesn't sync output buffer
  // memory. Force it to sync by locking then unlocking it.
  buffer_manager_->Register(*buffer);
  struct android_ycbcr ycbcr;
  buffer_manager_->LockYCbCr(*buffer, 0, 0, 0, width_, height_, &ycbcr);
  buffer_manager_->Unlock(*buffer);
  buffer_manager_->Deregister(*buffer);

  request_queue_.NotifyCapture(std::move(request));
}

void CameraDevice::OnFrameCaptured(mojo::ScopedSharedBufferHandle shm_handle,
                                   int32_t id,
                                   uint32_t size) {
  if (request_queue_.IsEmpty()) {
    ip_device_->ReturnBuffer(id);
    return;
  }

  base::ReadOnlySharedMemoryRegion shm =
      mojo::UnwrapReadOnlySharedMemoryRegion(std::move(shm_handle));
  if (!shm.IsValid()) {
    LOGFID(ERROR, id_) << "Error receiving shared memory region";
    ip_device_->ReturnBuffer(id);
    return;
  }

  if (jpeg_) {
    jpeg_thread_.task_runner()->PostTask(
        FROM_HERE,
        base::BindOnce(&CameraDevice::DecodeJpeg, base::Unretained(this),
                       std::move(shm), id, size));
    return;
  }

  base::ReadOnlySharedMemoryMapping mapping = shm.Map();
  if (!mapping.IsValid()) {
    LOGFID(ERROR, id_) << "Error mapping shm, unable to handle captured frame";
    ip_device_->ReturnBuffer(id);
    return;
  }

  std::unique_ptr<CaptureRequest> request = request_queue_.Pop();
  if (!request) {
    ip_device_->ReturnBuffer(id);
    return;
  }

  CopyFromMappingToOutputBuffer(&mapping, request->GetOutputBuffer()->buffer);

  ip_device_->ReturnBuffer(id);
  request_queue_.NotifyCapture(std::move(request));
}

void CameraDevice::OnConnectionError() {
  LOGF(ERROR) << "Lost connection to IP Camera";
  ip_device_.reset();
  binding_.Close();
}

void CameraDevice::StartJpegProcessor() {
  jda_ = JpegDecodeAccelerator::CreateInstance(
      CameraHal::GetInstance().GetMojoManagerToken());
  if (!jda_->Start()) {
    LOGF(ERROR) << "Error starting JPEG processor";
  }
}

}  // namespace cros
