// Copyright 2017 The Fuchsia 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 "transport.h"

#include <lib/async/default.h>
#include <lib/zx/channel.h>
#include <zircon/assert.h>
#include <zircon/status.h>

#include "src/connectivity/bluetooth/core/bt-host/common/log.h"

#include "device_wrapper.h"

namespace bt {
namespace hci {

// static
fxl::RefPtr<Transport> Transport::Create(
    std::unique_ptr<DeviceWrapper> hci_device) {
  return AdoptRef(new Transport(std::move(hci_device)));
}

Transport::Transport(std::unique_ptr<DeviceWrapper> hci_device)
    : hci_device_(std::move(hci_device)),
      is_initialized_(false),
      io_dispatcher_(nullptr),
      closed_cb_dispatcher_(nullptr) {
  ZX_DEBUG_ASSERT(hci_device_);
}

Transport::~Transport() {
  // Do nothing. Since Transport is shared across threads, this can be called
  // from any thread and calling ShutDown() would be unsafe.
}

bool Transport::Initialize(async_dispatcher_t* dispatcher) {
  ZX_DEBUG_ASSERT(thread_checker_.IsCreationThreadCurrent());
  ZX_DEBUG_ASSERT(hci_device_);
  ZX_DEBUG_ASSERT(!command_channel_);
  ZX_DEBUG_ASSERT(!acl_data_channel_);
  ZX_DEBUG_ASSERT(!IsInitialized());

  // Obtain command channel handle.
  zx::channel channel = hci_device_->GetCommandChannel();
  if (!channel.is_valid()) {
    bt_log(ERROR, "hci", "failed to obtain command channel handle");
    return false;
  }

  if (dispatcher) {
    io_dispatcher_ = dispatcher;
  } else {
    io_loop_ = std::make_unique<async::Loop>(&kAsyncLoopConfigNoAttachToThread);
    io_loop_->StartThread("hci-transport-io");
    io_dispatcher_ = io_loop_->dispatcher();
  }

  // We watch for handle errors and closures to perform the necessary clean up.
  WatchChannelClosed(channel, cmd_channel_wait_);
  command_channel_ = std::make_unique<CommandChannel>(this, std::move(channel));
  command_channel_->Initialize();

  is_initialized_ = true;

  return true;
}

bool Transport::InitializeACLDataChannel(
    const DataBufferInfo& bredr_buffer_info,
    const DataBufferInfo& le_buffer_info) {
  ZX_DEBUG_ASSERT(hci_device_);
  ZX_DEBUG_ASSERT(IsInitialized());

  // Obtain ACL data channel handle.
  zx::channel channel = hci_device_->GetACLDataChannel();
  if (!channel.is_valid()) {
    bt_log(ERROR, "hci", "failed to obtain ACL data channel handle");
    return false;
  }

  // We watch for handle errors and closures to perform the necessary clean up.
  WatchChannelClosed(channel, acl_channel_wait_);

  acl_data_channel_ =
      std::make_unique<ACLDataChannel>(this, std::move(channel));
  acl_data_channel_->Initialize(bredr_buffer_info, le_buffer_info);

  return true;
}

void Transport::SetTransportClosedCallback(
    fit::closure callback,
    async_dispatcher_t* dispatcher) {
  ZX_DEBUG_ASSERT(callback);
  ZX_DEBUG_ASSERT(dispatcher);
  ZX_DEBUG_ASSERT(!closed_cb_);
  ZX_DEBUG_ASSERT(!closed_cb_dispatcher_);

  closed_cb_ = std::move(callback);
  closed_cb_dispatcher_ = dispatcher;
}

void Transport::ShutDown() {
  ZX_DEBUG_ASSERT(thread_checker_.IsCreationThreadCurrent());
  ZX_DEBUG_ASSERT(IsInitialized());

  bt_log(INFO, "hci", "transport shutting down");

  if (acl_data_channel_) {
    acl_data_channel_->ShutDown();
  }
  if (command_channel_) {
    command_channel_->ShutDown();
  }

  async::PostTask(io_dispatcher_, [this] {
    cmd_channel_wait_.Cancel();
    if (acl_data_channel_) {
      acl_channel_wait_.Cancel();
    }
    if (io_loop_) {
      io_loop_->Quit();
    }
  });

  if (io_loop_) {
    io_loop_->JoinThreads();
  }

  // We avoid deallocating the channels here as they *could* still be accessed
  // by other threads. It's OK to clear |io_dispatcher_| as the channels hold
  // their own references to it.
  //
  // Once |io_loop_| joins above, |io_dispatcher_| may be defunct. However,
  // the channels are allowed to keep posting tasks on it (which will never
  // execute).
  io_dispatcher_ = nullptr;
  is_initialized_ = false;
  bt_log(INFO, "hci", "I/O loop exited");
}

bool Transport::IsInitialized() const {
  return is_initialized_;
}

void Transport::WatchChannelClosed(const zx::channel& channel,
                                   Waiter& wait) {
  async::PostTask(
      io_dispatcher_, [ handle = channel.get(), &wait, ref = fxl::Ref(this) ] {
        wait.set_object(handle);
        wait.set_trigger(ZX_CHANNEL_PEER_CLOSED);
        zx_status_t status = wait.Begin(async_get_default_dispatcher());
        if (status != ZX_OK) {
          bt_log(ERROR, "hci", "failed to set up closed handler: %s",
                 zx_status_get_string(status));
          wait.set_object(ZX_HANDLE_INVALID);
        }
      });
}

void Transport::OnChannelClosed(
    async_dispatcher_t* dispatcher,
    async::WaitBase* wait,
    zx_status_t status,
    const zx_packet_signal_t* signal) {
  if (status != ZX_OK) {
    bt_log(ERROR, "hci", "channel error: %s", zx_status_get_string(status));
  } else {
    ZX_DEBUG_ASSERT(signal->observed & ZX_CHANNEL_PEER_CLOSED);
  }
  NotifyClosedCallback();
}

void Transport::NotifyClosedCallback() {
  // Clear the handlers so that we stop receiving events.
  cmd_channel_wait_.Cancel();
  if (acl_data_channel_) {
    acl_channel_wait_.Cancel();
  }

  bt_log(INFO, "hci", "channel(s) were closed");
  if (closed_cb_) {
    async::PostTask(closed_cb_dispatcher_, closed_cb_.share());
  }
}

}  // namespace hci
}  // namespace bt
