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

#include <lib/async/default.h>

namespace bt::gap {

namespace {

const char* const kInspectPeerIdPropertyName = "peer_id";

}

BrEdrConnection::BrEdrConnection(PeerId peer_id, std::unique_ptr<hci::Connection> link,
                                 fit::closure send_auth_request_cb, fit::closure disconnect_cb,
                                 fit::closure on_peer_disconnect_cb, PeerCache* peer_cache,
                                 fbl::RefPtr<l2cap::L2cap> l2cap,
                                 fxl::WeakPtr<hci::Transport> transport,
                                 std::optional<Request> request)
    : ready_(false),
      peer_id_(peer_id),
      link_(std::move(link)),
      pairing_state_(std::make_unique<PairingState>(
          peer_id, link_.get(), peer_cache, std::move(send_auth_request_cb),
          [peer_id, disconnect_cb = std::move(disconnect_cb)](auto, hci::Status status) {
            if (bt_is_error(status, DEBUG, "gap-bredr",
                            "PairingState error status, disconnecting (peer id: %s)",
                            bt_str(peer_id))) {
              disconnect_cb();
            }
          })),
      request_(std::move(request)),
      domain_(std::move(l2cap)),
      sco_manager_(std::make_unique<sco::ScoConnectionManager>(
          peer_id_, link_->handle(), link_->peer_address(), link_->local_address(), transport)),
      create_time_(async::Now(async_get_default_dispatcher())) {
  link_->set_peer_disconnect_callback([peer_disconnect_cb = std::move(on_peer_disconnect_cb)](
                                          auto conn, auto /*reason*/) { peer_disconnect_cb(); });
}

BrEdrConnection::~BrEdrConnection() {
  if (request_.has_value()) {
    // Connection never completed so signal the requester(s).
    request_->NotifyCallbacks(hci::Status(HostError::kNotSupported), [] { return nullptr; });
  }

  sco_manager_.reset();
  pairing_state_.reset();
  link_.reset();
}

void BrEdrConnection::Start() {
  ZX_ASSERT_MSG(!ready_, "Start on a connection that's already started");
  ready_ = true;

  // Fulfill and clear request so that the dtor does not signal requester(s) with errors.
  if (auto request = std::exchange(request_, std::nullopt); request.has_value()) {
    request->NotifyCallbacks(hci::Status(), [this] { return this; });
  }
}

void BrEdrConnection::AddRequestCallback(BrEdrConnection::Request::OnComplete cb) {
  if (ready_) {
    cb(hci::Status(), this);
    return;
  }

  ZX_ASSERT(request_);
  request_->AddCallback(std::move(cb));
}

void BrEdrConnection::OpenL2capChannel(l2cap::PSM psm, l2cap::ChannelParameters params,
                                       l2cap::ChannelCallback cb) {
  if (!ready_) {
    // Connection is not yet ready for L2CAP; return a null channel.
    bt_log(INFO, "gap-bredr", "Connection to %s not complete; canceling channel to PSM %.4x",
           bt_str(peer_id()), psm);
    cb(nullptr);
    return;
  }

  bt_log(INFO, "gap-bredr", "opening l2cap channel on psm %#.4x (peer: %s)", psm,
         bt_str(peer_id()));
  domain_->OpenL2capChannel(link().handle(), psm, params, std::move(cb));
}

BrEdrConnection::ScoRequestHandle BrEdrConnection::OpenScoConnection(
    bool initiator, hci::SynchronousConnectionParameters parameters,
    ScoConnectionCallback callback) {
  if (initiator) {
    return sco_manager_->OpenConnection(parameters, std::move(callback));
  }
  return sco_manager_->AcceptConnection(parameters, std::move(callback));
}

void BrEdrConnection::AttachInspect(inspect::Node& parent, std::string name) {
  inspect_node_ = parent.CreateChild(name);
  inspect_properties_.peer_id =
      inspect_node_.CreateString(kInspectPeerIdPropertyName, peer_id_.ToString());
}

}  // namespace bt::gap
