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

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

namespace bt::hci {
using hci_spec::ConnectionHandle;
using hci_spec::LEConnectionParameters;
using pw::bluetooth::emboss::ConnectionRole;
using pw::bluetooth::emboss::GenericEnableParam;
using pw::bluetooth::emboss::LEAddressType;
using pw::bluetooth::emboss::LEConnectionCompleteSubeventView;
using pw::bluetooth::emboss::LECreateConnectionCancelCommandView;
using pw::bluetooth::emboss::LECreateConnectionCommandWriter;
using pw::bluetooth::emboss::LEEnhancedConnectionCompleteSubeventV1View;
using pw::bluetooth::emboss::LEExtendedCreateConnectionCommandV1Writer;
using pw::bluetooth::emboss::LEMetaEventView;
using pw::bluetooth::emboss::LEOwnAddressType;
using pw::bluetooth::emboss::LEPeerAddressType;
using pw::bluetooth::emboss::StatusCode;

LowEnergyConnector::PendingRequest::PendingRequest(
    const DeviceAddress& peer_address, StatusCallback status_callback)
    : peer_address(peer_address), status_callback(std::move(status_callback)) {}

LowEnergyConnector::LowEnergyConnector(
    Transport::WeakPtr hci,
    LocalAddressDelegate* local_addr_delegate,
    pw::async::Dispatcher& dispatcher,
    IncomingConnectionDelegate delegate,
    bool use_extended_operations)
    : pw_dispatcher_(dispatcher),
      hci_(std::move(hci)),
      local_addr_delegate_(local_addr_delegate),
      delegate_(std::move(delegate)),
      use_extended_operations_(use_extended_operations),
      weak_self_(this) {
  request_timeout_task_.set_function(
      [this](pw::async::Context& /*ctx*/, pw::Status status) {
        if (status.ok()) {
          OnCreateConnectionTimeout();
        }
      });

  CommandChannel::EventHandlerId id =
      hci_->command_channel()->AddLEMetaEventHandler(
          hci_spec::kLEConnectionCompleteSubeventCode,
          [this](const EmbossEventPacket& event) {
            OnConnectionCompleteEvent<LEConnectionCompleteSubeventView>(event);
            return CommandChannel::EventCallbackResult::kContinue;
          });
  event_handler_ids_.insert(id);

  id = hci_->command_channel()->AddLEMetaEventHandler(
      hci_spec::kLEEnhancedConnectionCompleteSubeventCode,
      [this](const EmbossEventPacket& event) {
        OnConnectionCompleteEvent<LEEnhancedConnectionCompleteSubeventV1View>(
            event);
        return CommandChannel::EventCallbackResult::kContinue;
      });
  event_handler_ids_.insert(id);
}

LowEnergyConnector::~LowEnergyConnector() {
  if (request_pending()) {
    Cancel();
  }

  if (hci_.is_alive() && hci_->command_channel()) {
    for (CommandChannel::EventHandlerId id : event_handler_ids_) {
      hci_->command_channel()->RemoveEventHandler(id);
    }
  }
}

bool LowEnergyConnector::CreateConnection(
    bool use_accept_list,
    const DeviceAddress& peer_address,
    uint16_t scan_interval,
    uint16_t scan_window,
    const hci_spec::LEPreferredConnectionParameters& initial_parameters,
    StatusCallback status_callback,
    pw::chrono::SystemClock::duration timeout) {
  BT_DEBUG_ASSERT(status_callback);
  BT_DEBUG_ASSERT(timeout.count() > 0);

  if (request_pending()) {
    return false;
  }

  BT_DEBUG_ASSERT(!request_timeout_task_.is_pending());
  pending_request_ = PendingRequest(peer_address, std::move(status_callback));

  if (use_local_identity_address_) {
    // Use the identity address if privacy override was enabled.
    DeviceAddress address = local_addr_delegate_->identity_address();
    CreateConnectionInternal(address,
                             use_accept_list,
                             peer_address,
                             scan_interval,
                             scan_window,
                             initial_parameters,
                             std::move(status_callback),
                             timeout);
    return true;
  }

  local_addr_delegate_->EnsureLocalAddress(
      [=, callback = std::move(status_callback)](
          const DeviceAddress& address) mutable {
        CreateConnectionInternal(address,
                                 use_accept_list,
                                 peer_address,
                                 scan_interval,
                                 scan_window,
                                 initial_parameters,
                                 std::move(callback),
                                 timeout);
      });

  return true;
}

std::optional<DeviceAddress> LowEnergyConnector::pending_peer_address() const {
  if (pending_request_) {
    return pending_request_->peer_address;
  }

  return std::nullopt;
}

void LowEnergyConnector::CreateConnectionInternal(
    const DeviceAddress& local_address,
    bool use_accept_list,
    const DeviceAddress& peer_address,
    uint16_t scan_interval,
    uint16_t scan_window,
    const hci_spec::LEPreferredConnectionParameters& initial_params,
    StatusCallback status_callback,
    pw::chrono::SystemClock::duration timeout) {
  if (!hci_.is_alive()) {
    return;
  }

  // Check if the connection request was canceled via Cancel().
  if (!pending_request_ || pending_request_->canceled) {
    bt_log(DEBUG,
           "hci-le",
           "connection request was canceled while obtaining local address");
    pending_request_.reset();
    return;
  }

  BT_DEBUG_ASSERT(!pending_request_->initiating);

  pending_request_->initiating = true;
  pending_request_->local_address = local_address;

  // HCI Command Status Event will be sent as our completion callback.
  auto self = weak_self_.GetWeakPtr();
  auto complete_cb = [self, timeout](auto id, const EventPacket& event) {
    BT_DEBUG_ASSERT(event.event_code() == hci_spec::kCommandStatusEventCode);

    if (!self.is_alive()) {
      return;
    }

    Result<> result = event.ToResult();
    if (result.is_error()) {
      self->OnCreateConnectionComplete(result, nullptr);
      return;
    }

    // The request was started but has not completed; initiate the command
    // timeout period. NOTE: The request will complete when the controller
    // asynchronously notifies us of with a LE Connection Complete event.
    self->request_timeout_task_.Cancel();
    self->request_timeout_task_.PostAfter(timeout);
  };

  std::optional<EmbossCommandPacket> request;
  if (use_extended_operations_) {
    request.emplace(BuildExtendedCreateConnectionPacket(local_address,
                                                        peer_address,
                                                        initial_params,
                                                        use_accept_list,
                                                        scan_interval,
                                                        scan_window));
  } else {
    request.emplace(BuildCreateConnectionPacket(local_address,
                                                peer_address,
                                                initial_params,
                                                use_accept_list,
                                                scan_interval,
                                                scan_window));
  }

  hci_->command_channel()->SendCommand(std::move(request.value()),
                                       complete_cb,
                                       hci_spec::kCommandStatusEventCode);
}

EmbossCommandPacket LowEnergyConnector::BuildExtendedCreateConnectionPacket(
    const DeviceAddress& local_address,
    const DeviceAddress& peer_address,
    const hci_spec::LEPreferredConnectionParameters& initial_params,
    bool use_accept_list,
    uint16_t scan_interval,
    uint16_t scan_window) {
  // The LE Extended Create Connection Command ends with a variable amount of
  // data: per PHY connection settings. Depending on the PHYs we select to scan
  // on when connecting, the variable amount of data at the end of the packet
  // grows. Currently, we scan on all available PHYs. Thus, we use the maximum
  // size of this packet.
  size_t max_size = pw::bluetooth::emboss::LEExtendedCreateConnectionCommandV1::
      MaxSizeInBytes();

  auto packet =
      EmbossCommandPacket::New<LEExtendedCreateConnectionCommandV1Writer>(
          hci_spec::kLEExtendedCreateConnection, max_size);
  auto params = packet.view_t();

  if (use_accept_list) {
    params.initiator_filter_policy().Write(GenericEnableParam::ENABLE);
  } else {
    params.initiator_filter_policy().Write(GenericEnableParam::DISABLE);
  }

  // TODO(http://b/328311582): Use the resolved address types for <5.0 LE
  // Privacy.
  if (peer_address.IsPublic()) {
    params.peer_address_type().Write(LEPeerAddressType::PUBLIC);
  } else {
    params.peer_address_type().Write(LEPeerAddressType::RANDOM);
  }

  if (local_address.IsPublic()) {
    params.own_address_type().Write(LEOwnAddressType::PUBLIC);
  } else {
    params.own_address_type().Write(LEOwnAddressType::RANDOM);
  }

  params.peer_address().CopyFrom(peer_address.value().view());

  // We scan on all available PHYs for a connection
  params.initiating_phys().le_1m().Write(true);
  params.initiating_phys().le_2m().Write(true);
  params.initiating_phys().le_coded().Write(true);

  for (int i = 0; i < params.num_entries().Read(); i++) {
    params.data()[i].scan_interval().Write(scan_interval);
    params.data()[i].scan_window().Write(scan_window);
    params.data()[i].connection_interval_min().Write(
        initial_params.min_interval());
    params.data()[i].connection_interval_max().Write(
        initial_params.max_interval());
    params.data()[i].max_latency().Write(initial_params.max_latency());
    params.data()[i].supervision_timeout().Write(
        initial_params.supervision_timeout());

    // These fields provide the expected minimum and maximum duration of
    // connection events. We have no preference, so we set them to zero and let
    // the Controller decide. Some Controllers require
    // max_ce_length < max_connection_interval * 2.
    params.data()[i].min_connection_event_length().Write(0x0000);
    params.data()[i].max_connection_event_length().Write(0x0000);
  }

  return packet;
}

EmbossCommandPacket LowEnergyConnector::BuildCreateConnectionPacket(
    const DeviceAddress& local_address,
    const DeviceAddress& peer_address,
    const hci_spec::LEPreferredConnectionParameters& initial_params,
    bool use_accept_list,
    uint16_t scan_interval,
    uint16_t scan_window) {
  auto packet = EmbossCommandPacket::New<LECreateConnectionCommandWriter>(
      hci_spec::kLECreateConnection);
  auto params = packet.view_t();

  if (use_accept_list) {
    params.initiator_filter_policy().Write(GenericEnableParam::ENABLE);
  } else {
    params.initiator_filter_policy().Write(GenericEnableParam::DISABLE);
  }

  // TODO(http://b/328311582): Use the resolved address types for <5.0 LE
  // Privacy.
  if (peer_address.IsPublic()) {
    params.peer_address_type().Write(LEAddressType::PUBLIC);
  } else {
    params.peer_address_type().Write(LEAddressType::RANDOM);
  }

  if (local_address.IsPublic()) {
    params.own_address_type().Write(LEOwnAddressType::PUBLIC);
  } else {
    params.own_address_type().Write(LEOwnAddressType::RANDOM);
  }

  params.le_scan_interval().Write(scan_interval);
  params.le_scan_window().Write(scan_window);
  params.peer_address().CopyFrom(peer_address.value().view());
  params.connection_interval_min().Write(initial_params.min_interval());
  params.connection_interval_max().Write(initial_params.max_interval());
  params.max_latency().Write(initial_params.max_latency());
  params.supervision_timeout().Write(initial_params.supervision_timeout());

  // These fields provide the expected minimum and maximum duration of
  // connection events. We have no preference, so we set them to zero and let
  // the Controller decide. Some Controllers require
  // max_ce_length < max_connection_interval * 2.
  params.min_connection_event_length().Write(0x0000);
  params.max_connection_event_length().Write(0x0000);

  return packet;
}

void LowEnergyConnector::CancelInternal(bool timed_out) {
  BT_DEBUG_ASSERT(request_pending());

  if (pending_request_->canceled) {
    bt_log(WARN, "hci-le", "connection attempt already canceled!");
    return;
  }

  // At this point we do not know whether the pending connection request has
  // completed or not (it may have completed in the controller but that does not
  // mean that we have processed the corresponding LE Connection Complete
  // event). Below we mark the request as canceled and tell the controller to
  // cancel its pending connection attempt.
  pending_request_->canceled = true;
  pending_request_->timed_out = timed_out;

  request_timeout_task_.Cancel();

  // Tell the controller to cancel the connection initiation attempt if a
  // request is outstanding. Otherwise there is no need to talk to the
  // controller.
  if (pending_request_->initiating && hci_.is_alive()) {
    bt_log(
        DEBUG, "hci-le", "telling controller to cancel LE connection attempt");
    auto complete_cb = [](auto id, const EventPacket& event) {
      hci_is_error(
          event, WARN, "hci-le", "failed to cancel connection request");
    };
    auto cancel = EmbossCommandPacket::New<LECreateConnectionCancelCommandView>(
        hci_spec::kLECreateConnectionCancel);
    hci_->command_channel()->SendCommand(std::move(cancel), complete_cb);

    // A connection complete event will be generated by the controller after
    // processing the cancel command.
    return;
  }

  bt_log(DEBUG, "hci-le", "connection initiation aborted");
  OnCreateConnectionComplete(ToResult(HostError::kCanceled), nullptr);
}

template <typename T>
void LowEnergyConnector::OnConnectionCompleteEvent(
    const EmbossEventPacket& event) {
  auto params = event.view<T>();

  DeviceAddress::Type address_type =
      DeviceAddress::LeAddrToDeviceAddr(params.peer_address_type().Read());
  DeviceAddressBytes address_bytes = DeviceAddressBytes(params.peer_address());
  DeviceAddress peer_address = DeviceAddress(address_type, address_bytes);

  // First check if this event is related to the currently pending request.
  const bool matches_pending_request =
      pending_request_ &&
      (pending_request_->peer_address.value() == peer_address.value());

  if (Result<> result = event.ToResult(); result.is_error()) {
    if (!matches_pending_request) {
      bt_log(WARN,
             "hci-le",
             "unexpected connection complete event with error received: %s",
             bt_str(result));
      return;
    }

    // The "Unknown Connect Identifier" error code is returned if this event
    // was sent due to a successful cancelation via the
    // HCI_LE_Create_Connection_Cancel command (sent by Cancel()).
    if (pending_request_->timed_out) {
      result = ToResult(HostError::kTimedOut);
    } else if (params.status().Read() == StatusCode::UNKNOWN_CONNECTION_ID) {
      result = ToResult(HostError::kCanceled);
    }

    OnCreateConnectionComplete(result, nullptr);
    return;
  }

  ConnectionRole role = params.role().Read();
  ConnectionHandle handle = params.connection_handle().Read();
  LEConnectionParameters connection_params =
      LEConnectionParameters(params.connection_interval().Read(),
                             params.peripheral_latency().Read(),
                             params.supervision_timeout().Read());

  // If the connection did not match a pending request then we pass the
  // information down to the incoming connection delegate.
  if (!matches_pending_request) {
    delegate_(handle, role, peer_address, connection_params);
    return;
  }

  // A new link layer connection was created. Create an object to track this
  // connection. Destroying this object will disconnect the link.
  auto connection =
      std::make_unique<LowEnergyConnection>(handle,
                                            pending_request_->local_address,
                                            peer_address,
                                            connection_params,
                                            role,
                                            hci_);

  Result<> result = fit::ok();
  if (pending_request_->timed_out) {
    result = ToResult(HostError::kTimedOut);
  } else if (pending_request_->canceled) {
    result = ToResult(HostError::kCanceled);
  }

  // If we were requested to cancel the connection after the logical link
  // is created we disconnect it.
  if (result.is_error()) {
    connection = nullptr;
  }

  OnCreateConnectionComplete(result, std::move(connection));
}

void LowEnergyConnector::OnCreateConnectionComplete(
    Result<> result, std::unique_ptr<LowEnergyConnection> link) {
  BT_DEBUG_ASSERT(pending_request_);
  bt_log(DEBUG, "hci-le", "connection complete - status: %s", bt_str(result));

  request_timeout_task_.Cancel();

  auto status_cb = std::move(pending_request_->status_callback);
  pending_request_.reset();

  status_cb(result, std::move(link));
}

void LowEnergyConnector::OnCreateConnectionTimeout() {
  BT_DEBUG_ASSERT(pending_request_);
  bt_log(INFO, "hci-le", "create connection timed out: canceling request");

  // TODO(armansito): This should cancel the connection attempt only if the
  // connection attempt isn't using the filter accept list.
  CancelInternal(true);
}
}  // namespace bt::hci
