/*
 * Copyright 2018 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/camera_mojo_channel_manager_impl.h"

#include <memory>
#include <utility>

#include <base/bind.h>
#include <base/logging.h>
#include <base/no_destructor.h>

#include "cros-camera/common.h"
#include "cros-camera/constants.h"
#include "cros-camera/ipc_util.h"

namespace cros {

// static
mojom::CameraHalDispatcherPtr CameraMojoChannelManagerImpl::dispatcher_;
base::Thread* CameraMojoChannelManagerImpl::ipc_thread_ = nullptr;
base::NoDestructor<base::Lock> CameraMojoChannelManagerImpl::static_lock_;
bool CameraMojoChannelManagerImpl::mojo_initialized_ = false;

// static
std::unique_ptr<CameraMojoChannelManager>
CameraMojoChannelManager::CreateInstance() {
  return base::WrapUnique<CameraMojoChannelManager>(
      new CameraMojoChannelManagerImpl());
}

CameraMojoChannelManagerImpl::CameraMojoChannelManagerImpl() {
  VLOGF_ENTER();
  bool success = InitializeMojoEnv();
  CHECK(success);
}

CameraMojoChannelManagerImpl::~CameraMojoChannelManagerImpl() {
  VLOGF_ENTER();
}

void CameraMojoChannelManagerImpl::CreateJpegDecodeAccelerator(
    mojom::JpegDecodeAcceleratorRequest request) {
  ipc_thread_->task_runner()->PostTask(
      FROM_HERE,
      base::Bind(
          &CameraMojoChannelManagerImpl::CreateJpegDecodeAcceleratorOnIpcThread,
          base::Unretained(this), base::Passed(std::move(request))));
}

void CameraMojoChannelManagerImpl::CreateJpegEncodeAccelerator(
    mojom::JpegEncodeAcceleratorRequest request) {
  ipc_thread_->task_runner()->PostTask(
      FROM_HERE,
      base::Bind(
          &CameraMojoChannelManagerImpl::CreateJpegEncodeAcceleratorOnIpcThread,
          base::Unretained(this), base::Passed(std::move(request))));
}

mojom::CameraAlgorithmOpsPtr
CameraMojoChannelManagerImpl::CreateCameraAlgorithmOpsPtr() {
  VLOGF_ENTER();

  mojo::ScopedMessagePipeHandle parent_pipe;
  mojom::CameraAlgorithmOpsPtr algorithm_ops;

  base::FilePath socket_path(constants::kCrosCameraAlgoSocketPathString);
  MojoResult result = cros::CreateMojoChannelToChildByUnixDomainSocket(
      socket_path, &parent_pipe);
  if (result != MOJO_RESULT_OK) {
    LOGF(WARNING) << "Failed to create Mojo Channel to" << socket_path.value();
    return nullptr;
  }

  algorithm_ops.Bind(
      mojom::CameraAlgorithmOpsPtrInfo(std::move(parent_pipe), 0u));

  LOGF(INFO) << "Connected to CameraAlgorithmOps";

  VLOGF_EXIT();
  return algorithm_ops;
}

void CameraMojoChannelManagerImpl::CreateJpegDecodeAcceleratorOnIpcThread(
    mojom::JpegDecodeAcceleratorRequest request) {
  DCHECK(ipc_thread_->task_runner()->BelongsToCurrentThread());

  EnsureDispatcherConnectedOnIpcThread();
  if (dispatcher_.is_bound()) {
    dispatcher_->GetJpegDecodeAccelerator(std::move(request));
  }
}

void CameraMojoChannelManagerImpl::CreateJpegEncodeAcceleratorOnIpcThread(
    mojom::JpegEncodeAcceleratorRequest request) {
  DCHECK(ipc_thread_->task_runner()->BelongsToCurrentThread());

  EnsureDispatcherConnectedOnIpcThread();
  if (dispatcher_.is_bound()) {
    dispatcher_->GetJpegEncodeAccelerator(std::move(request));
  }
}

bool CameraMojoChannelManagerImpl::InitializeMojoEnv() {
  VLOGF_ENTER();

  base::AutoLock l(*static_lock_);

  if (mojo_initialized_) {
    return true;
  }

  ipc_thread_ = new base::Thread("MojoIpcThread");
  if (!ipc_thread_->StartWithOptions(
          base::Thread::Options(base::MessageLoop::TYPE_IO, 0))) {
    LOGF(ERROR) << "Failed to start IPC Thread";
    delete ipc_thread_;
    ipc_thread_ = nullptr;
    return false;
  }
  mojo::edk::Init();
  mojo::edk::InitIPCSupport(ipc_thread_->task_runner());
  mojo_initialized_ = true;
  return true;
}

void CameraMojoChannelManagerImpl::EnsureDispatcherConnectedOnIpcThread() {
  DCHECK(ipc_thread_->task_runner()->BelongsToCurrentThread());
  VLOGF_ENTER();

  if (dispatcher_.is_bound()) {
    return;
  }

  mojo::ScopedMessagePipeHandle child_pipe;

  base::FilePath socket_path(constants::kCrosCameraSocketPathString);
  MojoResult result = cros::CreateMojoChannelToParentByUnixDomainSocket(
      socket_path, &child_pipe);
  if (result != MOJO_RESULT_OK) {
    LOGF(WARNING) << "Failed to create Mojo Channel to" << socket_path.value();
    return;
  }

  dispatcher_ = mojo::MakeProxy(
      mojom::CameraHalDispatcherPtrInfo(std::move(child_pipe), 0u),
      ipc_thread_->task_runner());
  dispatcher_.set_connection_error_handler(
      base::Bind(&CameraMojoChannelManagerImpl::OnDispatcherError));

  LOGF(INFO) << "Connected to CameraHalDispatcher";

  VLOGF_EXIT();
}

// static
__attribute__((destructor(101))) void
CameraMojoChannelManagerImpl::TearDownMojoEnv() {
  VLOGF_ENTER();

  base::AutoLock l(*static_lock_);

  if (!mojo_initialized_) {
    return;
  }

  ipc_thread_->task_runner()->PostTask(
      FROM_HERE,
      base::Bind(CameraMojoChannelManagerImpl::TearDownMojoEnvLockedOnThread));
  ipc_thread_->Stop();
  delete ipc_thread_;
  ipc_thread_ = nullptr;
}

// static
void CameraMojoChannelManagerImpl::TearDownMojoEnvLockedOnThread() {
  DCHECK(ipc_thread_->task_runner()->BelongsToCurrentThread());

  if (dispatcher_.is_bound()) {
    dispatcher_.reset();
  }
  mojo::edk::ShutdownIPCSupport(base::Bind(&base::DoNothing));
}

// static
void CameraMojoChannelManagerImpl::OnDispatcherError() {
  DCHECK(ipc_thread_->task_runner()->BelongsToCurrentThread());
  VLOGF_ENTER();
  LOGF(ERROR) << "Mojo channel to CameraHalDispatcher is broken";
  dispatcher_.reset();
}

}  // namespace cros
