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

#include <errno.h>
#include <utility>

#include <base/no_destructor.h>
#include <base/sequence_checker.h>
#include <mojo/core/embedder/embedder.h>
#include <mojo/core/embedder/scoped_ipc_support.h>
#include <mojo/public/cpp/bindings/binding.h>

#include "common/libcamera_connector/types.h"
#include "cros-camera/common.h"
#include "cros-camera/constants.h"
#include "cros-camera/future.h"
#include "cros-camera/ipc_util.h"
#include "mojo/unguessable_token.mojom.h"

namespace cros {

CameraServiceConnector::CameraServiceConnector()
    : ipc_thread_("CamConn"), camera_client_(nullptr) {}

CameraServiceConnector* CameraServiceConnector::GetInstance() {
  static base::NoDestructor<CameraServiceConnector> instance;
  return instance.get();
}

int CameraServiceConnector::Init(const cros_cam_init_option_t* option) {
  VLOGF_ENTER();
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  if (initialized_.IsSet()) {
    LOGF(ERROR) << "Should not run init() more than once";
    return -EPERM;
  }

  // TODO(b/170075468): Remove support for api_version 0 when Parallels migrates
  // to api_version 1.
  if (option->api_version >= 1) {
    token_ = TokenFromString(option->token);
    if (token_.is_empty()) {
      LOGF(ERROR) << "Failed to parse token string";
      return -EPERM;
    }
  }

  mojo::core::Init();
  bool ret = ipc_thread_.StartWithOptions(
      base::Thread::Options(base::MessagePumpType::IO, 0));
  if (!ret) {
    LOGF(ERROR) << "Failed to start IPC thread";
    return -ENODEV;
  }
  ipc_support_ = std::make_unique<mojo::core::ScopedIPCSupport>(
      ipc_thread_.task_runner(),
      mojo::core::ScopedIPCSupport::ShutdownPolicy::CLEAN);

  auto future = cros::Future<int>::Create(nullptr);
  ipc_thread_.task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(&CameraServiceConnector::InitOnThread,
                     base::Unretained(this), GetFutureCallback(future)));
  int result = future->Get();
  if (result == 0) {
    initialized_.Set();
  }
  return result;
}

int CameraServiceConnector::Exit() {
  VLOGF_ENTER();
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  if (!initialized_.IsSet()) {
    LOGF(ERROR) << "Should run init() before other functions";
    return -EPERM;
  }

  int ret = camera_client_->Exit();

  ipc_support_ = nullptr;
  ipc_thread_.Stop();

  return ret;
}

int CameraServiceConnector::GetCameraInfo(cros_cam_get_cam_info_cb_t callback,
                                          void* context) {
  if (!initialized_.IsSet()) {
    LOGF(ERROR) << "Should run init() before other functions";
    return -EPERM;
  }

  return camera_client_->SetCameraInfoCallback(callback, context);
}

int CameraServiceConnector::StartCapture(
    const cros_cam_capture_request_t* request,
    cros_cam_capture_cb_t callback,
    void* context) {
  if (!initialized_.IsSet()) {
    LOGF(ERROR) << "Should run init() before other functions";
    return -EPERM;
  }

  LOGF(INFO) << "StartCapture";
  return camera_client_->StartCapture(request, callback, context);
}

int CameraServiceConnector::StopCapture(int id) {
  if (!initialized_.IsSet()) {
    LOGF(ERROR) << "Should run init() before other functions";
    return -EPERM;
  }

  return camera_client_->StopCapture(id);
}

void CameraServiceConnector::RegisterClient(
    mojom::CameraHalClientPtr camera_hal_client,
    IntOnceCallback on_registered_callback) {
  VLOGF_ENTER();
  // This may be called from a different thread than the main thread,
  // (for example here it is called from CameraClient thread),
  // but mojo operations have to run on the same thread that bound
  // the interface, so we bounce the request over to that thread/runner.
  ipc_thread_.task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(&CameraServiceConnector::RegisterClientOnThread,
                     base::Unretained(this), std::move(camera_hal_client),
                     std::move(on_registered_callback)));
}

void CameraServiceConnector::RegisterClientOnThread(
    mojom::CameraHalClientPtr camera_hal_client,
    IntOnceCallback on_registered_callback) {
  VLOGF_ENTER();
  DCHECK(ipc_thread_.task_runner()->BelongsToCurrentThread());

  if (token_.is_empty()) {
    // TODO(b/170075468): Remove when this method is deprecated.
    dispatcher_->RegisterClient(std::move(camera_hal_client));
    std::move(on_registered_callback).Run(0);
  } else {
    auto mojo_token = mojo_base::mojom::UnguessableToken::New();
    mojo_token->high = token_.GetHighForSerialization();
    mojo_token->low = token_.GetLowForSerialization();
    dispatcher_->RegisterClientWithToken(
        std::move(camera_hal_client), cros::mojom::CameraClientType::UNKNOWN,
        std::move(mojo_token),
        base::BindOnce(&CameraServiceConnector::OnRegisteredClient,
                       base::Unretained(this),
                       std::move(on_registered_callback)));
  }
}

void CameraServiceConnector::OnRegisteredClient(
    IntOnceCallback on_registered_callback, int32_t result) {
  VLOGF_ENTER();
  DCHECK(ipc_thread_.task_runner()->BelongsToCurrentThread());

  if (result != 0) {
    LOGF(ERROR) << "Failed to register client: " << result;
  }
  std::move(on_registered_callback).Run(result);
}

void CameraServiceConnector::InitOnThread(IntOnceCallback init_callback) {
  VLOGF_ENTER();
  DCHECK(ipc_thread_.task_runner()->BelongsToCurrentThread());

  mojo::ScopedMessagePipeHandle child_pipe;
  base::FilePath socket_path(constants::kCrosCameraSocketPathString);
  MojoResult res =
      CreateMojoChannelToParentByUnixDomainSocket(socket_path, &child_pipe);
  if (res != MOJO_RESULT_OK) {
    LOGF(ERROR) << "Failed to create mojo channel to dispatcher";
    std::move(init_callback).Run(-ENODEV);
    return;
  }

  dispatcher_ = mojo::MakeProxy(
      mojom::CameraHalDispatcherPtrInfo(std::move(child_pipe), 0u),
      ipc_thread_.task_runner());
  bool connected = dispatcher_.is_bound();
  if (!connected) {
    LOGF(ERROR) << "Failed to make a proxy to dispatcher";
    std::move(init_callback).Run(-ENODEV);
    return;
  }
  dispatcher_.set_connection_error_handler(base::BindOnce(
      &CameraServiceConnector::OnDispatcherError, base::Unretained(this)));
  LOGF(INFO) << "Dispatcher connected";

  camera_client_ = std::make_unique<CameraClient>();
  camera_client_->Init(base::BindOnce(&CameraServiceConnector::RegisterClient,
                                      base::Unretained(this)),
                       std::move(init_callback));
}

void CameraServiceConnector::OnDispatcherError() {
  VLOGF_ENTER();
  // TODO(b/151047930): Attempt to reconnect on dispatcher error.
  LOGF(FATAL) << "Connection to camera dispatcher lost";
}

}  // namespace cros
