// Copyright 2020 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 "sco_connection.h"

namespace bt::sco {

ScoConnection::ScoConnection(std::unique_ptr<hci::Connection> connection,
                             fit::closure deactivated_cb,
                             hci_spec::SynchronousConnectionParameters parameters,
                             hci::ScoDataChannel* channel)
    : active_(false),
      connection_(std::move(connection)),
      deactivated_cb_(std::move(deactivated_cb)),
      channel_(channel),
      parameters_(parameters),
      weak_ptr_factory_(this) {
  ZX_ASSERT(connection_);
  ZX_ASSERT(!channel_ ||
            channel_->max_data_length() <= hci_spec::kMaxSynchronousDataPacketPayloadSize);

  handle_ = connection_->handle();

  connection_->set_peer_disconnect_callback([this](auto, auto) {
    // Notifies activator that this connection has been disconnected.
    // Activator will call Deactivate().
    Close();
  });
}

ScoConnection::UniqueId ScoConnection::unique_id() const {
  // HCI connection handles are unique per controller.
  return handle();
}

ScoConnection::UniqueId ScoConnection::id() const { return unique_id(); }

void ScoConnection::Close() {
  bt_log(TRACE, "gap-sco", "closing sco connection (handle: %.4x)", handle());

  bool active = active_;
  CleanUp();

  if (!active) {
    return;
  }

  ZX_ASSERT(activator_closed_cb_);
  // Move cb out of this, since cb may destroy this.
  auto cb = std::move(activator_closed_cb_);
  cb();
}

bool ScoConnection::Activate(fit::closure rx_callback, fit::closure closed_callback) {
  // TODO(fxbug.dev/58458): Handle Activate() called on a connection that has been closed already.
  ZX_ASSERT(closed_callback);
  ZX_ASSERT(!active_);
  ZX_ASSERT(rx_callback);
  activator_closed_cb_ = std::move(closed_callback);
  rx_callback_ = std::move(rx_callback);
  active_ = true;
  if (channel_ && parameters_.input_data_path == hci_spec::ScoDataPath::kHci) {
    channel_->RegisterConnection(weak_ptr_factory_.GetWeakPtr());
  }
  return true;
}

void ScoConnection::Deactivate() {
  bt_log(TRACE, "gap-sco", "deactivating sco connection (handle: %.4x)", handle());
  CleanUp();
  if (deactivated_cb_) {
    // Move cb out of this, since cb may destroy this.
    auto cb = std::move(deactivated_cb_);
    cb();
  }
}

uint16_t ScoConnection::max_tx_sdu_size() const {
  return channel_ ? channel_->max_data_length() : 0u;
}

bool ScoConnection::Send(ByteBufferPtr payload) {
  if (!active_) {
    bt_log(WARN, "gap-sco", "dropping SCO packet for inactive connection (handle: %#.4x)", handle_);
    return false;
  }

  if (!channel_) {
    bt_log(WARN, "gap-sco", "dropping SCO packet because HCI SCO is not supported (handle: %#.4x)",
           handle_);
    return false;
  }

  if (payload->size() > channel_->max_data_length()) {
    bt_log(WARN, "gap-sco",
           "dropping SCO packet larger than the buffer data packet length (packet size: %zu, max "
           "data length: "
           "%hu)",
           payload->size(), channel_->max_data_length());
    return false;
  }

  outbound_queue_.push(std::move(payload));

  // Notify ScoDataChannel that a packet is available. This is only necessary for the first
  // packet of an empty queue (flow control will poll this connection otherwise).
  if (outbound_queue_.size() == 1u) {
    channel_->OnOutboundPacketReadable();
  }
  return true;
}

std::unique_ptr<hci::ScoDataPacket> ScoConnection::Read() {
  if (inbound_queue_.empty()) {
    return nullptr;
  }
  std::unique_ptr<hci::ScoDataPacket> packet = std::move(inbound_queue_.front());
  inbound_queue_.pop();
  return packet;
}

hci_spec::SynchronousConnectionParameters ScoConnection::parameters() { return parameters_; }

std::unique_ptr<hci::ScoDataPacket> ScoConnection::GetNextOutboundPacket() {
  if (outbound_queue_.empty()) {
    return nullptr;
  }

  std::unique_ptr<hci::ScoDataPacket> out =
      hci::ScoDataPacket::New(handle(), static_cast<uint8_t>(outbound_queue_.front()->size()));
  if (!out) {
    bt_log(ERROR, "gap-sco", "failed to allocate SCO data packet");
    return nullptr;
  }
  out->mutable_view()->mutable_payload_data().Write(outbound_queue_.front()->view());
  outbound_queue_.pop();
  return out;
}

void ScoConnection::ReceiveInboundPacket(std::unique_ptr<hci::ScoDataPacket> packet) {
  ZX_ASSERT(packet->connection_handle() == handle_);

  if (!active_ || !rx_callback_) {
    bt_log(TRACE, "gap-sco", "dropping inbound SCO packet");
    return;
  }

  inbound_queue_.push(std::move(packet));
  // It's only necessary to notify activator of the first packet queued (flow control will poll this
  // connection otherwise).
  if (inbound_queue_.size() == 1u) {
    rx_callback_();
  }
}

void ScoConnection::OnHciError() {
  // Notify activator that this connection should be deactivated.
  Close();
}

void ScoConnection::CleanUp() {
  if (active_ && channel_ && parameters_.input_data_path == hci_spec::ScoDataPath::kHci) {
    channel_->UnregisterConnection(handle_);
  }
  active_ = false;
  connection_ = nullptr;
}

}  // namespace bt::sco
