//
//  Copyright (C) 2016 The Android Open Source Project
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at:
//
//  http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//

#include "service/low_energy_scanner.h"

#include <base/bind.h>
#include <base/logging.h>

#include "service/adapter.h"
#include "service/common/bluetooth/util/address_helper.h"
#include "service/logging_helpers.h"
#include "stack/include/bt_types.h"
#include "stack/include/hcidefs.h"

using std::lock_guard;
using std::mutex;

namespace bluetooth {

namespace {

// 31 + 31 for advertising data and scan response. This is the maximum length
// TODO(armansito): Fix the HAL to return a concatenated blob that contains the
// true length of each field and also provide a length parameter so that we
// can support advertising length extensions in the future.
const size_t kScanRecordLength = 62;

// Returns the length of the given scan record array. We have to calculate this
// based on the maximum possible data length and the TLV data. See TODO above
// |kScanRecordLength|.
size_t GetScanRecordLength(std::vector<uint8_t> bytes) {
  for (size_t i = 0, field_len = 0; i < kScanRecordLength;
       i += (field_len + 1)) {
    field_len = bytes[i];

    // Assert here that the data returned from the stack is correctly formatted
    // in TLV form and that the length of the current field won't exceed the
    // total data length.
    CHECK(i + field_len < kScanRecordLength);

    // If the field length is zero and we haven't reached the maximum length,
    // then we have found the length, as the stack will pad the data with zeros
    // accordingly.
    if (field_len == 0) return i;
  }

  // We have reached the end.
  return kScanRecordLength;
}

}  // namespace

// LowEnergyScanner implementation
// ========================================================

LowEnergyScanner::LowEnergyScanner(Adapter& adapter, const UUID& uuid,
                                   int scanner_id)
    : adapter_(adapter),
      app_identifier_(uuid),
      scanner_id_(scanner_id),
      scan_started_(false),
      delegate_(nullptr) {}

LowEnergyScanner::~LowEnergyScanner() {
  // Automatically unregister the scanner.
  VLOG(1) << "LowEnergyScanner unregistering scanner: " << scanner_id_;

  // Unregister as observer so we no longer receive any callbacks.
  hal::BluetoothGattInterface::Get()->RemoveScannerObserver(this);

  hal::BluetoothGattInterface::Get()->GetScannerHALInterface()->Unregister(
      scanner_id_);

  // Stop any scans started by this client.
  if (scan_started_.load()) StopScan();
}

void LowEnergyScanner::SetDelegate(Delegate* delegate) {
  lock_guard<mutex> lock(delegate_mutex_);
  delegate_ = delegate;
}

bool LowEnergyScanner::StartScan(const ScanSettings& settings,
                                 const std::vector<ScanFilter>& filters) {
  VLOG(2) << __func__;

  // Cannot start a scan if the adapter is not enabled.
  if (!adapter_.IsEnabled()) {
    LOG(ERROR) << "Cannot scan while Bluetooth is disabled";
    return false;
  }

  // TODO(jpawlowski): Push settings and filtering logic below the HAL.
  bt_status_t status =
      hal::BluetoothGattInterface::Get()->StartScan(scanner_id_);
  if (status != BT_STATUS_SUCCESS) {
    LOG(ERROR) << "Failed to initiate scanning for client: " << scanner_id_;
    return false;
  }

  scan_started_ = true;
  return true;
}

bool LowEnergyScanner::StopScan() {
  VLOG(2) << __func__;

  // TODO(armansito): We don't support batch scanning yet so call
  // StopRegularScanForClient directly. In the future we will need to
  // conditionally call a batch scan API here.
  bt_status_t status =
      hal::BluetoothGattInterface::Get()->StopScan(scanner_id_);
  if (status != BT_STATUS_SUCCESS) {
    LOG(ERROR) << "Failed to stop scan for client: " << scanner_id_;
    return false;
  }

  scan_started_ = false;
  return true;
}

const UUID& LowEnergyScanner::GetAppIdentifier() const {
  return app_identifier_;
}

int LowEnergyScanner::GetInstanceId() const { return scanner_id_; }

void LowEnergyScanner::ScanResultCallback(
    hal::BluetoothGattInterface* gatt_iface, const bt_bdaddr_t& bda, int rssi,
    std::vector<uint8_t> adv_data) {
  // Ignore scan results if this client didn't start a scan.
  if (!scan_started_.load()) return;

  lock_guard<mutex> lock(delegate_mutex_);
  if (!delegate_) return;

  // TODO(armansito): Apply software filters here.

  size_t record_len = GetScanRecordLength(adv_data);
  std::vector<uint8_t> scan_record(adv_data.begin(),
                                   adv_data.begin() + record_len);

  ScanResult result(BtAddrString(&bda), scan_record, rssi);

  delegate_->OnScanResult(this, result);
}

// LowEnergyScannerFactory implementation
// ========================================================

LowEnergyScannerFactory::LowEnergyScannerFactory(Adapter& adapter)
    : adapter_(adapter) {
  hal::BluetoothGattInterface::Get()->AddScannerObserver(this);
}

LowEnergyScannerFactory::~LowEnergyScannerFactory() {
  hal::BluetoothGattInterface::Get()->RemoveScannerObserver(this);
}

bool LowEnergyScannerFactory::RegisterInstance(
    const UUID& uuid, const RegisterCallback& callback) {
  VLOG(1) << __func__ << " - UUID: " << uuid.ToString();
  lock_guard<mutex> lock(pending_calls_lock_);

  if (pending_calls_.find(uuid) != pending_calls_.end()) {
    LOG(ERROR) << "Low-Energy scanner with given UUID already registered - "
               << "UUID: " << uuid.ToString();
    return false;
  }

  BleScannerInterface* hal_iface =
      hal::BluetoothGattInterface::Get()->GetScannerHALInterface();

  hal_iface->RegisterScanner(
      base::Bind(&LowEnergyScannerFactory::RegisterScannerCallback,
                 base::Unretained(this), callback, uuid));

  pending_calls_.insert(uuid);

  return true;
}

void LowEnergyScannerFactory::RegisterScannerCallback(
    const RegisterCallback& callback, const UUID& app_uuid, uint8_t scanner_id,
    uint8_t status) {
  UUID uuid(app_uuid);

  VLOG(1) << __func__ << " - UUID: " << uuid.ToString();
  lock_guard<mutex> lock(pending_calls_lock_);

  auto iter = pending_calls_.find(uuid);
  if (iter == pending_calls_.end()) {
    VLOG(1) << "Ignoring callback for unknown app_id: " << uuid.ToString();
    return;
  }

  // No need to construct a scanner if the call wasn't successful.
  std::unique_ptr<LowEnergyScanner> scanner;
  BLEStatus result = BLE_STATUS_FAILURE;
  if (status == BT_STATUS_SUCCESS) {
    scanner.reset(new LowEnergyScanner(adapter_, uuid, scanner_id));

    hal::BluetoothGattInterface::Get()->AddScannerObserver(scanner.get());

    result = BLE_STATUS_SUCCESS;
  }

  // Notify the result via the result callback.
  callback(result, app_uuid, std::move(scanner));

  pending_calls_.erase(iter);
}

}  // namespace bluetooth
