// Copyright 2019 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 "bredr_connection_request.h"

#include "src/connectivity/bluetooth/core/bt-host/common/identifier.h"
#include "src/connectivity/bluetooth/core/bt-host/common/log.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/connection.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/defaults.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/hci.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/status.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/util.h"

namespace bt {
namespace hci {

std::unique_ptr<CommandPacket> CreateConnectionPacket(
    DeviceAddress address, std::optional<PageScanRepetitionMode> page_scan_repetition_mode,
    std::optional<uint16_t> clock_offset) {
  auto request = CommandPacket::New(kCreateConnection, sizeof(CreateConnectionCommandParams));
  auto params = request->mutable_payload<CreateConnectionCommandParams>();

  params->bd_addr = address.value();
  params->packet_type = htole16(kEnableAllPacketTypes);

  // The Page Scan Repetition Mode of the remote device as retrieved by Inquiry.
  // If we do not have one for the device, opt for R2 so we will send for at
  // least 2.56s
  if (page_scan_repetition_mode)
    params->page_scan_repetition_mode = *page_scan_repetition_mode;
  else
    params->page_scan_repetition_mode = PageScanRepetitionMode::kR2;  // Every 2.56 seconds

  params->reserved = 0;  // Reserved, must be set to 0.

  // Clock Offset.  The lower 15 bits are set to the clock offset as retrieved
  // by an Inquiry. The highest bit is set to 1 if the rest of this parameter
  // is valid. If we don't have one, use the default.
  if (clock_offset)
    params->clock_offset = htole16(*clock_offset);
  else
    params->clock_offset = 0x0000;

  params->allow_role_switch =
      static_cast<uint8_t>(RoleSwitchBits::kDisallowRoleSwitch);  // Do not allow role switch

  return request;
}

void BrEdrConnectionRequest::CreateConnection(
    CommandChannel* command_channel, async_dispatcher_t* dispatcher,
    std::optional<uint16_t> clock_offset,
    std::optional<PageScanRepetitionMode> page_scan_repetition_mode, zx::duration timeout,
    OnCompleteDelegate on_command_fail) {
  ZX_DEBUG_ASSERT(timeout > zx::msec(0));

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

    if (!self)
      return;

    Status status = event.ToStatus();
    if (!status) {
      on_command_fail(status, peer_id);
    } else {
      // 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 BrEdr Connection Complete event.
      self->timeout_task_.PostDelayed(async_get_default_dispatcher(), timeout);
    }
  };

  auto packet = CreateConnectionPacket(peer_address_, page_scan_repetition_mode, clock_offset);

  command_channel->SendCommand(std::move(packet), dispatcher, std::move(complete_cb),
                               kCommandStatusEventCode);
}

// Status is either a Success or an Error value
Status BrEdrConnectionRequest::CompleteRequest(Status status) {
  bt_log(TRACE, "hci-bredr", "connection complete - status: %s", bt_str(status));
  timeout_task_.Cancel();

  if (!status.is_success()) {
    if (state_ == RequestState::kTimedOut) {
      status = Status(HostError::kTimedOut);
    } else if (status.protocol_error() == StatusCode::kUnknownConnectionId) {
      // The "Unknown Connection Identifier" error code is returned if this
      // event was sent due to a successful cancellation via the
      // HCI_Create_Connection_Cancel command
      // See Core Spec v5.0 Vol 2, Part E, Section 7.1.7
      status = Status(HostError::kCanceled);
    }
  }
  return status;
}

void BrEdrConnectionRequest::Timeout() {
  // If the request was cancelled, this handler will have been removed
  ZX_ASSERT(state_ == RequestState::kPending);
  bt_log(INFO, "hci-bredr", "create connection timed out: canceling request");
  state_ = RequestState::kTimedOut;
  timeout_task_.Cancel();
}

bool BrEdrConnectionRequest::Cancel() {
  if (!(state_ == RequestState::kPending)) {
    bt_log(WARN, "hci-bredr", "connection attempt already canceled!");
    return false;
  }
  state_ = RequestState::kCanceled;
  timeout_task_.Cancel();
  return true;
}

BrEdrConnectionRequest::~BrEdrConnectionRequest() { Cancel(); }

}  // namespace hci
}  // namespace bt
