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

#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/common/log.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/sm/util.h"

namespace bt::gap {

LowEnergyAddressManager::LowEnergyAddressManager(
    const DeviceAddress& public_address,
    StateQueryDelegate delegate,
    hci::CommandChannel::WeakPtr cmd_channel,
    pw::async::Dispatcher& dispatcher)
    : dispatcher_(dispatcher),
      delegate_(std::move(delegate)),
      cmd_(std::move(cmd_channel)),
      privacy_enabled_(false),
      public_(public_address),
      needs_refresh_(false),
      refreshing_(false),
      weak_self_(this) {
  BT_DEBUG_ASSERT(public_.type() == DeviceAddress::Type::kLEPublic);
  BT_DEBUG_ASSERT(delegate_);
  BT_DEBUG_ASSERT(cmd_.is_alive());
}

LowEnergyAddressManager::~LowEnergyAddressManager() { CancelExpiry(); }

void LowEnergyAddressManager::EnablePrivacy(bool enabled) {
  if (enabled == privacy_enabled_) {
    bt_log(DEBUG,
           "gap-le",
           "privacy already %s",
           (enabled ? "enabled" : "disabled"));
    return;
  }

  privacy_enabled_ = enabled;

  if (!enabled) {
    CleanUpPrivacyState();
    ResolveAddressRequests();
    NotifyAddressUpdate();
    return;
  }

  needs_refresh_ = true;

  TryRefreshRandomAddress();
}

void LowEnergyAddressManager::EnsureLocalAddress(AddressCallback callback) {
  BT_DEBUG_ASSERT(callback);

  // Report the address right away if it doesn't need refreshing.
  if (!needs_refresh_) {
    callback(current_address());
    return;
  }

  address_callbacks_.push(std::move(callback));
  TryRefreshRandomAddress();
}

void LowEnergyAddressManager::TryRefreshRandomAddress() {
  if (!privacy_enabled_ || !needs_refresh_) {
    bt_log(DEBUG, "gap-le", "address does not need refresh");
    return;
  }

  if (refreshing_) {
    bt_log(DEBUG, "gap-le", "address update in progress");
    return;
  }

  if (!CanUpdateRandomAddress()) {
    bt_log(DEBUG,
           "gap-le",
           "deferring local address refresh due to ongoing procedures");
    // Don't stall procedures that requested the current address while in this
    // state.
    ResolveAddressRequests();
    return;
  }

  CancelExpiry();
  refreshing_ = true;

  DeviceAddress random_addr;
  if (irk_) {
    random_addr = sm::util::GenerateRpa(*irk_);
  } else {
    random_addr = sm::util::GenerateRandomAddress(/*is_static=*/false);
  }

  auto cmd = hci::EmbossCommandPacket::New<
      pw::bluetooth::emboss::LESetRandomAddressCommandWriter>(
      hci_spec::kLESetRandomAddress);
  cmd.view_t().random_address().CopyFrom(random_addr.value().view());

  auto self = weak_self_.GetWeakPtr();
  auto cmd_complete_cb = [self, this, random_addr](
                             auto id, const hci::EventPacket& event) {
    if (!self.is_alive()) {
      return;
    }

    refreshing_ = false;

    if (!privacy_enabled_) {
      bt_log(DEBUG,
             "gap-le",
             "ignore random address result while privacy is disabled");
      return;
    }

    if (!hci_is_error(
            event, TRACE, "gap-le", "failed to update random address")) {
      needs_refresh_ = false;
      random_ = random_addr;
      bt_log(INFO, "gap-le", "random address updated: %s", bt_str(*random_));

      // Set the new random address to expire in kPrivateAddressTimeout.
      random_address_expiry_task_.set_function(
          [this](pw::async::Context /*ctx*/, pw::Status status) {
            if (status.ok()) {
              needs_refresh_ = true;
              TryRefreshRandomAddress();
            }
          });
      random_address_expiry_task_.PostAfter(kPrivateAddressTimeout);

      // Notify any listeners of the change in device address.
      NotifyAddressUpdate();
    }

    ResolveAddressRequests();
  };

  cmd_->SendCommand(std::move(cmd), std::move(cmd_complete_cb));
}

void LowEnergyAddressManager::CleanUpPrivacyState() {
  privacy_enabled_ = false;
  needs_refresh_ = false;
  CancelExpiry();
}

void LowEnergyAddressManager::CancelExpiry() {
  random_address_expiry_task_.Cancel();
}

bool LowEnergyAddressManager::CanUpdateRandomAddress() const {
  BT_DEBUG_ASSERT(delegate_);
  return delegate_();
}

void LowEnergyAddressManager::ResolveAddressRequests() {
  auto address = current_address();
  auto q = std::move(address_callbacks_);
  bt_log(DEBUG, "gap-le", "using local address %s", address.ToString().c_str());
  while (!q.empty()) {
    q.front()(address);
    q.pop();
  }
}

void LowEnergyAddressManager::NotifyAddressUpdate() {
  auto address = current_address();
  for (auto& cb : address_changed_callbacks_) {
    cb(address);
  }
}

}  // namespace bt::gap
