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

#include <endian.h>
#include <zircon/assert.h>

#include "src/connectivity/bluetooth/core/bt-host/common/log.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/advertising_report_parser.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/hci.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/local_address_delegate.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/sequential_command_runner.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/transport.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/util.h"

namespace bt {

namespace hci {
namespace {

std::string ScanStateToString(LowEnergyScanner::State state) {
  switch (state) {
    case LowEnergyScanner::State::kIdle:
      return "(idle)";
    case LowEnergyScanner::State::kStopping:
      return "(stopping)";
    case LowEnergyScanner::State::kInitiating:
      return "(initiating)";
    case LowEnergyScanner::State::kActiveScanning:
      return "(active scanning)";
    case LowEnergyScanner::State::kPassiveScanning:
      return "(passive scanning)";
    default:
      break;
  }

  ZX_PANIC("invalid scanner state: %u", static_cast<unsigned int>(state));
  return "(unknown)";
}

}  // namespace

LegacyLowEnergyScanner::LegacyLowEnergyScanner(
    LocalAddressDelegate* local_addr_delegate, fxl::RefPtr<Transport> hci,
    async_dispatcher_t* dispatcher)
    : LowEnergyScanner(hci, dispatcher),
      local_addr_delegate_(local_addr_delegate) {
  ZX_DEBUG_ASSERT(local_addr_delegate_);
  event_handler_id_ = transport()->command_channel()->AddLEMetaEventHandler(
      kLEAdvertisingReportSubeventCode,
      fit::bind_member(this, &LegacyLowEnergyScanner::OnAdvertisingReportEvent),
      this->dispatcher());
  scan_timeout_task_.set_handler(
      fit::bind_member(this, &LegacyLowEnergyScanner::OnScanPeriodComplete));
}

LegacyLowEnergyScanner::~LegacyLowEnergyScanner() {
  transport()->command_channel()->RemoveEventHandler(event_handler_id_);
}

bool LegacyLowEnergyScanner::StartScan(bool active, uint16_t scan_interval,
                                       uint16_t scan_window,
                                       bool filter_duplicates,
                                       LEScanFilterPolicy filter_policy,
                                       zx::duration period,
                                       ScanStatusCallback callback) {
  ZX_DEBUG_ASSERT(thread_checker_.IsCreationThreadCurrent());
  ZX_DEBUG_ASSERT(callback);
  ZX_DEBUG_ASSERT(period == kPeriodInfinite || period.get() > 0);
  ZX_DEBUG_ASSERT(scan_interval <= kLEScanIntervalMax &&
                  scan_interval >= kLEScanIntervalMin);
  ZX_DEBUG_ASSERT(scan_window <= kLEScanIntervalMax &&
                  scan_window >= kLEScanIntervalMin);
  ZX_DEBUG_ASSERT(scan_window < scan_interval);

  if (state() != State::kIdle) {
    bt_log(ERROR, "hci-le", "cannot start scan while in state: %s",
           ScanStateToString(state()).c_str());
    return false;
  }

  ZX_DEBUG_ASSERT(!scan_cb_);
  ZX_DEBUG_ASSERT(!scan_timeout_task_.is_pending());
  ZX_DEBUG_ASSERT(hci_cmd_runner()->IsReady());
  ZX_DEBUG_ASSERT(pending_results_.empty());

  set_state(State::kInitiating);
  set_active_scan_requested(active);
  scan_cb_ = std::move(callback);

  // Obtain the local address type.
  local_addr_delegate_->EnsureLocalAddress(
      [this, active, scan_interval, scan_window, filter_duplicates,
       filter_policy, period,
       callback = std::move(callback)](const auto& address) mutable {
        StartScanInternal(address, active, scan_interval, scan_window,
                          filter_duplicates, filter_policy, period,
                          std::move(callback));
      });

  return true;
}

void LegacyLowEnergyScanner::StartScanInternal(
    const DeviceAddress& local_address, bool active, uint16_t scan_interval,
    uint16_t scan_window, bool filter_duplicates,
    LEScanFilterPolicy filter_policy, zx::duration period,
    ScanStatusCallback callback) {
  // Check if the scan request was canceled by StopScan() while we were waiting
  // for the local address.
  if (state() != State::kInitiating) {
    bt_log(TRACE, "hci-le",
           "scan request was canceled while obtaining local address");
    return;
  }

  bt_log(TRACE, "hci-le",
         "requesting scan (%s, address: %s, interval: %#.4x, window: %#.4x)",
         (active ? "active" : "passive"), local_address.ToString().c_str(),
         scan_interval, scan_window);

  // HCI_LE_Set_Scan_Parameters
  auto command = CommandPacket::New(kLESetScanParameters,
                                    sizeof(LESetScanParametersCommandParams));
  auto scan_params = command->mutable_view()
                         ->mutable_payload<LESetScanParametersCommandParams>();
  scan_params->scan_type = active ? LEScanType::kActive : LEScanType::kPassive;
  scan_params->scan_interval = htole16(scan_interval);
  scan_params->scan_window = htole16(scan_window);
  scan_params->filter_policy = filter_policy;

  if (local_address.type() == DeviceAddress::Type::kLERandom) {
    scan_params->own_address_type = LEOwnAddressType::kRandom;
  } else {
    scan_params->own_address_type = LEOwnAddressType::kPublic;
  }
  hci_cmd_runner()->QueueCommand(std::move(command));

  // HCI_LE_Set_Scan_Enable
  command = CommandPacket::New(kLESetScanEnable,
                               sizeof(LESetScanEnableCommandParams));
  auto enable_params =
      command->mutable_view()->mutable_payload<LESetScanEnableCommandParams>();
  enable_params->scanning_enabled = GenericEnableParam::kEnable;
  enable_params->filter_duplicates = filter_duplicates
                                         ? GenericEnableParam::kEnable
                                         : GenericEnableParam::kDisable;

  hci_cmd_runner()->QueueCommand(std::move(command));
  hci_cmd_runner()->RunCommands([this, period](Status status) {
    ZX_DEBUG_ASSERT(scan_cb_);
    ZX_DEBUG_ASSERT(state() == State::kInitiating);

    if (!status) {
      if (status.error() == HostError::kCanceled) {
        bt_log(TRACE, "hci-le", "scan canceled");
        return;
      }

      auto cb = std::move(scan_cb_);

      ZX_DEBUG_ASSERT(!scan_cb_);
      set_state(State::kIdle);

      bt_log(ERROR, "hci-le", "failed to start scan: %s",
             status.ToString().c_str());
      cb(ScanStatus::kFailed);
      return;
    }

    // Schedule the timeout.
    if (period != kPeriodInfinite) {
      scan_timeout_task_.PostDelayed(dispatcher(), period);
    }

    if (active_scan_requested()) {
      set_state(State::kActiveScanning);
      scan_cb_(ScanStatus::kActive);
    } else {
      set_state(State::kPassiveScanning);
      scan_cb_(ScanStatus::kPassive);
    }
  });
}

bool LegacyLowEnergyScanner::StopScan() {
  ZX_DEBUG_ASSERT(thread_checker_.IsCreationThreadCurrent());

  if (state() == State::kStopping || state() == State::kIdle) {
    bt_log(TRACE, "hci-le", "cannot stop scan while in state: %s",
           ScanStateToString(state()).c_str());
    return false;
  }

  // Scan is either being initiated or already running. Cancel any in-flight HCI
  // command sequence.
  if (!hci_cmd_runner()->IsReady())
    hci_cmd_runner()->Cancel();

  // We'll tell the controller to stop scanning even if it is not (this is OK
  // because the command will have no effect; see Core Spec v5.0, Vol 2, Part E,
  // Section 7.8.11, paragraph 4).
  StopScanInternal(true);

  return true;
}

void LegacyLowEnergyScanner::StopScanPeriodForTesting() {
  ZX_DEBUG_ASSERT(IsScanning());
  StopScanInternal(false);
}

void LegacyLowEnergyScanner::StopScanInternal(bool stopped) {
  ZX_DEBUG_ASSERT(scan_cb_);

  scan_timeout_task_.Cancel();
  set_state(State::kStopping);

  // Notify any pending scan results unless the scan was terminated by the user.
  if (!stopped) {
    for (auto& result : pending_results_) {
      auto& pending = result.second;
      NotifyPeerFound(pending.result,
                      pending.data.view(0, pending.adv_data_len));
    }
  }

  // Either way clear all results from the previous scan period.
  pending_results_.clear();

  ZX_DEBUG_ASSERT(hci_cmd_runner()->IsReady());

  // Tell the controller to stop scanning.
  auto command = CommandPacket::New(kLESetScanEnable,
                                    sizeof(LESetScanEnableCommandParams));
  auto enable_params =
      command->mutable_view()->mutable_payload<LESetScanEnableCommandParams>();
  enable_params->scanning_enabled = GenericEnableParam::kDisable;
  enable_params->filter_duplicates = GenericEnableParam::kDisable;

  hci_cmd_runner()->QueueCommand(std::move(command));
  hci_cmd_runner()->RunCommands([this, stopped](Status status) {
    ZX_DEBUG_ASSERT(scan_cb_);
    ZX_DEBUG_ASSERT(state() == State::kStopping);

    if (!status) {
      bt_log(WARN, "hci-le", "failed to stop scan: %s",
             status.ToString().c_str());
      // Something went wrong but there isn't really a meaningful way to
      // recover, so we just fall through and notify the caller with
      // ScanStatus::kFailed instead.
    }

    auto cb = std::move(scan_cb_);
    set_state(State::kIdle);

    cb(!status ? ScanStatus::kFailed
               : (stopped ? ScanStatus::kStopped : ScanStatus::kComplete));
  });
}

void LegacyLowEnergyScanner::OnAdvertisingReportEvent(
    const EventPacket& event) {
  bt_log(DEBUG, "hci-le", "received advertising report");

  // Drop the event if not requested to scan.
  if (!IsScanning())
    return;

  AdvertisingReportParser parser(event);
  const LEAdvertisingReportData* report;
  int8_t rssi;
  while (parser.GetNextReport(&report, &rssi)) {
    bool needs_scan_rsp = false;
    bool connectable = false;
    bool directed = false;
    switch (report->event_type) {
      case LEAdvertisingEventType::kAdvDirectInd:
        directed = true;
        break;
      case LEAdvertisingEventType::kAdvInd:
        connectable = true;
        __FALLTHROUGH;
      case LEAdvertisingEventType::kAdvScanInd:
        if (IsActiveScanning()) {
          needs_scan_rsp = true;
        }
        break;
      case LEAdvertisingEventType::kScanRsp:
        if (IsActiveScanning()) {
          HandleScanResponse(*report, rssi);
        }
        continue;
      default:
        break;
    }

    if (report->length_data > kMaxLEAdvertisingDataLength) {
      bt_log(WARN, "hci-le", "advertising data too long! Ignoring");
      continue;
    }

    DeviceAddress address;
    bool resolved;
    if (!DeviceAddressFromAdvReport(*report, &address, &resolved))
      continue;

    LowEnergyScanResult result(address, resolved, connectable, rssi);
    if (directed) {
      delegate()->OnDirectedAdvertisement(result);
      continue;
    }

    if (!needs_scan_rsp) {
      NotifyPeerFound(result, BufferView(report->data, report->length_data));
      continue;
    }

    auto iter = pending_results_.emplace(address, PendingScanResult()).first;
    auto& pending = iter->second;

    // We overwrite the pending result entry with the most recent report, even
    // if one from this peer was already pending.
    pending.result = result;
    pending.adv_data_len = report->length_data;
    pending.data.Write(report->data, report->length_data);
  }
}

void LegacyLowEnergyScanner::HandleScanResponse(
    const LEAdvertisingReportData& report, int8_t rssi) {
  DeviceAddress address;
  bool resolved;
  if (!DeviceAddressFromAdvReport(report, &address, &resolved))
    return;

  auto iter = pending_results_.find(address);
  if (iter == pending_results_.end()) {
    bt_log(TRACE, "hci-le", "dropping unmatched scan response");
    return;
  }

  if (report.length_data > kMaxLEAdvertisingDataLength) {
    bt_log(WARN, "hci-le", "scan response too long! Ignoring");
    return;
  }
  auto& pending = iter->second;
  ZX_DEBUG_ASSERT(address == pending.result.address);

  // Update the result.
  pending.result.resolved = resolved;
  pending.result.rssi = rssi;

  // Append the scan response to the pending advertising data.
  pending.data.Write(report.data, report.length_data, pending.adv_data_len);

  NotifyPeerFound(pending.result, pending.data.view(0, pending.adv_data_len +
                                                           report.length_data));
  pending_results_.erase(iter);
}

void LegacyLowEnergyScanner::NotifyPeerFound(const LowEnergyScanResult& result,
                                             const ByteBuffer& data) {
  delegate()->OnPeerFound(result, data);
}

void LegacyLowEnergyScanner::OnScanPeriodComplete() {
  if (IsScanning()) {
    StopScanInternal(false);
  }
}

}  // namespace hci
}  // namespace bt
