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

#include <endian.h>
#include <lib/async/default.h>
#include <zircon/assert.h>

#include "src/connectivity/bluetooth/core/bt-host/common/log.h"
#include "src/connectivity/bluetooth/core/bt-host/hci-spec/defaults.h"
#include "src/connectivity/bluetooth/core/bt-host/hci-spec/protocol.h"
#include "src/connectivity/bluetooth/core/bt-host/hci-spec/util.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/local_address_delegate.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/transport.h"

namespace bt::hci {

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

LowEnergyConnector::LowEnergyConnector(fxl::WeakPtr<Transport> hci,
                                       LocalAddressDelegate* local_addr_delegate,
                                       async_dispatcher_t* dispatcher,
                                       IncomingConnectionDelegate delegate)
    : dispatcher_(dispatcher),
      hci_(hci),
      local_addr_delegate_(local_addr_delegate),
      delegate_(std::move(delegate)),
      weak_ptr_factory_(this) {
  ZX_DEBUG_ASSERT(dispatcher_);
  ZX_DEBUG_ASSERT(hci_);
  ZX_DEBUG_ASSERT(local_addr_delegate_);
  ZX_DEBUG_ASSERT(delegate_);

  auto self = weak_ptr_factory_.GetWeakPtr();
  event_handler_id_ = hci_->command_channel()->AddLEMetaEventHandler(
      kLEConnectionCompleteSubeventCode, [self](const auto& event) {
        if (self) {
          return self->OnConnectionCompleteEvent(event);
        }
        return CommandChannel::EventCallbackResult::kRemove;
      });
}

LowEnergyConnector::~LowEnergyConnector() {
  hci_->command_channel()->RemoveEventHandler(event_handler_id_);
  if (request_pending())
    Cancel();
}

bool LowEnergyConnector::CreateConnection(bool use_whitelist, const DeviceAddress& peer_address,
                                          uint16_t scan_interval, uint16_t scan_window,
                                          const LEPreferredConnectionParameters& initial_parameters,
                                          StatusCallback status_callback, zx::duration timeout) {
  ZX_DEBUG_ASSERT(thread_checker_.is_thread_valid());
  ZX_DEBUG_ASSERT(status_callback);
  ZX_DEBUG_ASSERT(timeout.get() > 0);

  if (request_pending())
    return false;

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

  local_addr_delegate_->EnsureLocalAddress(
      [this, use_whitelist, peer_address, scan_interval, scan_window, initial_parameters,
       callback = std::move(status_callback), timeout](const auto& address) mutable {
        // Use the identity address if privacy override was enabled.
        CreateConnectionInternal(
            use_local_identity_address_ ? local_addr_delegate_->identity_address() : address,
            use_whitelist, peer_address, scan_interval, scan_window, initial_parameters,
            std::move(callback), timeout);
      });

  return true;
}

void LowEnergyConnector::CreateConnectionInternal(
    const DeviceAddress& local_address, bool use_whitelist, const DeviceAddress& peer_address,
    uint16_t scan_interval, uint16_t scan_window,
    const LEPreferredConnectionParameters& initial_parameters, StatusCallback status_callback,
    zx::duration timeout) {
  // 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;
  }

  ZX_DEBUG_ASSERT(!pending_request_->initiating);

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

  auto request = CommandPacket::New(kLECreateConnection, sizeof(LECreateConnectionCommandParams));
  auto params = request->mutable_payload<LECreateConnectionCommandParams>();
  params->scan_interval = htole16(scan_interval);
  params->scan_window = htole16(scan_window);
  params->initiator_filter_policy =
      use_whitelist ? GenericEnableParam::kEnable : GenericEnableParam::kDisable;

  // TODO(armansito): Use the resolved address types for <5.0 LE Privacy.
  params->peer_address_type =
      peer_address.IsPublic() ? LEAddressType::kPublic : LEAddressType::kRandom;
  params->peer_address = peer_address.value();

  params->own_address_type =
      local_address.IsPublic() ? LEOwnAddressType::kPublic : LEOwnAddressType::kRandom;

  params->conn_interval_min = htole16(initial_parameters.min_interval());
  params->conn_interval_max = htole16(initial_parameters.max_interval());
  params->conn_latency = htole16(initial_parameters.max_latency());
  params->supervision_timeout = htole16(initial_parameters.supervision_timeout());
  params->minimum_ce_length = 0x0000;
  params->maximum_ce_length = 0x0000;

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

    if (!self)
      return;

    Status status = event.ToStatus();
    if (!status) {
      self->OnCreateConnectionComplete(Status(status), 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_.PostDelayed(async_get_default_dispatcher(), timeout);
  };

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

void LowEnergyConnector::Cancel() { CancelInternal(false); }

void LowEnergyConnector::CancelInternal(bool timed_out) {
  ZX_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) {
    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 = CommandPacket::New(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(Status(HostError::kCanceled), nullptr);
}

CommandChannel::EventCallbackResult LowEnergyConnector::OnConnectionCompleteEvent(
    const EventPacket& event) {
  ZX_DEBUG_ASSERT(event.event_code() == kLEMetaEventCode);
  ZX_DEBUG_ASSERT(event.params<LEMetaEventParams>().subevent_code ==
                  kLEConnectionCompleteSubeventCode);

  auto params = event.le_event_params<LEConnectionCompleteSubeventParams>();
  ZX_ASSERT(params);

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

  Status status(params->status);
  if (!status) {
    if (matches_pending_request) {
      // 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) {
        status = Status(HostError::kTimedOut);
      } else if (params->status == StatusCode::kUnknownConnectionId) {
        status = Status(HostError::kCanceled);
      }
      OnCreateConnectionComplete(status, nullptr);
    } else {
      bt_log(WARN, "hci-le", "unexpected connection complete event with error received: %s",
             status.ToString().c_str());
    }
    return CommandChannel::EventCallbackResult::kContinue;
  }

  ConnectionHandle handle = le16toh(params->connection_handle);
  Connection::Role role = (params->role == ConnectionRole::kMaster) ? Connection::Role::kMaster
                                                                    : Connection::Role::kSlave;
  DeviceAddress peer_address(AddressTypeFromHCI(params->peer_address_type), params->peer_address);
  LEConnectionParameters connection_params(le16toh(params->conn_interval),
                                           le16toh(params->conn_latency),
                                           le16toh(params->supervision_timeout));

  // 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 CommandChannel::EventCallbackResult::kContinue;
  }

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

  if (pending_request_->timed_out) {
    status = Status(HostError::kTimedOut);
  } else if (pending_request_->canceled) {
    status = Status(HostError::kCanceled);
  } else {
    status = Status();
  }

  // If we were requested to cancel the connection after the logical link
  // is created we disconnect it.
  if (!status) {
    connection = nullptr;
  }
  OnCreateConnectionComplete(status, std::move(connection));
  return CommandChannel::EventCallbackResult::kContinue;
}

void LowEnergyConnector::OnCreateConnectionComplete(Status status, ConnectionPtr link) {
  ZX_DEBUG_ASSERT(pending_request_);

  bt_log(DEBUG, "hci-le", "connection complete - status: %s", status.ToString().c_str());

  request_timeout_task_.Cancel();

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

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

void LowEnergyConnector::OnCreateConnectionTimeout() {
  ZX_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 white list.
  CancelInternal(true);
}

}  // namespace bt::hci
