// Copyright 2018 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 "host_server.h"

#include <fuchsia/mem/cpp/fidl.h>
#include <lib/fit/result.h>
#include <lib/syslog/cpp/macros.h>
#include <zircon/assert.h>

#include "gatt_server_server.h"
#include "helpers.h"
#include "low_energy_central_server.h"
#include "low_energy_peripheral_server.h"
#include "profile_server.h"
#include "src/connectivity/bluetooth/core/bt-host/common/identifier.h"
#include "src/connectivity/bluetooth/core/bt-host/common/log.h"
#include "src/connectivity/bluetooth/core/bt-host/gap/adapter.h"
#include "src/connectivity/bluetooth/core/bt-host/gap/bonding_data.h"
#include "src/connectivity/bluetooth/core/bt-host/gap/bredr_connection_manager.h"
#include "src/connectivity/bluetooth/core/bt-host/gap/bredr_discovery_manager.h"
#include "src/connectivity/bluetooth/core/bt-host/gap/gap.h"
#include "src/connectivity/bluetooth/core/bt-host/gap/low_energy_address_manager.h"
#include "src/connectivity/bluetooth/core/bt-host/gap/low_energy_discovery_manager.h"
#include "src/connectivity/bluetooth/core/bt-host/sm/types.h"
#include "src/connectivity/bluetooth/core/bt-host/sm/util.h"
#include "src/lib/fxl/strings/join_strings.h"
#include "src/lib/fxl/strings/string_number_conversions.h"
#include "src/lib/fxl/strings/string_printf.h"

