// 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 "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/gap/low_energy_connection_manager.h"

#include <optional>
#include <vector>

#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/common/assert.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/gap/gap.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/gap/generic_access_client.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/gap/low_energy_connection.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/gap/pairing_delegate.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/gap/peer.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/gap/peer_cache.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/gatt/local_service_manager.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/hci-spec/constants.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/hci-spec/defaults.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/hci-spec/protocol.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/hci-spec/util.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/hci/local_address_delegate.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/l2cap/channel_manager.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/sm/error.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/sm/security_manager.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/sm/smp.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/sm/types.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/sm/util.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/transport/transport.h"
#include "src/connectivity/bluetooth/lib/cpp-string/string_printf.h"

#pragma clang diagnostic ignored "-Wswitch-enum"

using bt::sm::BondableMode;

namespace bt::gap {

namespace {

// If an auto-connect attempt fails with any of the following error codes, we
// will stop auto- connecting to the peer until the next successful connection.
// We have only observed this issue with the 0x3e
// "kConnectionFailedToBeEstablished" error in the field, but have included
// these other errors based on their descriptions in v5.2 Vol. 1 Part F
// Section 2.
bool ShouldStopAlwaysAutoConnecting(pw::bluetooth::emboss::StatusCode err) {
  switch (err) {
    case pw::bluetooth::emboss::StatusCode::CONNECTION_TIMEOUT:
    case pw::bluetooth::emboss::StatusCode::CONNECTION_REJECTED_SECURITY:
    case pw::bluetooth::emboss::StatusCode::CONNECTION_ACCEPT_TIMEOUT_EXCEEDED:
    case pw::bluetooth::emboss::StatusCode::CONNECTION_TERMINATED_BY_LOCAL_HOST:
    case pw::bluetooth::emboss::StatusCode::CONNECTION_FAILED_TO_BE_ESTABLISHED:
      return true;
    default:
      return false;
  }
}

// During the initial connection to a peripheral we use the initial high
// duty-cycle parameters to ensure that initiating procedures (bonding,
// encryption setup, service discovery) are completed quickly. Once these
// procedures are complete, we will change the connection interval to the
// peripheral's preferred connection parameters (see v5.0, Vol 3, Part C,
// Section 9.3.12).
static const hci_spec::LEPreferredConnectionParameters
    kInitialConnectionParameters(kLEInitialConnIntervalMin,
                                 kLEInitialConnIntervalMax,
                                 /*max_latency=*/0,
                                 hci_spec::defaults::kLESupervisionTimeout);

const char* kInspectRequestsNodeName = "pending_requests";
const char* kInspectRequestNodeNamePrefix = "pending_request_";
const char* kInspectConnectionsNodeName = "connections";
const char* kInspectConnectionNodePrefix = "connection_";
const char* kInspectOutboundConnectorNodeName = "outbound_connector";
const char* kInspectConnectionFailuresPropertyName =
    "recent_connection_failures";

const char* kInspectOutgoingSuccessCountNodeName =
    "outgoing_connection_success_count";
const char* kInspectOutgoingFailureCountNodeName =
    "outgoing_connection_failure_count";
const char* kInspectIncomingSuccessCountNodeName =
    "incoming_connection_success_count";
const char* kInspectIncomingFailureCountNodeName =
    "incoming_connection_failure_count";

const char* kInspectDisconnectExplicitDisconnectNodeName =
    "disconnect_explicit_disconnect_count";
const char* kInspectDisconnectLinkErrorNodeName = "disconnect_link_error_count";
const char* kInspectDisconnectZeroRefNodeName = "disconnect_zero_ref_count";
const char* kInspectDisconnectRemoteDisconnectionNodeName =
    "disconnect_remote_disconnection_count";

}  // namespace

LowEnergyConnectionManager::LowEnergyConnectionManager(
    hci::CommandChannel::WeakPtr cmd_channel,
    hci::LocalAddressDelegate* addr_delegate,
    hci::LowEnergyConnector* connector,
    PeerCache* peer_cache,
    l2cap::ChannelManager* l2cap,
    gatt::GATT::WeakPtr gatt,
    LowEnergyDiscoveryManager::WeakPtr discovery_manager,
    sm::SecurityManagerFactory sm_creator,
    const AdapterState& adapter_state,
    pw::async::Dispatcher& dispatcher)
    : dispatcher_(dispatcher),
      cmd_(std::move(cmd_channel)),
      security_mode_(LESecurityMode::Mode1),
      sm_factory_func_(std::move(sm_creator)),
      request_timeout_(kLECreateConnectionTimeout),
      peer_cache_(peer_cache),
      l2cap_(l2cap),
      gatt_(gatt),
      adapter_state_(adapter_state),
      discovery_manager_(discovery_manager),
      hci_connector_(connector),
      local_address_delegate_(addr_delegate),
      weak_self_(this) {
  BT_DEBUG_ASSERT(peer_cache_);
  BT_DEBUG_ASSERT(l2cap_);
  BT_DEBUG_ASSERT(gatt_.is_alive());
  BT_DEBUG_ASSERT(cmd_.is_alive());
  BT_DEBUG_ASSERT(hci_connector_);
  BT_DEBUG_ASSERT(local_address_delegate_);
}

LowEnergyConnectionManager::~LowEnergyConnectionManager() {
  bt_log(INFO, "gap-le", "LowEnergyConnectionManager shutting down");

  weak_self_.InvalidatePtrs();

  // Clear |pending_requests_| and notify failure.
  for (auto& iter : pending_requests_) {
    iter.second.NotifyCallbacks(fit::error(HostError::kFailed));
  }
  pending_requests_.clear();

  current_request_.reset();

  remote_connectors_.clear();

  // Clean up all connections.
  for (auto& iter : connections_) {
    CleanUpConnection(std::move(iter.second));
  }

  connections_.clear();
}

void LowEnergyConnectionManager::Connect(
    PeerId peer_id,
    ConnectionResultCallback callback,
    LowEnergyConnectionOptions connection_options) {
  Peer* peer = peer_cache_->FindById(peer_id);
  if (!peer) {
    bt_log(WARN, "gap-le", "peer not found (id: %s)", bt_str(peer_id));
    callback(fit::error(HostError::kNotFound));
    return;
  }

  if (peer->technology() == TechnologyType::kClassic) {
    bt_log(ERROR,
           "gap-le",
           "peer does not support LE: %s",
           peer->ToString().c_str());
    callback(fit::error(HostError::kNotFound));
    return;
  }

  if (!peer->connectable()) {
    bt_log(
        ERROR, "gap-le", "peer not connectable: %s", peer->ToString().c_str());
    callback(fit::error(HostError::kNotFound));
    return;
  }

  // If we are already waiting to connect to |peer_id| then we store
  // |callback| to be processed after the connection attempt completes (in
  // either success of failure).
  auto pending_iter = pending_requests_.find(peer_id);
  if (pending_iter != pending_requests_.end()) {
    if (!current_request_) {
      bt_log(WARN,
             "gap-le",
             "Connect called for peer with pending request while no "
             "current_request_ exists (peer: "
             "%s)",
             bt_str(peer_id));
    }
    // TODO(https://fxbug.dev/42144310): Merge connection_options with the
    // options of the pending request.
    pending_iter->second.AddCallback(std::move(callback));
    // TODO(https://fxbug.dev/42148775): Try to create this connection.
    return;
  }

  // Add callback to connecting request if |peer_id| matches.
  if (current_request_ && current_request_->request.peer_id() == peer_id) {
    // TODO(https://fxbug.dev/42144310): Merge connection_options with the
    // options of the current request.
    current_request_->request.AddCallback(std::move(callback));
    return;
  }

  auto conn_iter = connections_.find(peer_id);
  if (conn_iter != connections_.end()) {
    // TODO(https://fxbug.dev/42144310): Handle connection_options that conflict
    // with the existing connection.
    callback(fit::ok(conn_iter->second->AddRef()));
    return;
  }

  internal::LowEnergyConnectionRequest request(
      peer_id,
      std::move(callback),
      connection_options,
      peer->MutLe().RegisterInitializingConnection());
  request.AttachInspect(
      inspect_pending_requests_node_,
      inspect_pending_requests_node_.UniqueName(kInspectRequestNodeNamePrefix));
  pending_requests_.emplace(peer_id, std::move(request));

  TryCreateNextConnection();
}

bool LowEnergyConnectionManager::Disconnect(PeerId peer_id,
                                            LowEnergyDisconnectReason reason) {
  auto remote_connector_iter = remote_connectors_.find(peer_id);
  if (remote_connector_iter != remote_connectors_.end()) {
    // Result callback will clean up connector.
    remote_connector_iter->second.connector->Cancel();
  }

  auto request_iter = pending_requests_.find(peer_id);
  if (request_iter != pending_requests_.end()) {
    BT_ASSERT(current_request_->request.peer_id() != peer_id);
    request_iter->second.NotifyCallbacks(fit::error(HostError::kCanceled));
    pending_requests_.erase(request_iter);
  }

  if (current_request_ && current_request_->request.peer_id() == peer_id) {
    // Connector will call result callback to clean up connection.
    current_request_->connector->Cancel();
  }

  // Ignore Disconnect for peer that is not pending or connected:
  auto iter = connections_.find(peer_id);
  if (iter == connections_.end()) {
    bt_log(INFO,
           "gap-le",
           "Disconnect called for unconnected peer (peer: %s)",
           bt_str(peer_id));
    return true;
  }

  // Handle peer that is already connected:

  // Remove the connection state from the internal map right away.
  auto conn = std::move(iter->second);
  connections_.erase(iter);

  // Since this was an intentional disconnect, update the auto-connection
  // behavior appropriately.
  peer_cache_->SetAutoConnectBehaviorForIntentionalDisconnect(peer_id);

  bt_log(INFO,
         "gap-le",
         "disconnecting (peer: %s, link: %s)",
         bt_str(conn->peer_id()),
         bt_str(*conn->link()));

  if (reason == LowEnergyDisconnectReason::kApiRequest) {
    inspect_properties_.disconnect_explicit_disconnect_count_.Add(1);
  } else {
    inspect_properties_.disconnect_link_error_count_.Add(1);
  }

  CleanUpConnection(std::move(conn));
  return true;
}

void LowEnergyConnectionManager::Pair(PeerId peer_id,
                                      sm::SecurityLevel pairing_level,
                                      sm::BondableMode bondable_mode,
                                      sm::ResultFunction<> cb) {
  auto iter = connections_.find(peer_id);
  if (iter == connections_.end()) {
    bt_log(WARN,
           "gap-le",
           "cannot pair: peer not connected (peer: %s)",
           bt_str(peer_id));
    cb(bt::ToResult(bt::HostError::kNotFound));
    return;
  }
  bt_log(INFO,
         "gap-le",
         "pairing with security level: %d (peer: %s)",
         static_cast<int>(pairing_level),
         bt_str(peer_id));
  iter->second->UpgradeSecurity(pairing_level, bondable_mode, std::move(cb));
}

void LowEnergyConnectionManager::SetSecurityMode(LESecurityMode mode) {
  security_mode_ = mode;
  if (mode == LESecurityMode::SecureConnectionsOnly) {
    // `Disconnect`ing the peer must not be done while iterating through
    // `connections_` as it removes the connection from `connections_`, hence
    // the helper vector.
    std::vector<PeerId> insufficiently_secure_peers;
    for (auto& [peer_id, connection] : connections_) {
      if (connection->security().level() !=
              sm::SecurityLevel::kSecureAuthenticated &&
          connection->security().level() != sm::SecurityLevel::kNoSecurity) {
        insufficiently_secure_peers.push_back(peer_id);
      }
    }
    for (PeerId id : insufficiently_secure_peers) {
      Disconnect(id);
    }
  }
  for (auto& iter : connections_) {
    iter.second->set_security_mode(mode);
  }
}

void LowEnergyConnectionManager::AttachInspect(inspect::Node& parent,
                                               std::string name) {
  inspect_node_ = parent.CreateChild(name);
  inspect_properties_.recent_connection_failures.AttachInspect(
      inspect_node_, kInspectConnectionFailuresPropertyName);
  inspect_pending_requests_node_ =
      inspect_node_.CreateChild(kInspectRequestsNodeName);
  inspect_connections_node_ =
      inspect_node_.CreateChild(kInspectConnectionsNodeName);
  for (auto& request : pending_requests_) {
    request.second.AttachInspect(inspect_pending_requests_node_,
                                 inspect_pending_requests_node_.UniqueName(
                                     kInspectRequestNodeNamePrefix));
  }
  for (auto& conn : connections_) {
    conn.second->AttachInspect(
        inspect_connections_node_,
        inspect_connections_node_.UniqueName(kInspectConnectionNodePrefix));
  }
  if (current_request_) {
    current_request_->connector->AttachInspect(
        inspect_node_, kInspectOutboundConnectorNodeName);
  }

  inspect_properties_.outgoing_connection_success_count_.AttachInspect(
      inspect_node_, kInspectOutgoingSuccessCountNodeName);
  inspect_properties_.outgoing_connection_failure_count_.AttachInspect(
      inspect_node_, kInspectOutgoingFailureCountNodeName);
  inspect_properties_.incoming_connection_success_count_.AttachInspect(
      inspect_node_, kInspectIncomingSuccessCountNodeName);
  inspect_properties_.incoming_connection_failure_count_.AttachInspect(
      inspect_node_, kInspectIncomingFailureCountNodeName);

  inspect_properties_.disconnect_explicit_disconnect_count_.AttachInspect(
      inspect_node_, kInspectDisconnectExplicitDisconnectNodeName);
  inspect_properties_.disconnect_link_error_count_.AttachInspect(
      inspect_node_, kInspectDisconnectLinkErrorNodeName);
  inspect_properties_.disconnect_zero_ref_count_.AttachInspect(
      inspect_node_, kInspectDisconnectZeroRefNodeName);
  inspect_properties_.disconnect_remote_disconnection_count_.AttachInspect(
      inspect_node_, kInspectDisconnectRemoteDisconnectionNodeName);
}

void LowEnergyConnectionManager::RegisterRemoteInitiatedLink(
    std::unique_ptr<hci::LowEnergyConnection> link,
    sm::BondableMode bondable_mode,
    ConnectionResultCallback callback) {
  BT_ASSERT(link);

  Peer* peer = UpdatePeerWithLink(*link);
  auto peer_id = peer->identifier();

  bt_log(INFO,
         "gap-le",
         "new remote-initiated link (peer: %s, local addr: %s, link: %s)",
         bt_str(peer_id),
         bt_str(link->local_address()),
         bt_str(*link));

  // TODO(https://fxbug.dev/42143994): Use own address when storing the
  // connection. Currently this will refuse the connection and disconnect the
  // link if |peer| is already connected to us by a different local address.
  if (connections_.find(peer_id) != connections_.end()) {
    bt_log(INFO,
           "gap-le",
           "multiple links from peer; remote-initiated connection refused "
           "(peer: %s)",
           bt_str(peer_id));
    callback(fit::error(HostError::kFailed));
    return;
  }

  if (remote_connectors_.find(peer_id) != remote_connectors_.end()) {
    bt_log(INFO,
           "gap-le",
           "remote connector for peer already exists; connection refused "
           "(peer: %s)",
           bt_str(peer_id));
    callback(fit::error(HostError::kFailed));
    return;
  }

  LowEnergyConnectionOptions connection_options{.bondable_mode = bondable_mode};
  internal::LowEnergyConnectionRequest request(
      peer_id,
      std::move(callback),
      connection_options,
      peer->MutLe().RegisterInitializingConnection());

  std::unique_ptr<internal::LowEnergyConnector> connector =
      std::make_unique<internal::LowEnergyConnector>(peer_id,
                                                     connection_options,
                                                     cmd_,
                                                     peer_cache_,
                                                     weak_self_.GetWeakPtr(),
                                                     l2cap_,
                                                     gatt_,
                                                     adapter_state_,
                                                     dispatcher_);
  auto [conn_iter, _] = remote_connectors_.emplace(
      peer_id, RequestAndConnector{std::move(request), std::move(connector)});
  // Wait until the connector is in the map to start in case the result callback
  // is called synchronously.
  auto result_cb =
      std::bind(&LowEnergyConnectionManager::OnRemoteInitiatedConnectResult,
                this,
                peer_id,
                std::placeholders::_1);
  conn_iter->second.connector->StartInbound(std::move(link),
                                            std::move(result_cb));
}

void LowEnergyConnectionManager::SetPairingDelegate(
    const PairingDelegate::WeakPtr& delegate) {
  // TODO(https://fxbug.dev/42169848): Add a test case for this once bug is
  // resolved.
  pairing_delegate_ = delegate;

  // Tell existing connections to abort ongoing pairing procedures. The new
  // delegate will receive calls to PairingDelegate::CompletePairing, unless it
  // is null.
  for (auto& iter : connections_) {
    iter.second->ResetSecurityManager(delegate.is_alive()
                                          ? delegate->io_capability()
                                          : sm::IOCapability::kNoInputNoOutput);
  }
}

void LowEnergyConnectionManager::SetDisconnectCallbackForTesting(
    DisconnectCallback callback) {
  test_disconn_cb_ = std::move(callback);
}

void LowEnergyConnectionManager::ReleaseReference(
    LowEnergyConnectionHandle* handle) {
  BT_ASSERT(handle);

  auto iter = connections_.find(handle->peer_identifier());
  BT_ASSERT(iter != connections_.end());

  iter->second->DropRef(handle);
  if (iter->second->ref_count() != 0u)
    return;

  // Move the connection object before erasing the entry.
  auto conn = std::move(iter->second);
  connections_.erase(iter);

  bt_log(INFO,
         "gap-le",
         "all refs dropped on connection (link: %s, peer: %s)",
         bt_str(*conn->link()),
         bt_str(conn->peer_id()));
  inspect_properties_.disconnect_zero_ref_count_.Add(1);
  CleanUpConnection(std::move(conn));
}

void LowEnergyConnectionManager::TryCreateNextConnection() {
  if (current_request_.has_value()) {
    bt_log(DEBUG, "gap-le", "%s: request already in progress", __FUNCTION__);
    return;
  }

  if (pending_requests_.empty()) {
    bt_log(TRACE, "gap-le", "%s: no pending requests remaining", __FUNCTION__);
    return;
  }

  for (auto& iter : pending_requests_) {
    auto peer_id = iter.first;
    Peer* peer = peer_cache_->FindById(peer_id);
    if (peer) {
      auto request_pair = pending_requests_.extract(peer_id);
      internal::LowEnergyConnectionRequest request =
          std::move(request_pair.mapped());

      std::unique_ptr<internal::LowEnergyConnector> connector =
          std::make_unique<internal::LowEnergyConnector>(
              peer_id,
              request.connection_options(),
              cmd_,
              peer_cache_,
              weak_self_.GetWeakPtr(),
              l2cap_,
              gatt_,
              adapter_state_,
              dispatcher_);
      connector->AttachInspect(inspect_node_,
                               kInspectOutboundConnectorNodeName);

      current_request_ =
          RequestAndConnector{std::move(request), std::move(connector)};
      // Wait until the connector is in current_request_ to start in case the
      // result callback is called synchronously.
      current_request_->connector->StartOutbound(
          request_timeout_,
          hci_connector_,
          discovery_manager_,
          fit::bind_member<
              &LowEnergyConnectionManager::OnLocalInitiatedConnectResult>(
              this));
      return;
    }

    bt_log(WARN,
           "gap-le",
           "deferring connection attempt (peer: %s)",
           bt_str(peer_id));

    // TODO(https://fxbug.dev/42172291): For now the requests for this peer
    // won't complete until the next peer discovery. This will no longer be an
    // issue when we use background scanning.
  }
}

void LowEnergyConnectionManager::OnLocalInitiatedConnectResult(
    hci::Result<std::unique_ptr<internal::LowEnergyConnection>> result) {
  BT_ASSERT(current_request_.has_value());

  internal::LowEnergyConnectionRequest request =
      std::move(current_request_->request);
  current_request_.reset();

  if (result.is_error()) {
    inspect_properties_.outgoing_connection_failure_count_.Add(1);
    bt_log(INFO,
           "gap-le",
           "failed to connect to peer (peer: %s, status: %s)",
           bt_str(request.peer_id()),
           bt_str(result));
  } else {
    inspect_properties_.outgoing_connection_success_count_.Add(1);
    bt_log(INFO,
           "gap-le",
           "connection request successful (peer: %s)",
           bt_str(request.peer_id()));
  }

  ProcessConnectResult(std::move(result), std::move(request));
  TryCreateNextConnection();
}

void LowEnergyConnectionManager::OnRemoteInitiatedConnectResult(
    PeerId peer_id,
    hci::Result<std::unique_ptr<internal::LowEnergyConnection>> result) {
  auto remote_connector_node = remote_connectors_.extract(peer_id);
  BT_ASSERT(!remote_connector_node.empty());

  internal::LowEnergyConnectionRequest request =
      std::move(remote_connector_node.mapped().request);

  if (result.is_error()) {
    inspect_properties_.incoming_connection_failure_count_.Add(1);
    bt_log(INFO,
           "gap-le",
           "failed to complete remote initated connection with peer (peer: %s, "
           "status: %s)",
           bt_str(peer_id),
           bt_str(result));
  } else {
    inspect_properties_.incoming_connection_success_count_.Add(1);
    bt_log(INFO,
           "gap-le",
           "remote initiated connection successful (peer: %s)",
           bt_str(peer_id));
  }

  ProcessConnectResult(std::move(result), std::move(request));
}

void LowEnergyConnectionManager::ProcessConnectResult(
    hci::Result<std::unique_ptr<internal::LowEnergyConnection>> result,
    internal::LowEnergyConnectionRequest request) {
  PeerId peer_id = request.peer_id();
  if (result.is_error()) {
    const hci::Error err = result.error_value();
    Peer* const peer = peer_cache_->FindById(peer_id);
    // Peer may have been forgotten (causing this error).
    // A separate connection may have been established in the other direction
    // while this connection was connecting, in which case the peer state should
    // not be updated.
    if (peer && connections_.find(peer->identifier()) == connections_.end()) {
      if (request.connection_options().auto_connect &&
          err.is_protocol_error() &&
          ShouldStopAlwaysAutoConnecting(err.protocol_error())) {
        // We may see a peer's connectable advertisements, but fail to establish
        // a connection to the peer (e.g. due to asymmetrical radio TX power).
        // Unsetting the AutoConnect flag here prevents a loop of "see peer
        // device, attempt auto-connect, fail to establish connection".
        peer->MutLe().set_auto_connect_behavior(
            Peer::AutoConnectBehavior::kSkipUntilNextConnection);
      }
    }

    const HostError host_error =
        err.is_host_error() ? err.host_error() : HostError::kFailed;
    request.NotifyCallbacks(fit::error(host_error));

    inspect_properties_.recent_connection_failures.Add(1);

    return;
  }

  InitializeConnection(std::move(result).value(), std::move(request));
}

bool LowEnergyConnectionManager::InitializeConnection(
    std::unique_ptr<internal::LowEnergyConnection> connection,
    internal::LowEnergyConnectionRequest request) {
  BT_ASSERT(connection);

  auto peer_id = connection->peer_id();

  // TODO(https://fxbug.dev/42143994): For now reject having more than one link
  // with the same peer. This should change once this has more context on the
  // local destination for remote initiated connections.
  if (connections_.find(peer_id) != connections_.end()) {
    bt_log(INFO,
           "gap-le",
           "cannot initialize multiple links to same peer; connection refused "
           "(peer: %s)",
           bt_str(peer_id));
    // Notify request that duplicate connection could not be initialized.
    request.NotifyCallbacks(fit::error(HostError::kFailed));
    // Do not update peer state, as there is another active LE connection in
    // connections_ for this peer.
    return false;
  }

  Peer* peer = peer_cache_->FindById(peer_id);
  BT_ASSERT(peer);

  connection->AttachInspect(
      inspect_connections_node_,
      inspect_connections_node_.UniqueName(kInspectConnectionNodePrefix));
  connection->set_peer_disconnect_callback(
      std::bind(&LowEnergyConnectionManager::OnPeerDisconnect,
                this,
                connection->link(),
                std::placeholders::_1));
  connection->set_error_callback([this, peer_id]() {
    Disconnect(peer_id, LowEnergyDisconnectReason::kError);
  });

  auto [conn_iter, inserted] =
      connections_.try_emplace(peer_id, std::move(connection));
  BT_ASSERT(inserted);

  conn_iter->second->set_peer_conn_token(peer->MutLe().RegisterConnection());

  // Create first ref to ensure that connection is cleaned up on early returns
  // or if first request callback does not retain a ref.
  auto first_ref = conn_iter->second->AddRef();

  UpdatePeerWithLink(*conn_iter->second->link());

  bt_log(TRACE,
         "gap-le",
         "notifying connection request callbacks (peer: %s)",
         bt_str(peer_id));

  request.NotifyCallbacks(fit::ok(std::bind(
      &internal::LowEnergyConnection::AddRef, conn_iter->second.get())));

  return true;
}

void LowEnergyConnectionManager::CleanUpConnection(
    std::unique_ptr<internal::LowEnergyConnection> conn) {
  BT_ASSERT(conn);

  // Mark the peer peer as no longer connected.
  Peer* peer = peer_cache_->FindById(conn->peer_id());
  BT_ASSERT_MSG(peer,
                "A connection was active for an unknown peer! (id: %s)",
                bt_str(conn->peer_id()));
  conn.reset();
}

Peer* LowEnergyConnectionManager::UpdatePeerWithLink(
    const hci::LowEnergyConnection& link) {
  Peer* peer = peer_cache_->FindByAddress(link.peer_address());
  if (!peer) {
    peer = peer_cache_->NewPeer(link.peer_address(), /*connectable=*/true);
  }
  peer->MutLe().SetConnectionParameters(link.low_energy_parameters());
  peer_cache_->SetAutoConnectBehaviorForSuccessfulConnection(
      peer->identifier());

  return peer;
}

void LowEnergyConnectionManager::OnPeerDisconnect(
    const hci::Connection* connection,
    pw::bluetooth::emboss::StatusCode reason) {
  auto handle = connection->handle();
  if (test_disconn_cb_) {
    test_disconn_cb_(handle);
  }

  // See if we can find a connection with a matching handle by walking the
  // connections list.
  auto iter = FindConnection(handle);
  if (iter == connections_.end()) {
    bt_log(WARN,
           "gap-le",
           "disconnect from unknown connection handle: %#.4x",
           handle);
    return;
  }

  // Found the connection. Remove the entry from |connections_| before notifying
  // the "closed" handlers.
  auto conn = std::move(iter->second);
  connections_.erase(iter);

  bt_log(INFO,
         "gap-le",
         "peer disconnected (peer: %s, handle: %#.4x)",
         bt_str(conn->peer_id()),
         handle);

  inspect_properties_.disconnect_remote_disconnection_count_.Add(1);

  CleanUpConnection(std::move(conn));
}

LowEnergyConnectionManager::ConnectionMap::iterator
LowEnergyConnectionManager::FindConnection(hci_spec::ConnectionHandle handle) {
  auto iter = connections_.begin();
  for (; iter != connections_.end(); ++iter) {
    const auto& conn = *iter->second;
    if (conn.handle() == handle)
      break;
  }
  return iter;
}

}  // namespace bt::gap
