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

#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/common/advertising_data.h"
#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/common/manufacturer_names.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/common/uuid.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/hci-spec/util.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/hci/low_energy_scanner.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/sm/types.h"
#include "src/connectivity/bluetooth/lib/cpp-string/string_printf.h"
#include "src/connectivity/bluetooth/lib/cpp-string/utf_codecs.h"

namespace bt::gap {
namespace {
// To prevent log spam, we only log every Nth failure to parse AdvertisingData
// from each peer. This value controls N.
const int64_t kAdvDataParseFailureWarnLogInterval = 25;
}  // namespace

std::string Peer::ConnectionStateToString(Peer::ConnectionState state) {
  switch (state) {
    case Peer::ConnectionState::kNotConnected:
      return "not connected";
    case Peer::ConnectionState::kInitializing:
      return "connecting";
    case Peer::ConnectionState::kConnected:
      return "connected";
  }

  BT_PANIC("invalid connection state %u", static_cast<unsigned int>(state));
  return "(unknown)";
}

std::string Peer::NameSourceToString(Peer::NameSource name_source) {
  switch (name_source) {
    case Peer::NameSource::kNameDiscoveryProcedure:
      return "Name Discovery Procedure";
    case Peer::NameSource::kAdvertisingDataComplete:
      return "Advertising data (complete)";
    case Peer::NameSource::kAdvertisingDataShortened:
      return "Advertising data (shortened)";
    case Peer::NameSource::kInquiryResultComplete:
      return "Inquiry result (complete)";
    case Peer::NameSource::kInquiryResultShortened:
      return "Inquiry result (shortened)";
    case Peer::NameSource::kGenericAccessService:
      return "Generic Access Service";
    case Peer::NameSource::kUnknown:
      return "Unknown source";
  }

  BT_PANIC("invalid peer name source %u",
           static_cast<unsigned int>(name_source));
  return "(unknown)";
}

Peer::LowEnergyData::LowEnergyData(Peer* owner)
    : peer_(owner),
      bond_data_(std::nullopt,
                 [](const std::optional<sm::PairingData>& p) {
                   return p.has_value();
                 }),
      auto_conn_behavior_(AutoConnectBehavior::kAlways),
      features_(std::nullopt,
                [](const std::optional<hci_spec::LESupportedFeatures> f) {
                  return f ? bt_lib_cpp_string::StringPrintf("%#.16lx",
                                                             f->le_features)
                           : "";
                }),
      service_changed_gatt_data_({.notify = false, .indicate = false}) {
  BT_DEBUG_ASSERT(peer_);
}

void Peer::LowEnergyData::AttachInspect(inspect::Node& parent,
                                        std::string name) {
  node_ = parent.CreateChild(name);
  inspect_properties_.connection_state =
      node_.CreateString(LowEnergyData::kInspectConnectionStateName,
                         Peer::ConnectionStateToString(connection_state()));
  inspect_properties_.last_adv_data_parse_failure = node_.CreateString(
      LowEnergyData::kInspectLastAdvertisingDataParseFailureName, "");
  adv_data_parse_failure_count_.AttachInspect(
      node_, LowEnergyData::kInspectAdvertisingDataParseFailureCountName);
  bond_data_.AttachInspect(node_, LowEnergyData::kInspectBondDataName);
  features_.AttachInspect(node_, LowEnergyData::kInspectFeaturesName);
}

void Peer::LowEnergyData::SetAdvertisingData(
    int8_t rssi,
    const ByteBuffer& data,
    pw::chrono::SystemClock::time_point timestamp) {
  // Prolong this peer's expiration in case it is temporary.
  peer_->UpdateExpiry();

  peer_->SetRssiInternal(rssi);

  // Update the advertising data
  adv_data_buffer_ = DynamicByteBuffer(data.size());
  data.Copy(&adv_data_buffer_);
  AdvertisingData::ParseResult res =
      AdvertisingData::FromBytes(adv_data_buffer_);
  if (!res.is_ok()) {
    int64_t current_failure_count = *adv_data_parse_failure_count_;
    adv_data_parse_failure_count_.Set(current_failure_count + 1);
    inspect_properties_.last_adv_data_parse_failure.Set(
        AdvertisingData::ParseErrorToString(res.error_value()));
    std::string message = bt_lib_cpp_string::StringPrintf(
        "failed to parse advertising data: %s (peer: %s)",
        bt::AdvertisingData::ParseErrorToString(res.error_value()).c_str(),
        bt_str(peer_->identifier()));
    // To prevent log spam, we only log the first, and then every Nth failure to
    // parse AdvertisingData from each peer at WARN level. Other failures are
    // logged at DEBUG level.
    if (*adv_data_parse_failure_count_ % kAdvDataParseFailureWarnLogInterval ==
        1) {
      bt_log(WARN, "gap-le", "%s", message.c_str());
    } else {
      bt_log(DEBUG, "gap-le", "%s", message.c_str());
    }
    // Update the error if we don't have a successful parse already
    if (parsed_adv_data_.is_error()) {
      parsed_adv_data_ = std::move(res);
    }
  } else {
    // Only update the adv_timestamp if the AdvertisingData parsed successfully
    adv_timestamp_ = timestamp;
    parsed_adv_data_ = std::move(res);

    // Do not update the name of bonded peers because advertisements are
    // unauthenticated.
    // TODO(https://fxbug.dev/42166256): Populate more Peer fields with relevant
    // fields from parsed_adv_data_.
    if (!peer_->bonded() && parsed_adv_data_->local_name().has_value()) {
      peer_->RegisterNameInternal(
          parsed_adv_data_->local_name()->name,
          parsed_adv_data_->local_name()->is_complete
              ? Peer::NameSource::kAdvertisingDataComplete
              : Peer::NameSource::kAdvertisingDataShortened);
    }
  }

  peer_->UpdatePeerAndNotifyListeners(NotifyListenersChange::kBondNotUpdated);
}

Peer::InitializingConnectionToken
Peer::LowEnergyData::RegisterInitializingConnection() {
  ConnectionState prev_state = connection_state();
  initializing_tokens_count_++;
  OnConnectionStateMaybeChanged(prev_state);

  auto unregister_cb = [self = peer_->GetWeakPtr(), this] {
    if (!self.is_alive()) {
      return;
    }

    ConnectionState prev_state = connection_state();
    initializing_tokens_count_--;
    OnConnectionStateMaybeChanged(prev_state);
  };

  return InitializingConnectionToken(std::move(unregister_cb));
}

Peer::ConnectionToken Peer::LowEnergyData::RegisterConnection() {
  // The high-level connection state is the same whether one or many registered
  // connections exist, but we track each connection in metrics to support
  // multiple connections to the same peer.
  peer_->peer_metrics_->LogLeConnection();

  ConnectionState prev_state = connection_state();
  connection_tokens_count_++;
  OnConnectionStateMaybeChanged(prev_state);

  auto unregister_cb = [self = peer_->GetWeakPtr(), this] {
    if (!self.is_alive()) {
      return;
    }

    connection_tokens_count_--;
    peer_->peer_metrics_->LogLeDisconnection();
    OnConnectionStateMaybeChanged(/*previous=*/ConnectionState::kConnected);
  };

  return ConnectionToken(std::move(unregister_cb));
}

void Peer::LowEnergyData::SetConnectionParameters(
    const hci_spec::LEConnectionParameters& params) {
  BT_DEBUG_ASSERT(peer_->connectable());
  conn_params_ = params;
}

void Peer::LowEnergyData::SetPreferredConnectionParameters(
    const hci_spec::LEPreferredConnectionParameters& params) {
  BT_DEBUG_ASSERT(peer_->connectable());
  preferred_conn_params_ = params;
}

bool Peer::LowEnergyData::StoreBond(const sm::PairingData& bond_data) {
  return peer_->store_le_bond_callback_(bond_data);
}

void Peer::LowEnergyData::SetBondData(const sm::PairingData& bond_data) {
  BT_DEBUG_ASSERT(peer_->connectable());
  BT_DEBUG_ASSERT(peer_->address().type() != DeviceAddress::Type::kLEAnonymous);

  // Make sure the peer is non-temporary.
  peer_->TryMakeNonTemporary();

  // This will mark the peer as bonded
  bond_data_.Set(bond_data);

  // Update to the new identity address if the current address is random.
  if (peer_->address().type() == DeviceAddress::Type::kLERandom &&
      bond_data.identity_address) {
    peer_->set_identity_known(true);
    peer_->set_address(*bond_data.identity_address);
  }

  // PeerCache notifies listeners of new bonds, so no need to request that here.
  peer_->UpdatePeerAndNotifyListeners(NotifyListenersChange::kBondNotUpdated);
}

void Peer::LowEnergyData::ClearBondData() {
  BT_ASSERT(bond_data_->has_value());
  if (bond_data_->value().irk) {
    peer_->set_identity_known(false);
  }
  bond_data_.Set(std::nullopt);
}

void Peer::LowEnergyData::OnConnectionStateMaybeChanged(
    ConnectionState previous) {
  if (connection_state() == previous) {
    return;
  }

  bt_log(DEBUG,
         "gap-le",
         "peer (%s) LE connection state changed from %s to %s (initializing "
         "count: %hu, "
         "connection count: %hu)",
         bt_str(peer_->identifier()),
         ConnectionStateToString(previous).c_str(),
         ConnectionStateToString(connection_state()).c_str(),
         initializing_tokens_count_,
         connection_tokens_count_);

  inspect_properties_.connection_state.Set(
      ConnectionStateToString(connection_state()));

  if (previous == ConnectionState::kNotConnected) {
    peer_->TryMakeNonTemporary();
  } else if (connection_state() == ConnectionState::kNotConnected) {
    peer_->TryMakeTemporary();
  }

  peer_->UpdateExpiry();
  peer_->UpdatePeerAndNotifyListeners(NotifyListenersChange::kBondNotUpdated);
}

Peer::BrEdrData::BrEdrData(Peer* owner)
    : peer_(owner), services_({}, MakeContainerOfToStringConvertFunction()) {
  BT_DEBUG_ASSERT(peer_);
  BT_DEBUG_ASSERT(peer_->identity_known());

  // Devices that are capable of BR/EDR and use a LE random device address will
  // end up with separate entries for the BR/EDR and LE addresses.
  BT_DEBUG_ASSERT(peer_->address().type() != DeviceAddress::Type::kLERandom &&
                  peer_->address().type() != DeviceAddress::Type::kLEAnonymous);
  address_ = {DeviceAddress::Type::kBREDR, peer_->address().value()};
}

void Peer::BrEdrData::AttachInspect(inspect::Node& parent, std::string name) {
  node_ = parent.CreateChild(name);
  inspect_properties_.connection_state =
      node_.CreateString(BrEdrData::kInspectConnectionStateName,
                         ConnectionStateToString(connection_state()));

  if (bonded()) {
    link_key_.value().AttachInspect(node_, BrEdrData::kInspectLinkKeyName);
  }
  services_.AttachInspect(node_, BrEdrData::kInspectServicesName);
}

void Peer::BrEdrData::SetInquiryData(
    const pw::bluetooth::emboss::InquiryResultView& view) {
  BT_DEBUG_ASSERT(peer_->address().value() ==
                  DeviceAddressBytes{view.bd_addr()});
  SetInquiryData(
      DeviceClass(view.class_of_device().BackingStorage().ReadUInt()),
      view.clock_offset().BackingStorage().ReadUInt(),
      view.page_scan_repetition_mode().Read());
}

void Peer::BrEdrData::SetInquiryData(
    const pw::bluetooth::emboss::InquiryResultWithRssiView& view) {
  BT_DEBUG_ASSERT(peer_->address().value() ==
                  DeviceAddressBytes{view.bd_addr()});
  SetInquiryData(
      DeviceClass(view.class_of_device().BackingStorage().ReadUInt()),
      view.clock_offset().BackingStorage().ReadUInt(),
      view.page_scan_repetition_mode().Read(),
      view.rssi().Read());
}

void Peer::BrEdrData::SetInquiryData(
    const pw::bluetooth::emboss::ExtendedInquiryResultEventView& view) {
  BT_DEBUG_ASSERT(peer_->address().value() ==
                  DeviceAddressBytes(view.bd_addr()));
  const BufferView response_view(
      view.extended_inquiry_response().BackingStorage().data(),
      view.extended_inquiry_response().SizeInBytes());
  SetInquiryData(
      DeviceClass(view.class_of_device().BackingStorage().ReadUInt()),
      view.clock_offset().BackingStorage().ReadUInt(),
      view.page_scan_repetition_mode().Read(),
      view.rssi().Read(),
      response_view);
}

Peer::InitializingConnectionToken
Peer::BrEdrData::RegisterInitializingConnection() {
  BT_ASSERT(!connected());

  ConnectionState prev_state = connection_state();
  initializing_tokens_count_++;
  OnConnectionStateMaybeChanged(prev_state);

  return InitializingConnectionToken([self = peer_->GetWeakPtr(), this] {
    if (!self.is_alive()) {
      return;
    }

    ConnectionState prev_state = connection_state();
    initializing_tokens_count_--;
    OnConnectionStateMaybeChanged(prev_state);
  });
}

Peer::ConnectionToken Peer::BrEdrData::RegisterConnection() {
  BT_ASSERT_MSG(!connected(),
                "attempt to register BR/EDR connection when a connection is "
                "already registered (peer: %s)",
                bt_str(peer_->identifier()));

  ConnectionState prev_state = connection_state();
  connection_tokens_count_++;
  OnConnectionStateMaybeChanged(prev_state);

  return ConnectionToken([self = peer_->GetWeakPtr(), this] {
    if (!self.is_alive()) {
      return;
    }

    ConnectionState prev_state = connection_state();
    connection_tokens_count_--;
    OnConnectionStateMaybeChanged(prev_state);
  });
}

void Peer::BrEdrData::OnConnectionStateMaybeChanged(ConnectionState previous) {
  if (previous == connection_state()) {
    return;
  }

  bt_log(DEBUG,
         "gap-bredr",
         "peer (%s) BR/EDR connection state changed from \"%s\" to \"%s\"",
         bt_str(peer_->identifier()),
         ConnectionStateToString(previous).c_str(),
         ConnectionStateToString(connection_state()).c_str());
  inspect_properties_.connection_state.Set(
      ConnectionStateToString(connection_state()));

  if (connection_state() == ConnectionState::kConnected) {
    peer_->peer_metrics_->LogBrEdrConnection();
  } else if (previous == ConnectionState::kConnected) {
    peer_->peer_metrics_->LogBrEdrDisconnection();
  }

  peer_->UpdateExpiry();

  // Transition to or from kConnected state is a notifyable change.
  if (previous == ConnectionState::kConnected ||
      connection_state() == ConnectionState::kConnected) {
    peer_->UpdatePeerAndNotifyListeners(NotifyListenersChange::kBondNotUpdated);
  }

  // Become non-temporary if we successfully connect or are initializing. BR/EDR
  // device remain non-temporary afterwards if bonded, and temporary again if
  // disconnect without bonding.
  if (connection_state() == ConnectionState::kNotConnected) {
    peer_->TryMakeTemporary();
  } else {
    peer_->TryMakeNonTemporary();
  }
}

void Peer::BrEdrData::SetInquiryData(
    DeviceClass device_class,
    uint16_t clock_offset,
    pw::bluetooth::emboss::PageScanRepetitionMode page_scan_rep_mode,
    int8_t rssi,
    const BufferView& eir_data) {
  peer_->UpdateExpiry();

  bool notify_listeners = false;

  // TODO(armansito): Consider sending notifications for RSSI updates perhaps
  // with throttling to avoid spamming.
  peer_->SetRssiInternal(rssi);

  page_scan_rep_mode_ = page_scan_rep_mode;
  clock_offset_ = le16toh(clock_offset) & hci_spec::kClockOffsetMask;

  if (!device_class_ || *device_class_ != device_class) {
    device_class_ = device_class;
    notify_listeners = true;
  }

  if (eir_data.size() && SetEirData(eir_data)) {
    notify_listeners = true;
  }

  peer_->OnPeerUpdate();

  if (notify_listeners) {
    peer_->NotifyListeners(NotifyListenersChange::kBondNotUpdated);
  }
}

bool Peer::BrEdrData::SetEirData(const ByteBuffer& eir) {
  BT_DEBUG_ASSERT(eir.size());

  // TODO(armansito): Validate that the EIR data is not malformed?
  SupplementDataReader reader(eir);
  DataType type;
  BufferView data;
  bool changed = false;
  while (reader.GetNextField(&type, &data)) {
    if (type == DataType::kCompleteLocalName) {
      // TODO(armansito): Parse more fields.
      // Do not update the name of bonded peers because inquiry results are
      // unauthenticated.
      if (!peer_->bonded()) {
        changed = peer_->RegisterNameInternal(
            data.ToString(), Peer::NameSource::kInquiryResultComplete);
      }
    } else if (type == DataType::kIncomplete16BitServiceUuids ||
               type == DataType::kComplete16BitServiceUuids) {
      // TODO(https://fxbug.dev/42082102): Consider adding 32-bit and 128-bit
      // UUIDs to the list
      ParseUuids(
          data, UUIDElemSize::k16Bit, [this, &changed](const UUID& uuid) {
            auto [_, inserted] = services_.Mutable()->insert(uuid);
            if (inserted) {
              changed = true;
            }
            return true;
          });
    }
  }
  return changed;
}

void Peer::BrEdrData::SetBondData(const sm::LTK& link_key) {
  BT_DEBUG_ASSERT(peer_->connectable());

  // Make sure the peer is non-temporary.
  peer_->TryMakeNonTemporary();

  // Storing the key establishes the bond.
  link_key_ = link_key;
  link_key_.value().AttachInspect(node_, BrEdrData::kInspectLinkKeyName);

  // PeerCache notifies listeners of new bonds, so no need to request that here.
  peer_->UpdatePeerAndNotifyListeners(NotifyListenersChange::kBondNotUpdated);
}

void Peer::BrEdrData::ClearBondData() {
  BT_ASSERT(link_key_.has_value());
  link_key_ = std::nullopt;
}

void Peer::BrEdrData::AddService(UUID uuid) {
  auto [_, inserted] = services_.Mutable()->insert(uuid);
  if (inserted) {
    auto update_bond = bonded() ? NotifyListenersChange::kBondUpdated
                                : NotifyListenersChange::kBondNotUpdated;
    peer_->UpdatePeerAndNotifyListeners(update_bond);
  }
}

Peer::Peer(NotifyListenersCallback notify_listeners_callback,
           PeerCallback update_expiry_callback,
           PeerCallback dual_mode_callback,
           StoreLowEnergyBondCallback store_le_bond_callback,
           PeerId identifier,
           const DeviceAddress& address,
           bool connectable,
           PeerMetrics* peer_metrics,
           pw::async::Dispatcher& dispatcher)
    : notify_listeners_callback_(std::move(notify_listeners_callback)),
      update_expiry_callback_(std::move(update_expiry_callback)),
      dual_mode_callback_(std::move(dual_mode_callback)),
      store_le_bond_callback_(std::move(store_le_bond_callback)),
      identifier_(identifier, MakeToStringInspectConvertFunction()),
      technology_((address.type() == DeviceAddress::Type::kBREDR)
                      ? TechnologyType::kClassic
                      : TechnologyType::kLowEnergy,
                  [](TechnologyType t) { return TechnologyTypeToString(t); }),
      address_(address, MakeToStringInspectConvertFunction()),
      identity_known_(false),
      name_(std::nullopt,
            [](const std::optional<PeerName>& v) {
              return v ? v->name +
                             " [source: " + NameSourceToString(v->source) + "]"
                       : "";
            }),
      lmp_version_(std::nullopt,
                   [](const std::optional<
                       pw::bluetooth::emboss::CoreSpecificationVersion>& v) {
                     return v ? hci_spec::HCIVersionToString(*v) : "";
                   }),
      lmp_manufacturer_(std::nullopt,
                        [](const std::optional<uint16_t>& m) {
                          return m ? GetManufacturerName(*m) : "";
                        }),
      lmp_features_(hci_spec::LMPFeatureSet(),
                    MakeToStringInspectConvertFunction()),
      connectable_(connectable),
      temporary_(true),
      rssi_(hci_spec::kRSSIInvalid),
      peer_metrics_(peer_metrics),
      last_updated_(dispatcher.now()),
      dispatcher_(dispatcher),
      weak_self_(this) {
  BT_DEBUG_ASSERT(notify_listeners_callback_);
  BT_DEBUG_ASSERT(update_expiry_callback_);
  BT_DEBUG_ASSERT(dual_mode_callback_);
  BT_DEBUG_ASSERT(identifier.IsValid());

  if (address.type() == DeviceAddress::Type::kBREDR ||
      address.type() == DeviceAddress::Type::kLEPublic) {
    identity_known_ = true;
  }

  // Initialize transport-specific state.
  if (*technology_ == TechnologyType::kClassic) {
    bredr_data_ = BrEdrData(this);
  } else {
    le_data_ = LowEnergyData(this);
  }
}

void Peer::AttachInspect(inspect::Node& parent, std::string node_name) {
  node_ = parent.CreateChild(node_name);
  identifier_.AttachInspect(node_, kInspectPeerIdName);
  technology_.AttachInspect(node_, kInspectTechnologyName);
  address_.AttachInspect(node_, kInspectAddressName);
  name_.AttachInspect(node_, kInspectPeerNameName);
  lmp_version_.AttachInspect(node_, kInspectVersionName);
  lmp_manufacturer_.AttachInspect(node_, kInspectManufacturerName);
  lmp_features_.AttachInspect(node_, kInspectFeaturesName);
  connectable_.AttachInspect(node_, kInspectConnectableName);
  temporary_.AttachInspect(node_, kInspectTemporaryName);

  if (bredr_data_) {
    bredr_data_->AttachInspect(node_, Peer::BrEdrData::kInspectNodeName);
  }
  if (le_data_) {
    le_data_->AttachInspect(node_, Peer::LowEnergyData::kInspectNodeName);
  }
}

Peer::LowEnergyData& Peer::MutLe() {
  if (le_data_) {
    return *le_data_;
  }

  le_data_ = LowEnergyData(this);
  le_data_->AttachInspect(node_);

  // Make dual-mode if both transport states have been initialized.
  if (bredr_data_) {
    MakeDualMode();
  }
  return *le_data_;
}

Peer::BrEdrData& Peer::MutBrEdr() {
  if (bredr_data_) {
    return *bredr_data_;
  }

  bredr_data_ = BrEdrData(this);
  bredr_data_->AttachInspect(node_);

  // Make dual-mode if both transport states have been initialized.
  if (le_data_) {
    MakeDualMode();
  }
  return *bredr_data_;
}

std::string Peer::ToString() const {
  return bt_lib_cpp_string::StringPrintf(
      "{peer id: %s, address: %s}", bt_str(*identifier_), bt_str(*address_));
}

bool Peer::RegisterName(const std::string& name, Peer::NameSource source) {
  if (RegisterNameInternal(name, source)) {
    UpdateExpiry();
    // TODO(https://fxbug.dev/42140058): Update the bond when this happens
    UpdatePeerAndNotifyListeners(NotifyListenersChange::kBondNotUpdated);
    return true;
  }
  return false;
}

void Peer::StoreBrEdrCrossTransportKey(sm::LTK ct_key) {
  if (!bredr_data_.has_value()) {
    // If the peer is LE-only, store the CT key separately until the peer is
    // otherwise marked as dual-mode.
    bredr_cross_transport_key_ = ct_key;
  } else if (!bredr_data_->link_key().has_value() ||
             ct_key.security().IsAsSecureAs(
                 bredr_data_->link_key()->security())) {
    // "The devices shall not overwrite that existing key with a key that is
    // weaker in either strength or MITM protection." (v5.2 Vol. 3 Part C 14.1).
    bredr_data_->SetBondData(ct_key);
  }
}

// Private methods below:

bool Peer::SetRssiInternal(int8_t rssi) {
  if (rssi != hci_spec::kRSSIInvalid && rssi_ != rssi) {
    rssi_ = rssi;
    return true;
  }
  return false;
}

bool Peer::RegisterNameInternal(const std::string& name,
                                Peer::NameSource source) {
  if (!bt_lib_cpp_string::IsStringUTF8(name)) {
    bt_log(WARN,
           "gap",
           "%s: not setting name to string that is not valid UTF-8",
           bt_str(*this));
    return false;
  }
  if (!name_->has_value() || source < (*name_)->source ||
      (source == (*name_)->source && name != (*name_)->name)) {
    name_.Set(Peer::PeerName{name, source});
    return true;
  }
  return false;
}

bool Peer::TryMakeNonTemporary() {
  // TODO(armansito): Since we don't currently support address resolution,
  // random addresses should never be persisted.
  if (!connectable()) {
    bt_log(DEBUG, "gap", "remains temporary: %s", bt_str(*this));
    return false;
  }

  bt_log(DEBUG, "gap", "became non-temporary: %s:", bt_str(*this));

  if (*temporary_) {
    temporary_.Set(false);
    UpdateExpiry();
    UpdatePeerAndNotifyListeners(NotifyListenersChange::kBondNotUpdated);
  }

  return true;
}

bool Peer::TryMakeTemporary() {
  if (le() && le()->connection_state() == ConnectionState::kNotConnected &&
      !identity_known()) {
    bt_log(DEBUG, "gap", "LE became temporary: %s:", bt_str(*this));
    temporary_.Set(true);
    return true;
  }
  if (bredr() && !bredr()->bonded()) {
    bt_log(DEBUG, "gap", "BR/EDR became temporary: %s:", bt_str(*this));
    temporary_.Set(true);
    return true;
  }
  return false;
}

void Peer::UpdateExpiry() {
  BT_DEBUG_ASSERT(update_expiry_callback_);
  update_expiry_callback_(*this);
}

void Peer::NotifyListeners(NotifyListenersChange change) {
  BT_DEBUG_ASSERT(notify_listeners_callback_);
  notify_listeners_callback_(*this, change);
}

void Peer::MakeDualMode() {
  technology_.Set(TechnologyType::kDualMode);
  if (bredr_cross_transport_key_) {
    BT_ASSERT(
        bredr_data_);  // Should only be hit after BR/EDR is already created.
    bredr_data_->SetBondData(*bredr_cross_transport_key_);
    bt_log(DEBUG,
           "gap-bredr",
           "restored cross-transport-generated br/edr link key");
    bredr_cross_transport_key_ = std::nullopt;
  }
  BT_DEBUG_ASSERT(dual_mode_callback_);
  dual_mode_callback_(*this);
}

void Peer::OnPeerUpdate() { last_updated_ = dispatcher_.now(); }

void Peer::UpdatePeerAndNotifyListeners(NotifyListenersChange change) {
  OnPeerUpdate();
  NotifyListeners(change);
}

}  // namespace bt::gap