namespace bthost {

namespace fbt = fuchsia::bluetooth;
namespace fsys = fuchsia::bluetooth::sys;

using bt::PeerId;
using bt::gap::LeSecurityModeToString;
using bt::sm::IOCapability;
using fidl_helpers::HostErrorToFidl;
using fidl_helpers::LeSecurityModeFromFidl;
using fidl_helpers::NewFidlError;
using fidl_helpers::PeerIdFromString;
using fidl_helpers::SecurityLevelFromFidl;
using fidl_helpers::StatusToFidl;

std::pair<PeerTracker::Updated, PeerTracker::Removed> PeerTracker::ToFidl(
    const bt::gap::PeerCache* peer_cache) {
  PeerTracker::Updated updated_fidl;
  for (auto& id : updated_) {
    auto* peer = peer_cache->FindById(id);

    // All ids in |updated_| are assumed to be valid as they would otherwise be in |removed_|.
    ZX_ASSERT(peer);

    updated_fidl.push_back(fidl_helpers::PeerToFidl(*peer));
  }

  PeerTracker::Removed removed_fidl;
  for (auto& id : removed_) {
    removed_fidl.push_back(fbt::PeerId{id.value()});
  }

  return std::make_pair(std::move(updated_fidl), std::move(removed_fidl));
}

void PeerTracker::Update(bt::PeerId id) {
  updated_.insert(id);
  removed_.erase(id);
}

void PeerTracker::Remove(bt::PeerId id) {
  updated_.erase(id);
  removed_.insert(id);
}

WatchPeersGetter::WatchPeersGetter(bt::gap::PeerCache* peer_cache) : peer_cache_(peer_cache) {
  ZX_DEBUG_ASSERT(peer_cache_);
}

void WatchPeersGetter::Notify(std::queue<Callback> callbacks, PeerTracker peers) {
  auto [updated, removed] = peers.ToFidl(peer_cache_);
  while (!callbacks.empty()) {
    auto f = std::move(callbacks.front());
    callbacks.pop();
    f(fidl::Clone(updated), fidl::Clone(removed));
  }
}

HostServer::HostServer(zx::channel channel, fxl::WeakPtr<bt::gap::Adapter> adapter,
                       fxl::WeakPtr<bt::gatt::GATT> gatt)
    : AdapterServerBase(adapter, this, std::move(channel)),
      pairing_delegate_(nullptr),
      gatt_(gatt),
      requesting_discovery_(false),
      requesting_background_scan_(false),
      requesting_discoverable_(false),
      io_capability_(IOCapability::kNoInputNoOutput),
      watch_peers_getter_(adapter->peer_cache()),
      weak_ptr_factory_(this) {
  ZX_ASSERT(gatt_);

  auto self = weak_ptr_factory_.GetWeakPtr();
  adapter->peer_cache()->set_peer_updated_callback([self](const auto& peer) {
    if (self) {
      self->OnPeerUpdated(peer);
    }
  });
  adapter->peer_cache()->set_peer_removed_callback([self](const auto& identifier) {
    if (self) {
      self->OnPeerRemoved(identifier);
    }
  });
  adapter->peer_cache()->set_peer_bonded_callback([self](const auto& peer) {
    if (self) {
      self->OnPeerBonded(peer);
    }
  });
  adapter->set_auto_connect_callback([self](auto conn_ref) {
    if (self) {
      self->RegisterLowEnergyConnection(std::move(conn_ref), true);
    }
  });

  // Initialize the HostInfo getter with the initial state.
  NotifyInfoChange();

  // Initialize the peer watcher with all known connectable peers that are in the cache.
  adapter->peer_cache()->ForEach([this](const bt::gap::Peer& peer) { OnPeerUpdated(peer); });
}

HostServer::~HostServer() { Close(); }

void HostServer::WatchState(WatchStateCallback callback) {
  info_getter_.Watch(std::move(callback));
}

void HostServer::SetLocalData(fsys::HostData host_data) {
  if (host_data.has_irk()) {
    bt_log(DEBUG, "fidl", "assign IRK");
    if (adapter()->le()) {
      adapter()->le()->set_irk(host_data.irk().value);
    }
  }
}

void HostServer::WatchPeers(WatchPeersCallback callback) {
  watch_peers_getter_.Watch(std::move(callback));
}

void HostServer::SetLocalName(::std::string local_name, SetLocalNameCallback callback) {
  ZX_DEBUG_ASSERT(!local_name.empty());
  adapter()->SetLocalName(std::move(local_name), [self = weak_ptr_factory_.GetWeakPtr(),
                                                  callback = std::move(callback)](auto status) {
    // Send adapter state update on success and if the connection is still open.
    if (status && self) {
      self->NotifyInfoChange();
    }
    callback(StatusToFidl(status));
  });
}

// TODO(fxbug.dev/35008): Add a unit test for this method.
void HostServer::SetDeviceClass(fbt::DeviceClass device_class, SetDeviceClassCallback callback) {
  // Device Class values must only contain data in the lower 3 bytes.
  if (device_class.value >= 1 << 24) {
    callback(fit::error(fsys::Error::INVALID_ARGUMENTS));
    return;
  }
  bt::DeviceClass dev_class(device_class.value);
  adapter()->SetDeviceClass(
      dev_class, [callback = std::move(callback)](auto status) { callback(StatusToFidl(status)); });
}

void HostServer::StartLEDiscovery(StartDiscoveryCallback callback) {
  if (!adapter()->le()) {
    callback(fit::error(fsys::Error::FAILED));
    return;
  }
  adapter()->le()->StartDiscovery(
      /*active=*/true,
      [self = weak_ptr_factory_.GetWeakPtr(), callback = std::move(callback)](auto session) {
        // End the new session if this AdapterServer got destroyed in the
        // meantime (e.g. because the client disconnected).
        if (!self) {
          callback(fit::error(fsys::Error::FAILED));
          return;
        }

        if (!self->requesting_discovery_) {
          callback(fit::error(fsys::Error::CANCELED));
          return;
        }

        if (!session) {
          bt_log(ERROR, "fidl", "failed to start active LE discovery session");
          callback(fit::error(fsys::Error::FAILED));
          self->bredr_discovery_session_ = nullptr;
          self->requesting_discovery_ = false;
          return;
        }

        // Set up a general-discovery filter for connectable devices.
        // NOTE(armansito): This currently has no effect since peer updates
        // are driven by PeerCache events. |session|'s "result callback" is unused.
        session->filter()->set_connectable(true);
        session->filter()->SetGeneralDiscoveryFlags();

        self->le_discovery_session_ = std::move(session);
        self->requesting_discovery_ = false;

        // Send the adapter state update.
        self->NotifyInfoChange();

        callback(fit::ok());
      });
}

void HostServer::StartDiscovery(StartDiscoveryCallback callback) {
  bt_log(DEBUG, "fidl", "%s", __FUNCTION__);
  ZX_DEBUG_ASSERT(adapter());

  if (le_discovery_session_ || requesting_discovery_) {
    bt_log(DEBUG, "fidl", "discovery already in progress");
    callback(fit::error(fsys::Error::IN_PROGRESS));
    return;
  }

  requesting_discovery_ = true;
  if (!adapter()->bredr()) {
    StartLEDiscovery(std::move(callback));
    return;
  }
  // TODO(jamuraa): start these in parallel instead of sequence
  adapter()->bredr()->RequestDiscovery(
      [self = weak_ptr_factory_.GetWeakPtr(), callback = std::move(callback), func = __FUNCTION__](
          bt::hci::Status status, auto session) mutable {
        if (!self) {
          callback(fit::error(fsys::Error::FAILED));
          return;
        }

        if (!self->requesting_discovery_) {
          callback(fit::error(fsys::Error::CANCELED));
          return;
        }

        if (!status || !session) {
          bt_log(ERROR, "fidl", "%s: failed to start BR/EDR discovery session", func);

          fit::result<void, fsys::Error> result;
          if (!status) {
            result = StatusToFidl(status);
          } else {
            result = fit::error(fsys::Error::FAILED);
          }
          self->requesting_discovery_ = false;
          callback(std::move(result));
          return;
        }

        self->bredr_discovery_session_ = std::move(session);
        self->StartLEDiscovery(std::move(callback));
      });
}

void HostServer::StopDiscovery() {
  bt_log(DEBUG, "fidl", "%s", __FUNCTION__);

  bool discovering = le_discovery_session_ || bredr_discovery_session_;
  bredr_discovery_session_ = nullptr;
  le_discovery_session_ = nullptr;

  if (discovering) {
    NotifyInfoChange();
  } else {
    bt_log(DEBUG, "fidl", "no active discovery session");
  }
}

void HostServer::SetConnectable(bool connectable, SetConnectableCallback callback) {
  bt_log(INFO, "fidl", "%s: %s", __FUNCTION__, connectable ? "true" : "false");

  auto classic = adapter()->bredr();
  if (!classic) {
    callback(fit::error(fsys::Error::NOT_SUPPORTED));
    return;
  }
  classic->SetConnectable(connectable, [callback = std::move(callback)](const auto& status) {
    callback(StatusToFidl(status));
  });
}

void HostServer::RestoreBonds(::std::vector<fsys::BondingData> bonds,
                              RestoreBondsCallback callback) {
  bt_log(INFO, "fidl", "%s", __FUNCTION__);

  std::vector<fsys::BondingData> errors;

  if (bonds.empty()) {
    // Nothing to do. Reply with an empty list.
    callback(std::move(errors));
    return;
  }

  for (auto& bond : bonds) {
    if (!bond.has_identifier() || !bond.has_address() ||
        !(bond.has_le_bond() || bond.has_bredr_bond())) {
      bt_log(ERROR, "fidl", "%s: BondingData mandatory fields missing!", __FUNCTION__);
      errors.push_back(std::move(bond));
      continue;
    }

    auto address = fidl_helpers::AddressFromFidlBondingData(bond);
    if (!address) {
      bt_log(ERROR, "fidl", "%s: BondingData address missing!", __FUNCTION__);
      errors.push_back(std::move(bond));
      continue;
    }

    bt::gap::BondingData bd;
    bd.identifier = bt::PeerId{bond.identifier().value};
    bd.address = *address;
    if (bond.has_name()) {
      bd.name = {bond.name()};
    }

    if (bond.has_le_bond()) {
      bd.le_pairing_data = fidl_helpers::LePairingDataFromFidl(bond.le_bond());
    }
    if (bond.has_bredr_bond()) {
      bd.bredr_link_key = fidl_helpers::BredrKeyFromFidl(bond.bredr_bond());
      bd.bredr_services = fidl_helpers::BredrServicesFromFidl(bond.bredr_bond());
    }

    // TODO(fxbug.dev/59645): Convert bond.bredr.services to BondingData::bredr_services
    if (!adapter()->AddBondedPeer(bd)) {
      bt_log(ERROR, "fidl", "%s: failed to restore bonding data entry", __FUNCTION__);
      errors.push_back(std::move(bond));
    }
  }

  callback(std::move(errors));
}

void HostServer::OnPeerBonded(const bt::gap::Peer& peer) {
  bt_log(DEBUG, "fidl", "%s", __FUNCTION__);
  binding()->events().OnNewBondingData(fidl_helpers::PeerToFidlBondingData(*adapter(), peer));
}

void HostServer::RegisterLowEnergyConnection(
    std::unique_ptr<bt::gap::LowEnergyConnectionHandle> conn_ref, bool auto_connect) {
  ZX_DEBUG_ASSERT(conn_ref);

  bt::PeerId id = conn_ref->peer_identifier();
  auto iter = le_connections_.find(id);
  if (iter != le_connections_.end()) {
    bt_log(WARN, "fidl", "%s: peer already connected; connection reference dropped (peer: %s)",
           __FUNCTION__, bt_str(id));
    return;
  }

  bt_log(DEBUG, "fidl", "LE peer connected (%s): %s ", (auto_connect ? "auto" : "direct"),
         bt_str(id));
  conn_ref->set_closed_callback([self = weak_ptr_factory_.GetWeakPtr(), id] {
    if (self)
      self->le_connections_.erase(id);
  });
  le_connections_[id] = std::move(conn_ref);
}

void HostServer::SetDiscoverable(bool discoverable, SetDiscoverableCallback callback) {
  bt_log(INFO, "fidl", "%s(%s)", __FUNCTION__, discoverable ? "true" : "false");
  // TODO(fxbug.dev/955): advertise LE here
  if (!discoverable) {
    bredr_discoverable_session_ = nullptr;
    NotifyInfoChange();
    callback(fit::ok());
    return;
  }
  if (discoverable && requesting_discoverable_) {
    bt_log(DEBUG, "fidl", "%s already in progress", __FUNCTION__);
    callback(fit::error(fsys::Error::IN_PROGRESS));
    return;
  }
  requesting_discoverable_ = true;
  if (!adapter()->bredr()) {
    callback(fit::error(fsys::Error::FAILED));
    return;
  }
  adapter()->bredr()->RequestDiscoverable(
      [self = weak_ptr_factory_.GetWeakPtr(), callback = std::move(callback), func = __FUNCTION__](
          bt::hci::Status status, auto session) {
        if (!self) {
          callback(fit::error(fsys::Error::FAILED));
          return;
        }

        if (!self->requesting_discoverable_) {
          callback(fit::error(fsys::Error::CANCELED));
          return;
        }

        if (!status || !session) {
          bt_log(ERROR, "fidl", "%s: failed (status: %s)", func, bt_str(status));
          fit::result<void, fsys::Error> result;
          if (!status) {
            result = StatusToFidl(status);
          } else {
            result = fit::error(fsys::Error::FAILED);
          }
          self->requesting_discoverable_ = false;
          callback(std::move(result));
          return;
        }

        self->bredr_discoverable_session_ = std::move(session);
        self->requesting_discoverable_ = false;
        self->NotifyInfoChange();
        callback(fit::ok());
      });
}

void HostServer::EnableBackgroundScan(bool enabled) {
  bt_log(INFO, "fidl", "%s background scan", (enabled ? "enable" : "disable"));
  if (!adapter()->le()) {
    bt_log(ERROR, "fidl", "%s: adapter does not support LE", __FUNCTION__);
    return;
  }

  if (!enabled) {
    requesting_background_scan_ = false;
    le_background_scan_ = nullptr;
    return;
  }

  // If a scan is already starting or is in progress, there is nothing to do to enable the scan.
  if (requesting_background_scan_ || le_background_scan_) {
    return;
  }

  requesting_background_scan_ = true;
  adapter()->le()->StartDiscovery(
      /*active=*/false, [self = weak_ptr_factory_.GetWeakPtr()](auto session) {
        if (!self) {
          return;
        }

        // Background scan may have been disabled while discovery was starting.
        if (!self->requesting_background_scan_) {
          return;
        }

        if (!session) {
          bt_log(ERROR, "fidl", "failed to start LE background scan");
          self->le_background_scan_ = nullptr;
          self->requesting_background_scan_ = false;
          return;
        }

        self->le_background_scan_ = std::move(session);
        self->requesting_background_scan_ = false;
      });
}

void HostServer::EnablePrivacy(bool enabled) {
  bt_log(INFO, "fidl", "%s: %s LE privacy", __FUNCTION__, (enabled ? "enable" : "disable"));
  if (adapter()->le()) {
    adapter()->le()->EnablePrivacy(enabled);
  }
}

void HostServer::SetLeSecurityMode(fsys::LeSecurityMode mode) {
  bt::gap::LeSecurityMode gap_mode = LeSecurityModeFromFidl(mode);
  bt_log(INFO, "fidl", "%s: %s", __FUNCTION__, LeSecurityModeToString(gap_mode));
  if (adapter()->le()) {
    adapter()->le()->SetSecurityMode(gap_mode);
  }
}

void HostServer::SetPairingDelegate(fsys::InputCapability input, fsys::OutputCapability output,
                                    ::fidl::InterfaceHandle<fsys::PairingDelegate> delegate) {
  bool cleared = !delegate;
  pairing_delegate_.Bind(std::move(delegate));

  if (cleared) {
    bt_log(INFO, "fidl", "%s: PairingDelegate cleared", __FUNCTION__);
    ResetPairingDelegate();
    return;
  }

  io_capability_ = fidl_helpers::IoCapabilityFromFidl(input, output);
  bt_log(INFO, "fidl", "%s: PairingDelegate assigned (I/O capability: %s)", __FUNCTION__,
         bt::sm::util::IOCapabilityToString(io_capability_).c_str());

  auto self = weak_ptr_factory_.GetWeakPtr();
  adapter()->SetPairingDelegate(self);
  pairing_delegate_.set_error_handler([self, func = __FUNCTION__](zx_status_t status) {
    bt_log(INFO, "fidl", "%s error handler: PairingDelegate disconnected", func);
    if (self) {
      self->ResetPairingDelegate();
    }
  });
}

// Attempt to connect to peer identified by |peer_id|. The peer must be
// in our peer cache. We will attempt to connect technologies (LowEnergy,
// Classic or Dual-Mode) as the peer claims to support when discovered
void HostServer::Connect(fbt::PeerId peer_id, ConnectCallback callback) {
  bt::PeerId id{peer_id.value};
  bt_log(INFO, "fidl", "%s: (peer: %s)", __FUNCTION__, bt_str(id));

  auto peer = adapter()->peer_cache()->FindById(id);
  if (!peer) {
    // We don't support connecting to peers that are not in our cache
    bt_log(WARN, "fidl", "%s: peer not found in peer cache (peer: %s)", __FUNCTION__, bt_str(id));
    callback(fit::error(fsys::Error::PEER_NOT_FOUND));
    return;
  }

  // TODO(fxbug.dev/1242): Dual-mode currently not supported; if the peer supports
  // BR/EDR we prefer BR/EDR. If a dual-mode peer, we should attempt to connect
  // both protocols.
  if (peer->bredr()) {
    ConnectBrEdr(id, std::move(callback));
    return;
  }

  ConnectLowEnergy(id, std::move(callback));
}

// Attempt to disconnect the peer identified by |peer_id| from all transports.
// If the peer is already not connected, return success. If the peer is
// disconnected succesfully, return success.
void HostServer::Disconnect(fbt::PeerId peer_id, DisconnectCallback callback) {
  bt::PeerId id{peer_id.value};
  bt_log(INFO, "fidl", "%s: (peer: %s)", __FUNCTION__, bt_str(id));

  bool le_disc = adapter()->le() ? adapter()->le()->Disconnect(id) : true;
  bool bredr_disc = adapter()->bredr()
                        ? adapter()->bredr()->Disconnect(id, bt::gap::DisconnectReason::kApiRequest)
                        : true;
  if (le_disc && bredr_disc) {
    callback(fit::ok());
  } else {
    bt_log(WARN, "fidl", "%s: failed (peer: %s)", __FUNCTION__, bt_str(id));
    callback(fit::error(fsys::Error::FAILED));
  }
}

void HostServer::ConnectLowEnergy(PeerId peer_id, ConnectCallback callback) {
  auto self = weak_ptr_factory_.GetWeakPtr();
  auto on_complete = [self, callback = std::move(callback), peer_id,
                      func = __FUNCTION__](auto result) {
    if (result.is_error()) {
      bt_log(INFO, "fidl", "%s: failed to connect LE transport to peer (peer: %s)", func,
             bt_str(peer_id));
      callback(fit::error(HostErrorToFidl(result.error())));
      return;
    }

    // We must be connected and to the right peer
    auto connection = result.take_value();
    ZX_ASSERT(connection);
    ZX_ASSERT(peer_id == connection->peer_identifier());

    callback(fit::ok());

    if (self)
      self->RegisterLowEnergyConnection(std::move(connection), false);
  };

  adapter()->le()->Connect(peer_id, std::move(on_complete), bt::gap::LowEnergyConnectionOptions());
}

// Initiate an outgoing Br/Edr connection, unless already connected
// Br/Edr connections are host-wide, and stored in BrEdrConnectionManager
void HostServer::ConnectBrEdr(PeerId peer_id, ConnectCallback callback) {
  auto on_complete = [callback = std::move(callback), peer_id, func = __FUNCTION__](
                         auto status, auto connection) {
    if (!status) {
      ZX_ASSERT(!connection);
      bt_log(INFO, "fidl", "%s: failed to connect BR/EDR transport to peer (peer: %s)", func,
             bt_str(peer_id));
      callback(fit::error(HostErrorToFidl(status.error())));
      return;
    }

    // We must be connected and to the right peer
    ZX_ASSERT(connection);
    ZX_ASSERT(peer_id == connection->peer_id());

    callback(fit::ok());
  };

  if (!adapter()->bredr()->Connect(peer_id, std::move(on_complete))) {
    bt_log(INFO, "fidl", "%s: failed to initiate BR/EDR transport connection to peer (peer: %s)",
           __FUNCTION__, bt_str(peer_id));
    callback(fit::error(fsys::Error::FAILED));
  }
}

void HostServer::Forget(fbt::PeerId peer_id, ForgetCallback callback) {
  bt::PeerId id{peer_id.value};
  auto peer = adapter()->peer_cache()->FindById(id);
  if (!peer) {
    bt_log(DEBUG, "fidl", "peer %s to forget wasn't found", bt_str(id));
    callback(fit::ok());
    return;
  }

  const bool le_disconnected = adapter()->le() ? adapter()->le()->Disconnect(id) : true;
  const bool bredr_disconnected =
      adapter()->bredr()
          ? adapter()->bredr()->Disconnect(id, bt::gap::DisconnectReason::kApiRequest)
          : true;
  const bool peer_removed = adapter()->peer_cache()->RemoveDisconnectedPeer(id);

  if (!le_disconnected || !bredr_disconnected) {
    const auto message =
        fxl::StringPrintf("link(s) failed to close:%s%s", le_disconnected ? "" : " LE",
                          bredr_disconnected ? "" : " BR/EDR");
    callback(fit::error(fsys::Error::FAILED));
  } else {
    ZX_ASSERT(peer_removed);
    callback(fit::ok());
  }
}

void HostServer::Pair(fbt::PeerId id, fsys::PairingOptions options, PairCallback callback) {
  auto peer_id = bt::PeerId(id.value);
  auto peer = adapter()->peer_cache()->FindById(peer_id);
  if (!peer) {
    bt_log(WARN, "fidl", "%s: unknown peer %s", __FUNCTION__, bt_str(peer_id));
    // We don't support pairing to peers that are not in our cache
    callback(fit::error(fsys::Error::PEER_NOT_FOUND));
    return;
  }
  // If options specifies a transport preference for LE or BR/EDR, we use that. Otherwise, we use
  // whatever transport exists, defaulting to LE for dual-mode connections.
  bool pair_bredr = !peer->le();
  if (options.has_transport() && options.transport() != fsys::TechnologyType::DUAL_MODE) {
    pair_bredr = (options.transport() == fsys::TechnologyType::CLASSIC);
  }
  if (pair_bredr) {
    PairBrEdr(peer_id, std::move(callback));
    return;
  }
  PairLowEnergy(peer_id, std::move(options), std::move(callback));
}

void HostServer::PairLowEnergy(PeerId peer_id, fsys::PairingOptions options,
                               PairCallback callback) {
  std::optional<bt::sm::SecurityLevel> security_level;
  if (options.has_le_security_level()) {
    security_level = SecurityLevelFromFidl(options.le_security_level());
    if (!security_level.has_value()) {
      bt_log(WARN, "fidl", "%s: pairing options missing LE security level (peer: %s)", __FUNCTION__,
             bt_str(peer_id));
      callback(fit::error(fsys::Error::INVALID_ARGUMENTS));
      return;
    }
  } else {
    security_level = bt::sm::SecurityLevel::kAuthenticated;
  }
  bt::sm::BondableMode bondable_mode = bt::sm::BondableMode::Bondable;
  if (options.has_bondable_mode() && options.bondable_mode() == fsys::BondableMode::NON_BONDABLE) {
    bondable_mode = bt::sm::BondableMode::NonBondable;
  }
  auto on_complete = [peer_id, callback = std::move(callback),
                      func = __FUNCTION__](bt::sm::Status status) {
    if (!status) {
      bt_log(WARN, "fidl", "%s: failed to pair (peer: %s)", func, bt_str(peer_id));
      callback(fit::error(HostErrorToFidl(status.error())));
    } else {
      callback(fit::ok());
    }
  };
  ZX_ASSERT(adapter()->le());
  adapter()->le()->Pair(peer_id, *security_level, bondable_mode, std::move(on_complete));
}

void HostServer::PairBrEdr(PeerId peer_id, PairCallback callback) {
  auto on_complete = [peer_id, callback = std::move(callback),
                      func = __FUNCTION__](bt::hci::Status status) {
    if (!status) {
      bt_log(WARN, "fidl", "%s: failed to pair (peer: %s)", func, bt_str(peer_id));
      callback(fit::error(HostErrorToFidl(status.error())));
    } else {
      callback(fit::ok());
    }
  };
  // TODO(fxbug.dev/57991): Add security parameter to Pair and use that here instead of hardcoding
  // default.
  bt::gap::BrEdrSecurityRequirements security{.authentication = false, .secure_connections = false};
  ZX_ASSERT(adapter()->bredr());
  adapter()->bredr()->Pair(peer_id, security, std::move(on_complete));
}

void HostServer::RequestLowEnergyCentral(
    fidl::InterfaceRequest<fuchsia::bluetooth::le::Central> request) {
  BindServer<LowEnergyCentralServer>(std::move(request), gatt_);
}

void HostServer::RequestLowEnergyPeripheral(
    fidl::InterfaceRequest<fuchsia::bluetooth::le::Peripheral> request) {
  BindServer<LowEnergyPeripheralServer>(std::move(request));
}

void HostServer::RequestGattServer(
    fidl::InterfaceRequest<fuchsia::bluetooth::gatt::Server> request) {
  auto self = weak_ptr_factory_.GetWeakPtr();
  auto server = std::make_unique<GattServerServer>(gatt_->AsWeakPtr(), std::move(request));
  server->set_error_handler([self, server = server.get()](zx_status_t status) {
    if (self) {
      bt_log(DEBUG, "bt-host", "GATT server disconnected");
      self->servers_.erase(server);
    }
  });
  servers_[server.get()] = std::move(server);
}

void HostServer::RequestProfile(
    fidl::InterfaceRequest<fuchsia::bluetooth::bredr::Profile> request) {
  BindServer<ProfileServer>(std::move(request));
}

void HostServer::Close() {
  bt_log(INFO, "fidl", "closing FIDL handles");

  // Invalidate all weak pointers. This will guarantee that all pending tasks
  // that reference this HostServer will return early if they run in the future.
  weak_ptr_factory_.InvalidateWeakPtrs();

  // Destroy all FIDL bindings.
  servers_.clear();

  // Cancel pending requests.
  requesting_discovery_ = false;
  requesting_discoverable_ = false;
  requesting_background_scan_ = false;

  le_discovery_session_ = nullptr;
  le_background_scan_ = nullptr;
  bredr_discovery_session_ = nullptr;
  bredr_discoverable_session_ = nullptr;

  // Drop all connections that are attached to this HostServer.
  le_connections_.clear();

  if (adapter()->le()) {
    // Stop background scan if enabled.
    adapter()->le()->EnablePrivacy(false);
    adapter()->le()->set_irk(std::nullopt);
  }

  // Disallow future pairing.
  pairing_delegate_ = nullptr;
  ResetPairingDelegate();

  // Send adapter state change.
  if (binding()->is_bound()) {
    NotifyInfoChange();
  }
}

bt::sm::IOCapability HostServer::io_capability() const {
  bt_log(DEBUG, "fidl", "I/O capability: %s",
         bt::sm::util::IOCapabilityToString(io_capability_).c_str());
  return io_capability_;
}

void HostServer::CompletePairing(PeerId id, bt::sm::Status status) {
  bt_log(DEBUG, "fidl", "pairing complete for peer: %s, status: %s", bt_str(id), bt_str(status));
  ZX_DEBUG_ASSERT(pairing_delegate_);
  pairing_delegate_->OnPairingComplete(fbt::PeerId{id.value()}, status.is_success());
}

void HostServer::ConfirmPairing(PeerId id, ConfirmCallback confirm) {
  bt_log(DEBUG, "fidl", "pairing confirmation request for peer: %s", bt_str(id));
  DisplayPairingRequest(id, std::nullopt, fsys::PairingMethod::CONSENT, std::move(confirm));
}

void HostServer::DisplayPasskey(PeerId id, uint32_t passkey, DisplayMethod method,
                                ConfirmCallback confirm) {
  auto fidl_method = fsys::PairingMethod::PASSKEY_DISPLAY;
  if (method == DisplayMethod::kComparison) {
    bt_log(DEBUG, "fidl", "compare passkey %06u on peer: %s", passkey, bt_str(id));
    fidl_method = fsys::PairingMethod::PASSKEY_COMPARISON;
  } else {
    bt_log(DEBUG, "fidl", "enter passkey %06u on peer: %s", passkey, bt_str(id));
  }
  DisplayPairingRequest(id, passkey, fidl_method, std::move(confirm));
}

void HostServer::RequestPasskey(PeerId id, PasskeyResponseCallback respond) {
  bt_log(DEBUG, "fidl", "passkey request for peer: %s", bt_str(id));
  auto found_peer = adapter()->peer_cache()->FindById(id);
  ZX_ASSERT(found_peer);
  auto peer = fidl_helpers::PeerToFidl(*found_peer);

  ZX_ASSERT(pairing_delegate_);
  pairing_delegate_->OnPairingRequest(
      std::move(peer), fsys::PairingMethod::PASSKEY_ENTRY, 0u,
      [respond = std::move(respond), id, func = __FUNCTION__](const bool accept,
                                                              uint32_t entered_passkey) mutable {
        if (!respond) {
          bt_log(
              WARN, "fidl",
              "%s: The PairingDelegate invoked the Pairing Request callback more than once, which "
              "should not happen (peer: %s)",
              func, bt_str(id));
          return;
        }
        bt_log(INFO, "fidl",
               "%s: got PairingDelegate response: %s with passkey code \"%u\" (peer: %s)", func,
               accept ? "accept" : "reject", entered_passkey, bt_str(id));
        if (!accept) {
          respond(-1);
        } else {
          respond(entered_passkey);
        }
      });
}

void HostServer::DisplayPairingRequest(bt::PeerId id, std::optional<uint32_t> passkey,
                                       fsys::PairingMethod method, ConfirmCallback confirm) {
  auto found_peer = adapter()->peer_cache()->FindById(id);
  ZX_ASSERT(found_peer);
  auto peer = fidl_helpers::PeerToFidl(*found_peer);

  ZX_ASSERT(pairing_delegate_);
  uint32_t displayed_passkey = passkey ? *passkey : 0u;
  pairing_delegate_->OnPairingRequest(
      std::move(peer), method, displayed_passkey,
      [confirm = std::move(confirm), id, func = __FUNCTION__](const bool accept,
                                                              uint32_t entered_passkey) mutable {
        if (!confirm) {
          bt_log(
              WARN, "fidl",
              "%s: The PairingDelegate invoked the Pairing Request callback more than once, which "
              "should not happen (peer: %s)",
              func, bt_str(id));
          return;
        }
        bt_log(INFO, "fidl", "%s: got PairingDelegate response: %s, \"%u\" (peer: %s)", func,
               accept ? "accept" : "reject", entered_passkey, bt_str(id));
        confirm(accept);
      });
}

void HostServer::OnConnectionError(Server* server) {
  ZX_DEBUG_ASSERT(server);
  servers_.erase(server);
}

void HostServer::OnPeerUpdated(const bt::gap::Peer& peer) {
  if (!peer.connectable()) {
    return;
  }

  watch_peers_getter_.Transform([id = peer.identifier()](auto tracker) {
    tracker.Update(id);
    return tracker;
  });
}

void HostServer::OnPeerRemoved(bt::PeerId id) {
  // TODO(armansito): Notify only if the peer is connectable for symmetry with
  // OnPeerUpdated?
  watch_peers_getter_.Transform([id](auto tracker) {
    tracker.Remove(id);
    return tracker;
  });
}

void HostServer::ResetPairingDelegate() {
  io_capability_ = IOCapability::kNoInputNoOutput;
  adapter()->SetPairingDelegate(fxl::WeakPtr<HostServer>());
}

void HostServer::NotifyInfoChange() { info_getter_.Set(fidl_helpers::HostInfoToFidl(*adapter())); }

}  // namespace bthost
