//
//  Copyright (C) 2015 Google, Inc.
//
//  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/hal/bluetooth_interface.h"

#include <mutex>
#include <shared_mutex>

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

#include "service/logging_helpers.h"

#include "btcore/include/hal_util.h"

using std::lock_guard;
using std::unique_lock;
using std::shared_lock;
using std::mutex;
#if defined(OS_GENERIC) && defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION < 3500)
using shared_mutex_impl = std::shared_mutex;
#else
using shared_mutex_impl = std::shared_timed_mutex;
#endif

namespace bluetooth {
namespace hal {

namespace {

// The global BluetoothInterface instance.
BluetoothInterface* g_bluetooth_interface = nullptr;

// Mutex used by callbacks to access |g_interface|. If we initialize or clean it
// use unique_lock. If only accessing |g_interface| use shared lock.
// TODO(jpawlowski): this should be just shared_mutex, as we currently don't use
// timed methods. Change to shared_mutex when we upgrade to C++14
shared_mutex_impl g_instance_lock;

// Helper for obtaining the observer list. This is forward declared here and
// defined below since it depends on BluetoothInterfaceImpl.
base::ObserverList<BluetoothInterface::Observer>* GetObservers();

#define FOR_EACH_BLUETOOTH_OBSERVER(func) \
  FOR_EACH_OBSERVER(BluetoothInterface::Observer, *GetObservers(), func)

#define VERIFY_INTERFACE_OR_RETURN()                                   \
  do {                                                                 \
    if (!g_bluetooth_interface) {                                      \
      LOG(WARNING) << "Callback received while |g_interface| is NULL"; \
      return;                                                          \
    }                                                                  \
  } while (0)

void AdapterStateChangedCallback(bt_state_t state) {
  shared_lock<shared_mutex_impl> lock(g_instance_lock);
  VERIFY_INTERFACE_OR_RETURN();
  VLOG(1) << "Adapter state changed: " << BtStateText(state);
  FOR_EACH_BLUETOOTH_OBSERVER(AdapterStateChangedCallback(state));
}

void AdapterPropertiesCallback(bt_status_t status, int num_properties,
                               bt_property_t* properties) {
  shared_lock<shared_mutex_impl> lock(g_instance_lock);
  VERIFY_INTERFACE_OR_RETURN();
  VLOG(1) << "Adapter properties changed - status: " << BtStatusText(status)
          << ", num_properties: " << num_properties;
  FOR_EACH_BLUETOOTH_OBSERVER(
      AdapterPropertiesCallback(status, num_properties, properties));
}

void RemoteDevicePropertiesCallback(bt_status_t status,
                                    RawAddress* remote_bd_addr,
                                    int num_properties,
                                    bt_property_t* properties) {
  shared_lock<shared_mutex_impl> lock(g_instance_lock);
  VERIFY_INTERFACE_OR_RETURN();
  VLOG(1) << " Remote device properties changed - status: "
          << BtStatusText(status)
          << " - BD_ADDR: " << BtAddrString(remote_bd_addr)
          << ", num_properties: " << num_properties;
  FOR_EACH_BLUETOOTH_OBSERVER(RemoteDevicePropertiesCallback(
      status, remote_bd_addr, num_properties, properties));
}

void DiscoveryStateChangedCallback(bt_discovery_state_t state) {
  shared_lock<shared_mutex_impl> lock(g_instance_lock);
  VERIFY_INTERFACE_OR_RETURN();
  VLOG(1) << "Discovery state changed - state: " << BtDiscoveryStateText(state);
  FOR_EACH_BLUETOOTH_OBSERVER(DiscoveryStateChangedCallback(state));
}

void PinRequestCallback(RawAddress* remote_bd_addr, bt_bdname_t* bd_name,
                        uint32_t cod, bool min_16_digit) {
  shared_lock<shared_mutex_impl> lock(g_instance_lock);
  VERIFY_INTERFACE_OR_RETURN();
  VLOG(2) << __func__ << " - remote_bd_addr: " << remote_bd_addr
          << " - bd_name: " << bd_name << " - cod: " << cod
          << " - min_16_digit: " << min_16_digit;
  FOR_EACH_BLUETOOTH_OBSERVER(
      PinRequestCallback(remote_bd_addr, bd_name, cod, min_16_digit));
}

void SSPRequestCallback(RawAddress* remote_bd_addr, bt_bdname_t* bd_name,
                        uint32_t cod, bt_ssp_variant_t pairing_variant,
                        uint32_t pass_key) {
  shared_lock<shared_mutex_impl> lock(g_instance_lock);
  VERIFY_INTERFACE_OR_RETURN();
  VLOG(2) << __func__ << " - remote_bd_addr: " << remote_bd_addr
          << " - bd_name: " << bd_name << " - cod: " << cod
          << " - pairing_variant: " << pairing_variant;
  FOR_EACH_BLUETOOTH_OBSERVER(SSPRequestCallback(remote_bd_addr, bd_name, cod,
                                                 pairing_variant, pass_key));
}

void BondStateChangedCallback(bt_status_t status, RawAddress* remote_bd_addr,
                              bt_bond_state_t state) {
  shared_lock<shared_mutex_impl> lock(g_instance_lock);
  VERIFY_INTERFACE_OR_RETURN();
  VLOG(2) << __func__ << " - remote_bd_addr: " << BtAddrString(remote_bd_addr)
          << " - status: " << status << " - state: " << state;
  FOR_EACH_BLUETOOTH_OBSERVER(
      BondStateChangedCallback(status, remote_bd_addr, state));
}

void AclStateChangedCallback(bt_status_t status, RawAddress* remote_bd_addr,
                             bt_acl_state_t state) {
  shared_lock<shared_mutex_impl> lock(g_instance_lock);
  VERIFY_INTERFACE_OR_RETURN();
  CHECK(remote_bd_addr);
  VLOG(1) << "Remote device ACL state changed - status: "
          << BtStatusText(status)
          << " - BD_ADDR: " << BtAddrString(remote_bd_addr) << " - state: "
          << ((state == BT_ACL_STATE_CONNECTED) ? "CONNECTED" : "DISCONNECTED");
  FOR_EACH_BLUETOOTH_OBSERVER(
      AclStateChangedCallback(status, *remote_bd_addr, state));
}

void ThreadEventCallback(bt_cb_thread_evt evt) {
  VLOG(1) << "ThreadEventCallback" << BtEventText(evt);

  // TODO(armansito): This callback is completely useless to us but btif borks
  // out if this is not set. Consider making this optional.
}

bool SetWakeAlarmCallout(uint64_t /* delay_millis */, bool /* should_wake */,
                         alarm_cb /* cb */, void* /* data */) {
  // TODO(armansito): According to sharvil@, this interface doesn't even need to
  // exist and can be done entirely from within osi by interfacing directly with
  // the kernel. Remove these stubs once that's fixed. (See http://b/23390297)
  return false;
}

int AcquireWakeLockCallout(const char* /* lock_name */) {
  // TODO(armansito): According to sharvil@, this interface doesn't even need to
  // exist and can be done entirely from within osi by interfacing directly with
  // the kernel. Remove these stubs once that's fixed. (See http://b/23390297)
  // Lie here and return success so that enabling and disabling the controller
  // works before this is properly implemented.
  return BT_STATUS_SUCCESS;
}

int ReleaseWakeLockCallout(const char* /* lock_name */) {
  // TODO(armansito): According to sharvil@, this interface doesn't even need to
  // exist and can be done entirely from within osi by interfacing directly with
  // the kernel. Remove these stubs once that's fixed. (See http://b/23390297)
  // Lie here and return success so that enabling and disabling the controller
  // works before this is properly implemented.
  return BT_STATUS_SUCCESS;
}

// The HAL Bluetooth DM callbacks.
bt_callbacks_t bt_callbacks = {
    sizeof(bt_callbacks_t),
    AdapterStateChangedCallback,
    AdapterPropertiesCallback,
    RemoteDevicePropertiesCallback,
    nullptr, /* device_found_cb */
    DiscoveryStateChangedCallback,
    PinRequestCallback,
    SSPRequestCallback,
    BondStateChangedCallback,
    AclStateChangedCallback,
    ThreadEventCallback,
    nullptr, /* dut_mode_recv_cb */
    nullptr, /* le_test_mode_cb */
    nullptr  /* energy_info_cb */
};

bt_os_callouts_t bt_os_callouts = {sizeof(bt_os_callouts_t),
                                   SetWakeAlarmCallout, AcquireWakeLockCallout,
                                   ReleaseWakeLockCallout};

}  // namespace

// BluetoothInterface implementation for production.
class BluetoothInterfaceImpl : public BluetoothInterface {
 public:
  BluetoothInterfaceImpl() : hal_iface_(nullptr), hal_adapter_(nullptr) {}

