// Copyright 2015 The Chromium 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 "mojo/edk/system/ipc_support.h"

#include <type_traits>
#include <utility>

#include "base/logging.h"
#include "mojo/edk/embedder/master_process_delegate.h"
#include "mojo/edk/embedder/slave_process_delegate.h"
#include "mojo/edk/system/channel_manager.h"
#include "mojo/edk/system/master_connection_manager.h"
#include "mojo/edk/system/message_pipe_dispatcher.h"
#include "mojo/edk/system/slave_connection_manager.h"

using mojo::platform::PlatformHandleWatcher;
using mojo::platform::ScopedPlatformHandle;
using mojo::platform::TaskRunner;
using mojo::util::RefPtr;

namespace mojo {
namespace system {

IPCSupport::IPCSupport(embedder::PlatformSupport* platform_support,
                       embedder::ProcessType process_type,
                       RefPtr<TaskRunner>&& delegate_thread_task_runner,
                       embedder::ProcessDelegate* process_delegate,
                       RefPtr<TaskRunner>&& io_task_runner,
                       PlatformHandleWatcher* io_watcher,
                       ScopedPlatformHandle platform_handle)
    : process_type_(process_type),
      delegate_thread_task_runner_(std::move(delegate_thread_task_runner)),
      process_delegate_(process_delegate),
      io_task_runner_(std::move(io_task_runner)),
      io_watcher_(io_watcher) {
  DCHECK(delegate_thread_task_runner_);
  DCHECK(io_task_runner_);
  DCHECK(io_watcher_);

  switch (process_type_) {
    case embedder::ProcessType::UNINITIALIZED:
      CHECK(false);
      break;
    case embedder::ProcessType::NONE:
      DCHECK(!platform_handle.is_valid());  // We wouldn't do anything with it.
      // Nothing to do.
      break;
    case embedder::ProcessType::MASTER:
      DCHECK(!platform_handle.is_valid());  // We wouldn't do anything with it.
      connection_manager_.reset(
          new system::MasterConnectionManager(platform_support));
      static_cast<system::MasterConnectionManager*>(connection_manager_.get())
          ->Init(
              delegate_thread_task_runner_.Clone(),
              static_cast<embedder::MasterProcessDelegate*>(process_delegate_));
      break;
    case embedder::ProcessType::SLAVE:
      connection_manager_.reset(
          new system::SlaveConnectionManager(platform_support));
      static_cast<system::SlaveConnectionManager*>(connection_manager_.get())
          ->Init(
              delegate_thread_task_runner_.Clone(),
              static_cast<embedder::SlaveProcessDelegate*>(process_delegate_),
              platform_handle.Pass());
      break;
  }

  channel_manager_.reset(
      new ChannelManager(platform_support, io_task_runner_.Clone(), io_watcher_,
                         connection_manager_.get()));
}

IPCSupport::~IPCSupport() {
  DCHECK_EQ(process_type_, embedder::ProcessType::UNINITIALIZED);
}

void IPCSupport::ShutdownOnIOThread() {
  DCHECK_NE(process_type_, embedder::ProcessType::UNINITIALIZED);

  channel_manager_->ShutdownOnIOThread();
  channel_manager_.reset();

  if (connection_manager_) {
    connection_manager_->Shutdown();
    connection_manager_.reset();
  }

  io_watcher_ = nullptr;
  io_task_runner_ = nullptr;
  process_delegate_ = nullptr;
  delegate_thread_task_runner_ = nullptr;
  process_type_ = embedder::ProcessType::UNINITIALIZED;
}

ConnectionIdentifier IPCSupport::GenerateConnectionIdentifier() {
  return connection_manager()->GenerateConnectionIdentifier();
}

RefPtr<MessagePipeDispatcher> IPCSupport::ConnectToSlave(
    const ConnectionIdentifier& connection_id,
    embedder::SlaveInfo slave_info,
    ScopedPlatformHandle platform_handle,
    std::function<void()>&& callback,
    RefPtr<TaskRunner>&& callback_thread_task_runner,
    ChannelId* channel_id) {
  DCHECK(channel_id);

  // We rely on |ChannelId| and |ProcessIdentifier| being identical types.
  static_assert(std::is_same<ChannelId, ProcessIdentifier>::value,
                "ChannelId and ProcessIdentifier types don't match");

  ScopedPlatformHandle platform_connection_handle = ConnectToSlaveInternal(
      connection_id, slave_info, platform_handle.Pass(), channel_id);
  return channel_manager()->CreateChannel(
      *channel_id, platform_connection_handle.Pass(), std::move(callback),
      std::move(callback_thread_task_runner));
}

RefPtr<MessagePipeDispatcher> IPCSupport::ConnectToMaster(
    const ConnectionIdentifier& connection_id,
    std::function<void()>&& callback,
    RefPtr<TaskRunner>&& callback_thread_task_runner,
    ChannelId* channel_id) {
  DCHECK(channel_id);

  static_assert(std::is_same<ChannelId, ProcessIdentifier>::value,
                "ChannelId and ProcessIdentifier types don't match");
  ScopedPlatformHandle platform_connection_handle =
      ConnectToMasterInternal(connection_id);
  *channel_id = kMasterProcessIdentifier;
  return channel_manager()->CreateChannel(
      *channel_id, platform_connection_handle.Pass(), std::move(callback),
      std::move(callback_thread_task_runner));
}

ScopedPlatformHandle IPCSupport::ConnectToSlaveInternal(
    const ConnectionIdentifier& connection_id,
    embedder::SlaveInfo slave_info,
    ScopedPlatformHandle platform_handle,
    ProcessIdentifier* slave_process_identifier) {
  DCHECK(slave_process_identifier);
  DCHECK_EQ(process_type_, embedder::ProcessType::MASTER);

  *slave_process_identifier =
      static_cast<system::MasterConnectionManager*>(connection_manager())
          ->AddSlaveAndBootstrap(slave_info, platform_handle.Pass(),
                                 connection_id);

  system::ProcessIdentifier peer_id = system::kInvalidProcessIdentifier;
  bool is_first;
  ScopedPlatformHandle platform_connection_handle;
  CHECK_EQ(connection_manager()->Connect(connection_id, &peer_id, &is_first,
                                         &platform_connection_handle),
           ConnectionManager::Result::SUCCESS_CONNECT_NEW_CONNECTION);
  DCHECK_EQ(peer_id, *slave_process_identifier);
  DCHECK(platform_connection_handle.is_valid());
  return platform_connection_handle;
}

ScopedPlatformHandle IPCSupport::ConnectToMasterInternal(
    const ConnectionIdentifier& connection_id) {
  DCHECK_EQ(process_type_, embedder::ProcessType::SLAVE);

  system::ProcessIdentifier peer_id = system::kInvalidProcessIdentifier;
  bool is_first;
  ScopedPlatformHandle platform_connection_handle;
  CHECK_EQ(connection_manager()->Connect(connection_id, &peer_id, &is_first,
                                         &platform_connection_handle),
           ConnectionManager::Result::SUCCESS_CONNECT_NEW_CONNECTION);
  DCHECK_EQ(peer_id, system::kMasterProcessIdentifier);
  DCHECK(platform_connection_handle.is_valid());
  return platform_connection_handle;
}

}  // namespace system
}  // namespace mojo
