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

#include <lib/async/default.h>
#include <zircon/device/bt-hci.h>
#include <zircon/status.h>

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

namespace bt {
namespace testing {

FakeControllerBase::FakeControllerBase() {}

FakeControllerBase::~FakeControllerBase() {
  // When this destructor gets called any subclass state will be undefined. If
  // Stop() has not been called before reaching this point this can cause
  // runtime errors when our event loop handlers attempt to invoke the pure
  // virtual methods of this class.
}

bool FakeControllerBase::StartCmdChannel(zx::channel chan) {
  if (cmd_channel_.is_valid()) {
    return false;
  }

  cmd_channel_ = std::move(chan);
  cmd_channel_wait_.set_object(cmd_channel_.get());
  cmd_channel_wait_.set_trigger(ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED);
  zx_status_t status = cmd_channel_wait_.Begin(async_get_default_dispatcher());
  if (status != ZX_OK) {
    cmd_channel_.reset();
    bt_log(WARN, "fake-hci", "failed to start command channel: %s", zx_status_get_string(status));
    return false;
  }
  return true;
}

bool FakeControllerBase::StartAclChannel(zx::channel chan) {
  if (acl_channel_.is_valid()) {
    return false;
  }

  acl_channel_ = std::move(chan);
  acl_channel_wait_.set_object(acl_channel_.get());
  acl_channel_wait_.set_trigger(ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED);
  zx_status_t status = acl_channel_wait_.Begin(async_get_default_dispatcher());
  if (status != ZX_OK) {
    acl_channel_.reset();
    bt_log(WARN, "fake-hci", "failed to start ACL channel: %s", zx_status_get_string(status));
    return false;
  }
  return true;
}

bool FakeControllerBase::StartSnoopChannel(zx::channel chan) {
  if (snoop_channel_.is_valid()) {
    return false;
  }
  snoop_channel_ = std::move(chan);
  return true;
}

void FakeControllerBase::Stop() {
  CloseCommandChannel();
  CloseACLDataChannel();
  CloseSnoopChannel();
}

zx_status_t FakeControllerBase::SendCommandChannelPacket(const ByteBuffer& packet) {
  zx_status_t status = cmd_channel_.write(0, packet.data(), packet.size(), nullptr, 0);
  if (status != ZX_OK) {
    bt_log(WARN, "fake-hci", "failed to write to control channel: %s",
           zx_status_get_string(status));
    return status;
  }

  SendSnoopChannelPacket(packet, BT_HCI_SNOOP_TYPE_EVT, true);

  return ZX_OK;
}

zx_status_t FakeControllerBase::SendACLDataChannelPacket(const ByteBuffer& packet) {
  zx_status_t status = acl_channel_.write(0, packet.data(), packet.size(), nullptr, 0);
  if (status != ZX_OK) {
    bt_log(WARN, "fake-hci", "failed to write to ACL data channel: %s",
           zx_status_get_string(status));
    return status;
  }

  SendSnoopChannelPacket(packet, BT_HCI_SNOOP_TYPE_ACL, true);

  return ZX_OK;
}

void FakeControllerBase::SendSnoopChannelPacket(const ByteBuffer& packet,
                                                bt_hci_snoop_type_t packet_type, bool is_received) {
  if (snoop_channel_.is_valid()) {
    uint8_t snoop_buffer[packet.size() + 1];
    uint8_t flags = bt_hci_snoop_flags(packet_type, is_received);

    snoop_buffer[0] = flags;
    memcpy(snoop_buffer + 1, packet.data(), packet.size());
    zx_status_t status = snoop_channel_.write(0, snoop_buffer, packet.size() + 1, nullptr, 0);
    if (status != ZX_OK) {
      bt_log(WARN, "fake-hci", "cleaning up snoop channel after failed write: %s",
             zx_status_get_string(status));
      CloseSnoopChannel();
    }
  }
}

void FakeControllerBase::CloseCommandChannel() {
  if (cmd_channel_.is_valid()) {
    cmd_channel_wait_.Cancel();
    cmd_channel_wait_.set_object(ZX_HANDLE_INVALID);
    cmd_channel_.reset();
  }
}

void FakeControllerBase::CloseACLDataChannel() {
  if (acl_channel_.is_valid()) {
    acl_channel_wait_.Cancel();
    acl_channel_wait_.set_object(ZX_HANDLE_INVALID);
    acl_channel_.reset();
  }
}

void FakeControllerBase::CloseSnoopChannel() {
  if (snoop_channel_.is_valid()) {
    snoop_channel_.reset();
  }
}

void FakeControllerBase::HandleCommandPacket(async_dispatcher_t* dispatcher, async::WaitBase* wait,
                                             zx_status_t wait_status,
                                             const zx_packet_signal_t* signal) {
  StaticByteBuffer<hci::kMaxCommandPacketPayloadSize> buffer;
  uint32_t read_size;
  zx_status_t status = cmd_channel_.read(0u, buffer.mutable_data(), nullptr,
                                         hci::kMaxCommandPacketPayloadSize, 0, &read_size, nullptr);
  ZX_DEBUG_ASSERT(status == ZX_OK || status == ZX_ERR_PEER_CLOSED);
  if (status < 0) {
    if (status == ZX_ERR_PEER_CLOSED) {
      bt_log(INFO, "fake-hci", "command channel was closed");
    } else {
      bt_log(ERROR, "fake-hci", "failed to read on cmd channel: %s", zx_status_get_string(status));
    }
    CloseCommandChannel();
    return;
  }

  if (read_size < sizeof(hci::CommandHeader)) {
    bt_log(ERROR, "fake-hci", "malformed command packet received");
  } else {
    MutableBufferView view(buffer.mutable_data(), read_size);
    PacketView<hci::CommandHeader> packet(&view, read_size - sizeof(hci::CommandHeader));
    SendSnoopChannelPacket(packet.data(), BT_HCI_SNOOP_TYPE_CMD, false);
    OnCommandPacketReceived(packet);
  }

  status = wait->Begin(dispatcher);
  if (status != ZX_OK) {
    bt_log(ERROR, "fake-hci", "failed to wait on cmd channel: %s", zx_status_get_string(status));
    CloseCommandChannel();
  }
}

void FakeControllerBase::HandleACLPacket(async_dispatcher_t* dispatcher, async::WaitBase* wait,
                                         zx_status_t wait_status,
                                         const zx_packet_signal_t* signal) {
  StaticByteBuffer<hci::kMaxACLPayloadSize + sizeof(hci::ACLDataHeader)> buffer;
  uint32_t read_size;
  zx_status_t status =
      acl_channel_.read(0u, buffer.mutable_data(), nullptr, buffer.size(), 0, &read_size, nullptr);
  ZX_DEBUG_ASSERT(status == ZX_OK || status == ZX_ERR_PEER_CLOSED);
  if (status < 0) {
    if (status == ZX_ERR_PEER_CLOSED) {
      bt_log(INFO, "fake-hci", "ACL channel was closed");
    } else {
      bt_log(ERROR, "fake-hci", "failed to read on ACL channel: %s", zx_status_get_string(status));
    }

    CloseACLDataChannel();
    return;
  }

  BufferView view(buffer.data(), read_size);
  SendSnoopChannelPacket(view, BT_HCI_SNOOP_TYPE_ACL, false);
  OnACLDataPacketReceived(view);

  status = wait->Begin(dispatcher);
  if (status != ZX_OK) {
    bt_log(ERROR, "fake-hci", "failed to wait on ACL channel: %s", zx_status_get_string(status));
    CloseACLDataChannel();
  }
}

}  // namespace testing
}  // namespace bt
