// 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::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);
}

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;
}

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::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";
  }
}

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);
}

}  // namespace bluetooth