  ~BluetoothInterfaceImpl() override {
    if (hal_iface_) hal_iface_->cleanup();
  }

  // BluetoothInterface overrides.
  void AddObserver(Observer* observer) override {
    shared_lock<shared_mutex_impl> lock(g_instance_lock);
    observers_.AddObserver(observer);
  }

  void RemoveObserver(Observer* observer) override {
    shared_lock<shared_mutex_impl> lock(g_instance_lock);
    observers_.RemoveObserver(observer);
  }

  const bt_interface_t* GetHALInterface() const override { return hal_iface_; }

  bt_callbacks_t* GetHALCallbacks() const override { return &bt_callbacks; }

  const bluetooth_device_t* GetHALAdapter() const override {
    return hal_adapter_;
  }

  // Initialize the interface. This loads the shared Bluetooth library and sets
  // up the callbacks.
  bool Initialize() {
    // Load the Bluetooth shared library module.
    const hw_module_t* module;
    int status = hal_util_load_bt_library(&module);
    if (status) {
      LOG(ERROR) << "Failed to load Bluetooth library: " << status;
      return false;
    }

    // Open the Bluetooth adapter.
    hw_device_t* device;
    status = module->methods->open(module, BT_HARDWARE_MODULE_ID, &device);
    if (status) {
      LOG(ERROR) << "Failed to open the Bluetooth module";
      return false;
    }

    hal_adapter_ = reinterpret_cast<bluetooth_device_t*>(device);
    hal_iface_ = hal_adapter_->get_bluetooth_interface();

    // Initialize the Bluetooth interface. Set up the adapter (Bluetooth DM) API
    // callbacks.
    status = hal_iface_->init(&bt_callbacks);
    if (status != BT_STATUS_SUCCESS) {
      LOG(ERROR) << "Failed to initialize Bluetooth stack";
      return false;
    }

    status = hal_iface_->set_os_callouts(&bt_os_callouts);
    if (status != BT_STATUS_SUCCESS) {
      LOG(ERROR) << "Failed to set up Bluetooth OS callouts";
      return false;
    }

    return true;
  }

