// 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 "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/gap/low_energy_interrogator.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/hci-spec/constants.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/transport/command_channel.h"

namespace bt::gap {

LowEnergyInterrogator::LowEnergyInterrogator(
    Peer::WeakPtr peer,
    hci_spec::ConnectionHandle handle,
    hci::CommandChannel::WeakPtr cmd_channel,
    bool sca_supported)
    : peer_(std::move(peer)),
      peer_id_(peer_->identifier()),
      handle_(handle),
      cmd_runner_(cmd_channel->AsWeakPtr()),
      controller_supports_sca_(sca_supported),
      weak_self_(this) {}

void LowEnergyInterrogator::Start(ResultCallback callback) {
  BT_ASSERT(!callback_);
  callback_ = std::move(callback);

  if (!peer_.is_alive()) {
    Complete(ToResult(HostError::kFailed));
    return;
  }

  BT_ASSERT(peer_->le().has_value());

  // Always read remote version information as a test of whether the connection
  // was *actually* successfully established. If the connection failed to be
  // established, the command status of the Read Remote Version Information
  // command will be "Connection Failed to be Established".
  // See https://fxbug.dev/42138706 for details.
  QueueReadRemoteVersionInformation();

  if (!peer_->le()->features().has_value()) {
    QueueReadLERemoteFeatures();
  }

  cmd_runner_.RunCommands([this](hci::Result<> result) {
    if (result.is_error() || !peer_->le()->features().has_value() ||
        !controller_supports_sca_) {
      Complete(result);
      return;
    }

    // Verify the peer supports SCA updates
    if (!(peer_->le()->features()->le_features &
          static_cast<uint64_t>(
              hci_spec::LESupportedFeature::kSleepClockAccuracyUpdates))) {
      bt_log(INFO, "gap-le", "peer %s does not support SCA", bt_str(peer_id_));
      Complete(result);
      return;
    }

    QueueRequestPeerSca();
  });
}

void LowEnergyInterrogator::Cancel() {
  if (!cmd_runner_.IsReady()) {
    cmd_runner_.Cancel();
  }
}

void LowEnergyInterrogator::Complete(hci::Result<> result) {
  if (!callback_) {
    return;
  }

  auto self = weak_self_.GetWeakPtr();

  // callback may destroy this object
  callback_(result);

  // Complete() may have been called by a command callback, in which case the
  // runner needs to be canceled.
  if (self.is_alive() && !cmd_runner_.IsReady()) {
    cmd_runner_.Cancel();
  }
}

void LowEnergyInterrogator::QueueRequestPeerSca() {
  auto packet = hci::EmbossCommandPacket::New<
      pw::bluetooth::emboss::LERequestPeerSCACommandWriter>(
      hci_spec::kLERequestPeerSCA);
  packet.view_t().connection_handle().Write(handle_);

  // It's safe to capture |this| instead of a weak ptr to self because
  // |cmd_runner_| guarantees that |cmd_cb| won't be invoked if |cmd_runner_| is
  // destroyed, and |this| outlives |cmd_runner_|.
  auto cmd_cb = [this](const hci::EmbossEventPacket& event) {
    if (hci_is_error(event, WARN, "gap-le", "LE request peer SCA failed")) {
      return;
    }
    auto view = event.view<
        pw::bluetooth::emboss::LERequestPeerSCACompleteSubeventView>();
    bt_log(DEBUG,
           "gap-le",
           "LE request peer SCA complete (peer: %s, value: %d)",
           bt_str(peer_id_),
           view.peer_clock_accuracy().Read());
    peer_->MutLe().set_sleep_clock_accuracy(view.peer_clock_accuracy().Read());
  };

  bt_log(TRACE, "gap-le", "requesting SCA for peer %s", bt_str(peer_id_));
  cmd_runner_.QueueLeAsyncCommand(
      std::move(packet),
      hci_spec::kLERequestPeerSCACompleteSubeventCode,
      std::move(cmd_cb),
      /*wait=*/true);
  cmd_runner_.RunCommands([this](hci::Result<> result) {
    // This shouldn't happen since we verified that the peer supports SCA
    // updates
    BT_DEBUG_ASSERT_MSG(!result.is_error(),
                        "request for SCA from peer %s failed",
                        bt_str(peer_id_));
    // Report success since the data is not critical and we don't want to
    // interrupt pairing
    Complete(fit::ok());
  });
}

void LowEnergyInterrogator::QueueReadLERemoteFeatures() {
  auto packet = hci::EmbossCommandPacket::New<
      pw::bluetooth::emboss::LEReadRemoteFeaturesCommandWriter>(
      hci_spec::kLEReadRemoteFeatures);
  packet.view_t().connection_handle().Write(handle_);

  // It's safe to capture |this| instead of a weak ptr to self because
  // |cmd_runner_| guarantees that |cmd_cb| won't be invoked if |cmd_runner_| is
  // destroyed, and |this| outlives |cmd_runner_|.
  auto cmd_cb = [this](const hci::EmbossEventPacket& event) {
    if (hci_is_error(event, WARN, "gap-le", "LE read remote features failed")) {
      return;
    }
    bt_log(DEBUG,
           "gap-le",
           "LE read remote features complete (peer: %s)",
           bt_str(peer_id_));
    auto view = event.view<
        pw::bluetooth::emboss::LEReadRemoteFeaturesCompleteSubeventView>();
    peer_->MutLe().SetFeatures(hci_spec::LESupportedFeatures{
        view.le_features().BackingStorage().ReadUInt()});
  };

  bt_log(TRACE,
         "gap-le",
         "sending LE read remote features command (peer id: %s)",
         bt_str(peer_id_));
  cmd_runner_.QueueLeAsyncCommand(
      std::move(packet),
      hci_spec::kLEReadRemoteFeaturesCompleteSubeventCode,
      std::move(cmd_cb),
      /*wait=*/false);
}

void LowEnergyInterrogator::QueueReadRemoteVersionInformation() {
  auto packet = hci::EmbossCommandPacket::New<
      pw::bluetooth::emboss::ReadRemoteVersionInfoCommandWriter>(
      hci_spec::kReadRemoteVersionInfo);
  packet.view_t().connection_handle().Write(handle_);

  // It's safe to capture |this| instead of a weak ptr to self because
  // |cmd_runner_| guarantees that |cmd_cb| won't be invoked if |cmd_runner_| is
  // destroyed, and |this| outlives |cmd_runner_|.
  auto cmd_cb = [this](const hci::EmbossEventPacket& event) {
    if (hci_is_error(
            event, WARN, "gap-le", "read remote version info failed")) {
      return;
    }
    BT_DEBUG_ASSERT(event.event_code() ==
                    hci_spec::kReadRemoteVersionInfoCompleteEventCode);
    bt_log(TRACE,
           "gap-le",
           "read remote version info completed (peer: %s)",
           bt_str(peer_id_));
    auto view = event.view<
        pw::bluetooth::emboss::ReadRemoteVersionInfoCompleteEventView>();
    peer_->set_version(view.version().Read(),
                       view.company_identifier().Read(),
                       view.subversion().Read());
  };

  bt_log(TRACE,
         "gap-le",
         "asking for version info (peer id: %s)",
         bt_str(peer_id_));
  cmd_runner_.QueueCommand(std::move(packet),
                           std::move(cmd_cb),
                           /*wait=*/false,
                           hci_spec::kReadRemoteVersionInfoCompleteEventCode);
}

}  // namespace bt::gap
