// Copyright 2018 The Chromium OS 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 "bluetooth/newblued/newblue.h"

#include <newblue/sm.h>

#include <algorithm>
#include <memory>
#include <utility>
#include <vector>

#include <base/bind.h>
#include <base/message_loop/message_loop.h>
#include <base/strings/stringprintf.h>
#include <chromeos/dbus/service_constants.h>

#include "bluetooth/common/util.h"

namespace bluetooth {

namespace {

// Converts the uint8_t[6] MAC address into std::string form, e.g.
// {0x05, 0x04, 0x03, 0x02, 0x01, 0x00} will be 00:01:02:03:04:05.
std::string ConvertBtAddrToString(const struct bt_addr& addr) {
  return base::StringPrintf("%02X:%02X:%02X:%02X:%02X:%02X", addr.addr[5],
                            addr.addr[4], addr.addr[3], addr.addr[2],
                            addr.addr[1], addr.addr[0]);
}

}  // namespace

Newblue::Newblue(std::unique_ptr<LibNewblue> libnewblue)
    : libnewblue_(std::move(libnewblue)), weak_ptr_factory_(this) {}

base::WeakPtr<Newblue> Newblue::GetWeakPtr() {
  return weak_ptr_factory_.GetWeakPtr();
}

bool Newblue::Init() {
  if (base::MessageLoop::current())
    origin_task_runner_ = base::MessageLoop::current()->task_runner();
  return true;
}

void Newblue::RegisterPairingAgent(PairingAgent* pairing_agent) {
  pairing_agent_ = pairing_agent;
}

void Newblue::UnregisterPairingAgent() {
  pairing_agent_ = nullptr;
}

bool Newblue::ListenReadyForUp(base::Closure callback) {
  // Dummy MAC address. NewBlue doesn't actually use the MAC address as it's
  // exclusively controlled by BlueZ.
  static const uint8_t kZeroMac[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

  if (!libnewblue_->HciUp(kZeroMac, &Newblue::OnStackReadyForUpThunk, this))
    return false;

  ready_for_up_callback_ = callback;
  return true;
}

bool Newblue::BringUp() {
  if (!libnewblue_->HciIsUp()) {
    LOG(ERROR) << "HCI is not ready for up";
    return false;
  }

  if (libnewblue_->L2cInit()) {
    LOG(ERROR) << "Failed to initialize L2CAP";
    return false;
  }

  if (!libnewblue_->AttInit()) {
    LOG(ERROR) << "Failed to initialize ATT";
    return false;
  }

  if (!libnewblue_->GattProfileInit()) {
    LOG(ERROR) << "Failed to initialize GATT";
    return false;
  }

  if (!libnewblue_->GattBuiltinInit()) {
    LOG(ERROR) << "Failed to initialize GATT services";
    return false;
  }

  if (!libnewblue_->SmInit()) {
    LOG(ERROR) << "Failed to init SM";
    return false;
  }

  // Always register passkey display observer, assuming that our UI always
  // supports this.
  // TODO(sonnysasaka): We may optimize this by registering passkey display
  // observer only if there is currently a default agent registered.
  passkey_display_observer_id_ = libnewblue_->SmRegisterPasskeyDisplayObserver(
      this, &Newblue::PasskeyDisplayObserverCallbackThunk);

  pair_state_handle_ = libnewblue_->SmRegisterPairStateObserver(
      this, &Newblue::PairStateCallbackThunk);
  if (!pair_state_handle_) {
    LOG(ERROR) << "Failed to register as an observer of pairing state";
    return false;
  }

  return true;
}

bool Newblue::StartDiscovery(DeviceDiscoveredCallback callback) {
  if (discovery_handle_ != 0) {
    LOG(WARNING) << "Discovery is already started, ignoring request";
    return false;
  }

  discovery_handle_ = libnewblue_->HciDiscoverLeStart(
      &Newblue::DiscoveryCallbackThunk, this, true /* active */,
      false /* use_random_addr */);
  if (discovery_handle_ == 0) {
    LOG(ERROR) << "Failed to start LE discovery";
    return false;
  }

  device_discovered_callback_ = callback;
  return true;
}

bool Newblue::StopDiscovery() {
  if (discovery_handle_ == 0) {
    LOG(WARNING) << "Discovery is not started, ignoring request";
    return false;
  }

  bool ret = libnewblue_->HciDiscoverLeStop(discovery_handle_);
  if (!ret) {
    LOG(ERROR) << "Failed to stop LE discovery";
    return false;
  }

  device_discovered_callback_.Reset();
  discovery_handle_ = 0;
  return true;
}

UniqueId Newblue::RegisterAsPairObserver(PairStateChangedCallback callback) {
  UniqueId observer_id = GetNextId();
  if (observer_id != kInvalidUniqueId)
    pair_observers_.emplace(observer_id, callback);
  return observer_id;
}

void Newblue::UnregisterAsPairObserver(UniqueId observer_id) {
  pair_observers_.erase(observer_id);
}

bool Newblue::Pair(const std::string& device_address,
                   bool is_random_address,
                   smPairSecurityRequirements security_requirement) {
  struct bt_addr address;
  if (!ConvertToBtAddr(is_random_address, device_address, &address))
    return false;

  libnewblue_->SmPair(&address, &security_requirement);
  return true;
}

bool Newblue::CancelPair(const std::string& device_address,
                         bool is_random_address) {
  struct bt_addr address;
  if (!ConvertToBtAddr(is_random_address, device_address, &address))
    return false;

  libnewblue_->SmUnpair(&address);
  return true;
}

std::vector<KnownDevice> Newblue::GetKnownDevices() {
  struct smKnownDevNode* head = libnewblue_->SmGetKnownDevices();
  struct smKnownDevNode* node = head;
  std::vector<KnownDevice> devices;

  while (node) {
    KnownDevice device;
    device.address = ConvertBtAddrToString(node->addr);
    device.address_type = node->addr.type;
    device.is_paired = node->isPaired;
    if (node->name)
      device.name = std::string(node->name);
    devices.push_back(device);
    node = node->next;
  }

  libnewblue_->SmKnownDevicesFree(head);
  return devices;
}

/*** Private Methods ***/

bool Newblue::PostTask(const tracked_objects::Location& from_here,
                       const base::Closure& task) {
  CHECK(origin_task_runner_.get());
  return origin_task_runner_->PostTask(from_here, task);
}

void Newblue::OnStackReadyForUpThunk(void* data) {
  Newblue* newblue = static_cast<Newblue*>(data);
  newblue->PostTask(FROM_HERE, base::Bind(&Newblue::OnStackReadyForUp,
                                          newblue->GetWeakPtr()));
}

void Newblue::OnStackReadyForUp() {
  if (ready_for_up_callback_.is_null()) {
    // libnewblue says it's ready for up but I don't have any callback. Most
    // probably another stack (e.g. BlueZ) just re-initialized the adapter.
    LOG(WARNING) << "No callback when stack is ready for up";
    return;
  }

  ready_for_up_callback_.Run();
  // It only makes sense to bring up the stack once and for all. Reset the
  // callback here so we won't bring up the stack twice.
  ready_for_up_callback_.Reset();
}

void Newblue::DiscoveryCallbackThunk(void* data,
                                     const struct bt_addr* addr,
                                     int8_t rssi,
                                     uint8_t reply_type,
                                     const void* eir,
                                     uint8_t eir_len) {
  Newblue* newblue = static_cast<Newblue*>(data);
  std::vector<uint8_t> eir_vector(static_cast<const uint8_t*>(eir),
                                  static_cast<const uint8_t*>(eir) + eir_len);
  std::string address = ConvertBtAddrToString(*addr);
  newblue->PostTask(
      FROM_HERE, base::Bind(&Newblue::DiscoveryCallback, newblue->GetWeakPtr(),
                            address, addr->type, rssi, reply_type, eir_vector));
}

void Newblue::DiscoveryCallback(const std::string& address,
                                uint8_t address_type,
                                int8_t rssi,
                                uint8_t reply_type,
                                const std::vector<uint8_t>& eir) {
  VLOG(1) << __func__;

  if (device_discovered_callback_.is_null()) {
    LOG(WARNING) << "DiscoveryCallback called when not discovering";
    return;
  }

  device_discovered_callback_.Run(address, address_type, rssi, reply_type, eir);
}

void Newblue::PairStateCallbackThunk(void* data,
                                     const void* pair_state_change,
                                     uniq_t observer_id) {
  CHECK(data && pair_state_change);

  Newblue* newblue = static_cast<Newblue*>(data);
  const smPairStateChange* change =
      static_cast<const smPairStateChange*>(pair_state_change);

  newblue->PostTask(
      FROM_HERE, base::Bind(&Newblue::PairStateCallback, newblue->GetWeakPtr(),
                            *change, observer_id));
}

void Newblue::PairStateCallback(const smPairStateChange& change,
                                uniq_t observer_id) {
  VLOG(1) << __func__;

  CHECK_EQ(observer_id, pair_state_handle_);

  std::string address = ConvertBtAddrToString(change.peerAddr);
  PairState state = static_cast<PairState>(change.pairState);
  PairError error = static_cast<PairError>(change.pairErr);

  // Notify |pair_observers|.
  for (const auto& observer : pair_observers_)
    observer.second.Run(address, state, error);
}

void Newblue::PasskeyDisplayObserverCallbackThunk(
    void* data,
    const struct smPasskeyDisplay* passkey_display,
    uniq_t observer_id) {
  if (!passkey_display) {
    LOG(WARNING) << "passkey display is not given";
    return;
  }

  Newblue* newblue = static_cast<Newblue*>(data);
  newblue->PostTask(
      FROM_HERE,
      base::Bind(&Newblue::PasskeyDisplayObserverCallback,
                 newblue->GetWeakPtr(), *passkey_display, observer_id));
}

void Newblue::PasskeyDisplayObserverCallback(
    struct smPasskeyDisplay passkey_display, uniq_t observer_id) {
  if (observer_id != passkey_display_observer_id_) {
    LOG(WARNING) << "passkey display observer id mismatch";
    return;
  }

  if (passkey_display.valid) {
    CHECK(pairing_agent_);
    pairing_agent_->DisplayPasskey(
        ConvertBtAddrToString(passkey_display.peerAddr),
        passkey_display.passkey);
  } else {
    VLOG(1) << "The passkey session expired with the device";
  }
}

}  // namespace bluetooth