  base::ObserverList<Observer>* observers() { return &observers_; }

 private:
  // List of observers that are interested in notifications from us. We're not
  // using a base::ObserverListThreadSafe, which it posts observer events
  // automatically on the origin threads, as we want to avoid that overhead and
  // simply forward the events to the upper layer.
  base::ObserverList<Observer> observers_;

  // The HAL handle obtained from the shared library. We hold a weak reference
  // to this since the actual data resides in the shared Bluetooth library.
  const bt_interface_t* hal_iface_;

  // The HAL handle that represents the underlying Bluetooth adapter. We hold a
  // weak reference to this since the actual data resides in the shared
  // Bluetooth library.
  const bluetooth_device_t* hal_adapter_;

  DISALLOW_COPY_AND_ASSIGN(BluetoothInterfaceImpl);
};

namespace {

// Helper for obtaining the observer list from the global instance. This
// function is NOT thread safe.
base::ObserverList<BluetoothInterface::Observer>* GetObservers() {
  CHECK(g_bluetooth_interface);
  return static_cast<BluetoothInterfaceImpl*>(g_bluetooth_interface)
      ->observers();
}

}  // namespace

// Default observer implementations. These are provided so that the methods
// themselves are optional.
void BluetoothInterface::Observer::AdapterStateChangedCallback(
    bt_state_t /* state*/) {
  // Do nothing.
}

void BluetoothInterface::Observer::AdapterPropertiesCallback(
    bt_status_t /* status */, int /* num_properties */,
    bt_property_t* /* properties */) {
  // Do nothing.
}

void BluetoothInterface::Observer::RemoteDevicePropertiesCallback(
    bt_status_t /* status */, RawAddress* /* remote_bd_addr */,
    int /* num_properties */, bt_property_t* /* properties */) {
  // Do nothing.
}

void BluetoothInterface::Observer::DiscoveryStateChangedCallback(
    bt_discovery_state_t /* state */) {
  // Do nothing.
}

void BluetoothInterface::Observer::PinRequestCallback(
    RawAddress* remote_bd_addr, bt_bdname_t* bd_name, uint32_t cod,
    bool min_16_digit) {
  // Do nothing.
}

void BluetoothInterface::Observer::SSPRequestCallback(
    RawAddress* remote_bd_addr, bt_bdname_t* bd_name, uint32_t cod,
    bt_ssp_variant_t pairing_variant, uint32_t pass_key) {
  // Do nothing.
}

void BluetoothInterface::Observer::BondStateChangedCallback(
    bt_status_t status, RawAddress* remote_bd_addr, bt_bond_state_t state) {
  // Do nothing.
}

void BluetoothInterface::Observer::AclStateChangedCallback(
    bt_status_t /* status */, const RawAddress& /* remote_bdaddr */,
    bt_acl_state_t /* state */) {
  // Do nothing.
}

// static
bool BluetoothInterface::Initialize() {
  unique_lock<shared_mutex_impl> lock(g_instance_lock);
  CHECK(!g_bluetooth_interface);

  std::unique_ptr<BluetoothInterfaceImpl> impl(new BluetoothInterfaceImpl());
  if (!impl->Initialize()) {
    LOG(ERROR) << "Failed to initialize BluetoothInterface";
    return false;
  }

  g_bluetooth_interface = impl.release();

  return true;
}

// static
void BluetoothInterface::CleanUp() {
  unique_lock<shared_mutex_impl> lock(g_instance_lock);
  CHECK(g_bluetooth_interface);

  delete g_bluetooth_interface;
  g_bluetooth_interface = nullptr;
}

// static
bool BluetoothInterface::IsInitialized() {
  shared_lock<shared_mutex_impl> lock(g_instance_lock);

  return g_bluetooth_interface != nullptr;
}

// static
BluetoothInterface* BluetoothInterface::Get() {
  shared_lock<shared_mutex_impl> lock(g_instance_lock);
  CHECK(g_bluetooth_interface);
  return g_bluetooth_interface;
}

// static
void BluetoothInterface::InitializeForTesting(
    BluetoothInterface* test_instance) {
  unique_lock<shared_mutex_impl> lock(g_instance_lock);
  CHECK(test_instance);
  CHECK(!g_bluetooth_interface);

  g_bluetooth_interface = test_instance;
}

}  // namespace hal
}  // namespace bluetooth
