// Copyright (c) 2012 The Chromium 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 "device/bluetooth/bluetooth_adapter.h"

#include <memory>
#include <string>
#include <utility>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/single_thread_task_runner.h"
#include "build/build_config.h"
#include "device/bluetooth/bluetooth_common.h"
#include "device/bluetooth/bluetooth_device.h"
#include "device/bluetooth/bluetooth_discovery_session.h"
#include "device/bluetooth/bluetooth_discovery_session_outcome.h"
#include "device/bluetooth/bluetooth_remote_gatt_characteristic.h"
#include "device/bluetooth/bluetooth_remote_gatt_descriptor.h"
#include "device/bluetooth/bluetooth_remote_gatt_service.h"

namespace device {

BluetoothAdapter::ServiceOptions::ServiceOptions() = default;
BluetoothAdapter::ServiceOptions::~ServiceOptions() = default;

#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS) && !defined(OS_MACOSX) && \
    !defined(OS_WIN) && !defined(OS_LINUX)
// static
base::WeakPtr<BluetoothAdapter> BluetoothAdapter::CreateAdapter(
    InitCallback init_callback) {
  return base::WeakPtr<BluetoothAdapter>();
}
#endif  // !defined(OS_CHROMEOS) && !defined(OS_WIN) && !defined(OS_MACOSX)

base::WeakPtr<BluetoothAdapter> BluetoothAdapter::GetWeakPtrForTesting() {
  return GetWeakPtr();
}

#if defined(OS_LINUX)
void BluetoothAdapter::Shutdown() {
  NOTIMPLEMENTED();
}
#endif

void BluetoothAdapter::AddObserver(BluetoothAdapter::Observer* observer) {
  DCHECK(observer);
  observers_.AddObserver(observer);
}

void BluetoothAdapter::RemoveObserver(BluetoothAdapter::Observer* observer) {
  DCHECK(observer);
  observers_.RemoveObserver(observer);
}

bool BluetoothAdapter::HasObserver(BluetoothAdapter::Observer* observer) {
  DCHECK(observer);
  return observers_.HasObserver(observer);
}

bool BluetoothAdapter::CanPower() const {
  return IsPresent();
}

void BluetoothAdapter::SetPowered(bool powered,
                                  const base::Closure& callback,
                                  const ErrorCallback& error_callback) {
  if (set_powered_callbacks_) {
    // Only allow one pending callback at a time.
    ui_task_runner_->PostTask(FROM_HERE, error_callback);
    return;
  }

  if (powered == IsPowered()) {
    // Return early in case no change of power state is needed.
    ui_task_runner_->PostTask(FROM_HERE, callback);
    return;
  }

  if (!SetPoweredImpl(powered)) {
    ui_task_runner_->PostTask(FROM_HERE, error_callback);
    return;
  }

  set_powered_callbacks_ = std::make_unique<SetPoweredCallbacks>();
  set_powered_callbacks_->powered = powered;
  set_powered_callbacks_->callback = callback;
  set_powered_callbacks_->error_callback = error_callback;
}

std::unordered_map<BluetoothDevice*, BluetoothDevice::UUIDSet>
BluetoothAdapter::RetrieveGattConnectedDevicesWithDiscoveryFilter(
    const BluetoothDiscoveryFilter& discovery_filter) {
  return std::unordered_map<BluetoothDevice*, BluetoothDevice::UUIDSet>();
}

void BluetoothAdapter::StartDiscoverySession(
    const DiscoverySessionCallback& callback,
    const ErrorCallback& error_callback) {
  StartDiscoverySessionWithFilter(nullptr, callback, error_callback);
}

void BluetoothAdapter::StartDiscoverySessionWithFilter(
    std::unique_ptr<BluetoothDiscoveryFilter> discovery_filter,
    const DiscoverySessionCallback& callback,
    const ErrorCallback& error_callback) {
  std::unique_ptr<BluetoothDiscoverySession> new_session(
      new BluetoothDiscoverySession(this, std::move(discovery_filter)));
  discovery_sessions_.insert(new_session.get());

  auto new_session_callbacks =
      base::WrapUnique(new StartOrStopDiscoveryCallback(
          base::BindOnce(callback, std::move(new_session)), error_callback));

  // Queue up the callbacks to be handled when we process the discovery queue.
  discovery_callback_queue_.push(std::move(new_session_callbacks));

  // If OS is already working on a discovery request we must wait to process the
  // queue until that request is complete.
  if (discovery_request_pending_) {
    return;
  }

  // The OS is ready to start a request so process the queue now.
  ProcessDiscoveryQueue();
}

void BluetoothAdapter::MaybeUpdateFilter(
    std::unique_ptr<BluetoothDiscoveryFilter> discovery_filter,
    DiscoverySessionResultCallback callback) {
  if (discovery_filter->Equals(current_discovery_filter_)) {
    std::move(callback).Run(/*is_error=*/false,
                            UMABluetoothDiscoverySessionOutcome::SUCCESS);
    return;
  }

  UpdateFilter(std::move(discovery_filter), std::move(callback));
}

void BluetoothAdapter::RemoveDiscoverySession(
    BluetoothDiscoverySession* discovery_session,
    const base::Closure& callback,
    DiscoverySessionErrorCallback error_callback) {
  size_t erased = discovery_sessions_.erase(discovery_session);
  DCHECK_EQ(1u, erased);

  std::unique_ptr<StartOrStopDiscoveryCallback> removal_callbacks(
      new StartOrStopDiscoveryCallback(callback, std::move(error_callback)));

  // Queue up the callbacks to be handled when we process the discovery queue.
  discovery_callback_queue_.push(std::move(removal_callbacks));

  // If OS is already working on a discovery request we must wait to process the
  // queue until that request is complete.
  if (discovery_request_pending_) {
    return;
  }

  // The OS is ready to start a request so process the queue now.
  ProcessDiscoveryQueue();
}

std::unique_ptr<BluetoothDiscoveryFilter>
BluetoothAdapter::GetMergedDiscoveryFilter() const {
  auto result =
      std::make_unique<BluetoothDiscoveryFilter>(BLUETOOTH_TRANSPORT_DUAL);
  bool first_merge = true;

  for (auto* iter : discovery_sessions_) {
    if (!iter->IsActive())
      continue;

    const BluetoothDiscoveryFilter* curr_filter = iter->GetDiscoveryFilter();

    if (first_merge) {
      first_merge = false;
      if (curr_filter) {
        result->CopyFrom(*curr_filter);
      }
      continue;
    }
    result = BluetoothDiscoveryFilter::Merge(result.get(), curr_filter);
  }
  return result;
}

BluetoothAdapter::DeviceList BluetoothAdapter::GetDevices() {
  ConstDeviceList const_devices =
    const_cast<const BluetoothAdapter *>(this)->GetDevices();

  DeviceList devices;
  for (ConstDeviceList::const_iterator i = const_devices.begin();
       i != const_devices.end(); ++i)
    devices.push_back(const_cast<BluetoothDevice *>(*i));

  return devices;
}

BluetoothAdapter::ConstDeviceList BluetoothAdapter::GetDevices() const {
  ConstDeviceList devices;
  for (const auto& device : devices_)
    devices.push_back(device.second.get());

  return devices;
}

BluetoothDevice* BluetoothAdapter::GetDevice(const std::string& address) {
  return const_cast<BluetoothDevice *>(
      const_cast<const BluetoothAdapter *>(this)->GetDevice(address));
}

const BluetoothDevice* BluetoothAdapter::GetDevice(
    const std::string& address) const {
  std::string canonicalized_address =
      BluetoothDevice::CanonicalizeAddress(address);
  if (canonicalized_address.empty())
    return nullptr;

  auto iter = devices_.find(canonicalized_address);
  if (iter != devices_.end())
    return iter->second.get();

  return nullptr;
}

void BluetoothAdapter::AddPairingDelegate(
    BluetoothDevice::PairingDelegate* pairing_delegate,
    PairingDelegatePriority priority) {
  // Remove the delegate, if it already exists, before inserting to allow a
  // change of priority.
  RemovePairingDelegate(pairing_delegate);

  // Find the first point with a lower priority, or the end of the list.
  auto iter = pairing_delegates_.begin();
  while (iter != pairing_delegates_.end() && iter->second >= priority)
    ++iter;

  pairing_delegates_.insert(iter, std::make_pair(pairing_delegate, priority));
}

void BluetoothAdapter::RemovePairingDelegate(
    BluetoothDevice::PairingDelegate* pairing_delegate) {
  for (auto iter = pairing_delegates_.begin(); iter != pairing_delegates_.end();
       ++iter) {
    if (iter->first == pairing_delegate) {
      RemovePairingDelegateInternal(pairing_delegate);
      pairing_delegates_.erase(iter);
      return;
    }
  }
}

BluetoothDevice::PairingDelegate* BluetoothAdapter::DefaultPairingDelegate() {
  if (pairing_delegates_.empty())
    return NULL;

  return pairing_delegates_.front().first;
}

std::vector<BluetoothAdvertisement*>
BluetoothAdapter::GetPendingAdvertisementsForTesting() const {
  return {};
}

void BluetoothAdapter::NotifyAdapterPresentChanged(bool present) {
  for (auto& observer : observers_)
    observer.AdapterPresentChanged(this, present);
}

void BluetoothAdapter::NotifyAdapterPoweredChanged(bool powered) {
  for (auto& observer : observers_)
    observer.AdapterPoweredChanged(this, powered);
}

void BluetoothAdapter::NotifyDeviceChanged(BluetoothDevice* device) {
  DCHECK(device);
  DCHECK_EQ(device->GetAdapter(), this);

  for (auto& observer : observers_)
    observer.DeviceChanged(this, device);
}

#if defined(OS_CHROMEOS) || defined(OS_LINUX)
void BluetoothAdapter::NotifyDevicePairedChanged(BluetoothDevice* device,
                                                 bool new_paired_status) {
  for (auto& observer : observers_)
    observer.DevicePairedChanged(this, device, new_paired_status);
}
#endif

#if defined(OS_CHROMEOS)
void BluetoothAdapter::NotifyDeviceBatteryChanged(BluetoothDevice* device) {
  DCHECK_EQ(device->GetAdapter(), this);
  for (auto& observer : observers_) {
    observer.DeviceBatteryChanged(this, device, device->battery_percentage());
  }
}
#endif

void BluetoothAdapter::NotifyGattServiceAdded(
    BluetoothRemoteGattService* service) {
  DCHECK_EQ(service->GetDevice()->GetAdapter(), this);

  for (auto& observer : observers_)
    observer.GattServiceAdded(this, service->GetDevice(), service);
}

void BluetoothAdapter::NotifyGattServiceRemoved(
    BluetoothRemoteGattService* service) {
  DCHECK_EQ(service->GetDevice()->GetAdapter(), this);

  for (auto& observer : observers_)
    observer.GattServiceRemoved(this, service->GetDevice(), service);
}

void BluetoothAdapter::NotifyGattServiceChanged(
    BluetoothRemoteGattService* service) {
  DCHECK_EQ(service->GetDevice()->GetAdapter(), this);

  for (auto& observer : observers_)
    observer.GattServiceChanged(this, service);
}

int BluetoothAdapter::NumDiscoverySessions() const {
  return discovery_sessions_.size();
}

void BluetoothAdapter::NotifyGattServicesDiscovered(BluetoothDevice* device) {
  DCHECK(device->GetAdapter() == this);

  for (auto& observer : observers_)
    observer.GattServicesDiscovered(this, device);
}

void BluetoothAdapter::NotifyGattDiscoveryComplete(
    BluetoothRemoteGattService* service) {
  DCHECK_EQ(service->GetDevice()->GetAdapter(), this);

  for (auto& observer : observers_)
    observer.GattDiscoveryCompleteForService(this, service);
}

void BluetoothAdapter::NotifyGattCharacteristicAdded(
    BluetoothRemoteGattCharacteristic* characteristic) {
  DCHECK_EQ(characteristic->GetService()->GetDevice()->GetAdapter(), this);

  for (auto& observer : observers_)
    observer.GattCharacteristicAdded(this, characteristic);
}

void BluetoothAdapter::NotifyGattCharacteristicRemoved(
    BluetoothRemoteGattCharacteristic* characteristic) {
  DCHECK_EQ(characteristic->GetService()->GetDevice()->GetAdapter(), this);

  for (auto& observer : observers_)
    observer.GattCharacteristicRemoved(this, characteristic);
}

void BluetoothAdapter::NotifyGattDescriptorAdded(
    BluetoothRemoteGattDescriptor* descriptor) {
  DCHECK_EQ(
      descriptor->GetCharacteristic()->GetService()->GetDevice()->GetAdapter(),
      this);

  for (auto& observer : observers_)
    observer.GattDescriptorAdded(this, descriptor);
}

void BluetoothAdapter::NotifyGattDescriptorRemoved(
    BluetoothRemoteGattDescriptor* descriptor) {
  DCHECK_EQ(
      descriptor->GetCharacteristic()->GetService()->GetDevice()->GetAdapter(),
      this);

  for (auto& observer : observers_)
    observer.GattDescriptorRemoved(this, descriptor);
}

void BluetoothAdapter::NotifyGattCharacteristicValueChanged(
    BluetoothRemoteGattCharacteristic* characteristic,
    const std::vector<uint8_t>& value) {
  DCHECK_EQ(characteristic->GetService()->GetDevice()->GetAdapter(), this);

  base::WeakPtr<BluetoothRemoteGattCharacteristic> weak_characteristic =
      characteristic->GetWeakPtr();
  for (auto& observer : observers_) {
    if (!weak_characteristic)
      break;
    observer.GattCharacteristicValueChanged(this, characteristic, value);
  }
}

void BluetoothAdapter::NotifyGattDescriptorValueChanged(
    BluetoothRemoteGattDescriptor* descriptor,
    const std::vector<uint8_t>& value) {
  DCHECK_EQ(
      descriptor->GetCharacteristic()->GetService()->GetDevice()->GetAdapter(),
      this);

  for (auto& observer : observers_)
    observer.GattDescriptorValueChanged(this, descriptor, value);
}

BluetoothAdapter::SetPoweredCallbacks::SetPoweredCallbacks() = default;
BluetoothAdapter::SetPoweredCallbacks::~SetPoweredCallbacks() = default;

BluetoothAdapter::StartOrStopDiscoveryCallback::StartOrStopDiscoveryCallback(
    base::OnceClosure start_callback,
    ErrorCallback start_error_callback) {
  this->start_callback = std::move(start_callback);
  this->start_error_callback = start_error_callback;
}
BluetoothAdapter::StartOrStopDiscoveryCallback::StartOrStopDiscoveryCallback(
    base::Closure stop_callback,
    DiscoverySessionErrorCallback stop_error_callback) {
  this->stop_callback = stop_callback;
  this->stop_error_callback = std::move(stop_error_callback);
}
BluetoothAdapter::StartOrStopDiscoveryCallback::
    ~StartOrStopDiscoveryCallback() = default;

BluetoothAdapter::BluetoothAdapter() {}

BluetoothAdapter::~BluetoothAdapter() {
  // If there's a pending powered request, run its error callback.
  if (set_powered_callbacks_)
    set_powered_callbacks_->error_callback.Run();
}

void BluetoothAdapter::RunPendingPowerCallbacks() {
  if (set_powered_callbacks_) {
    // Move into a local variable to clear out both callbacks at the end of the
    // scope and to allow scheduling another SetPowered() call in either of the
    // callbacks.
    auto callbacks = std::move(set_powered_callbacks_);
    callbacks->powered == IsPowered() ? std::move(callbacks->callback).Run()
                                      : callbacks->error_callback.Run();
  }
}

void BluetoothAdapter::OnDiscoveryChangeComplete(
    bool is_error,
    UMABluetoothDiscoverySessionOutcome outcome) {
  UpdateDiscoveryState(is_error);

  // Take a weak reference to |this| in case a callback frees the adapter.
  base::WeakPtr<BluetoothAdapter> self = GetWeakPtr();

  if (is_error) {
    NotifyDiscoveryError(std::move(callbacks_awaiting_response_));

    if (!self)
      return;

    discovery_request_pending_ = false;
    ProcessDiscoveryQueue();
    return;
  }

  current_discovery_filter_.CopyFrom(filter_being_set_);

  auto callbacks_awaiting_response = std::move(callbacks_awaiting_response_);
  while (!callbacks_awaiting_response.empty()) {
    std::unique_ptr<StartOrStopDiscoveryCallback> callbacks =
        std::move(callbacks_awaiting_response.front());
    callbacks_awaiting_response.pop();
    if (callbacks->start_callback)
      std::move(callbacks->start_callback).Run();
    if (callbacks->stop_callback)
      std::move(callbacks->stop_callback).Run();
  }

  if (!self)
    return;

  discovery_request_pending_ = false;
  ProcessDiscoveryQueue();
}

void BluetoothAdapter::UpdateDiscoveryState(bool is_error) {
  if (is_error) {
    if (internal_discovery_state_ == DiscoveryState::kStarting)
      internal_discovery_state_ = DiscoveryState::kIdle;
    // If there was an error stopping we still assume it worked as there is not
    // much we can do about the device messing up.
    if (internal_discovery_state_ == DiscoveryState::kStopping)
      internal_discovery_state_ = DiscoveryState::kIdle;
    return;
  }

  if (internal_discovery_state_ == DiscoveryState::kStarting)
    internal_discovery_state_ = DiscoveryState::kDiscovering;
  if (internal_discovery_state_ == DiscoveryState::kStopping)
    internal_discovery_state_ = DiscoveryState::kIdle;
}

void BluetoothAdapter::ProcessDiscoveryQueue() {
  if (discovery_callback_queue_.empty())
    return;
  DCHECK(callbacks_awaiting_response_.empty());
  callbacks_awaiting_response_.swap(discovery_callback_queue_);

  if (NumDiscoverySessions() == 0) {
    if (internal_discovery_state_ == DiscoveryState::kIdle) {
      OnDiscoveryChangeComplete(false,
                                UMABluetoothDiscoverySessionOutcome::SUCCESS);
      return;
    }
    internal_discovery_state_ = DiscoveryState::kStopping;
    discovery_request_pending_ = true;
    StopScan(base::BindOnce(&BluetoothAdapter::OnDiscoveryChangeComplete,
                            GetWeakPtr()));

    return;
  }

  auto result_callback = base::BindOnce(
      &BluetoothAdapter::OnDiscoveryChangeComplete, GetWeakPtr());
  auto new_desired_filter = GetMergedDiscoveryFilter();
  discovery_request_pending_ = true;
  filter_being_set_.CopyFrom(*new_desired_filter.get());
  if (internal_discovery_state_ == DiscoveryState::kDiscovering) {
    MaybeUpdateFilter(std::move(new_desired_filter),
                      std::move(result_callback));
    return;
  }
  internal_discovery_state_ = DiscoveryState::kStarting;
  StartScanWithFilter(std::move(new_desired_filter),
                      std::move(result_callback));
}

void BluetoothAdapter::NotifyDiscoveryError(CallbackQueue callback_queue) {
  while (!callback_queue.empty()) {
    std::unique_ptr<StartOrStopDiscoveryCallback> callbacks =
        std::move(callback_queue.front());
    callback_queue.pop();
    if (callbacks->start_error_callback)
      callbacks->start_error_callback.Run();
    // We never return error when stopping. If the physical adapter is messing
    // up and not stopping we are still just going to continue like it did stop.
    if (callbacks->stop_callback)
      std::move(callbacks->stop_callback).Run();
  }
}

void BluetoothAdapter::MarkDiscoverySessionsAsInactive() {
  // All sessions are becoming inactive so any pending requests should now fail
  if (!discovery_callback_queue_.empty())
    NotifyDiscoveryError(std::move(discovery_callback_queue_));
  // As sessions are marked as inactive they will notify the adapter that they
  // have become inactive, upon which the adapter will remove them from
  // |discovery_sessions_|. To avoid invalidating the iterator, make a copy
  // here.
  std::set<BluetoothDiscoverySession*> temp(discovery_sessions_);
  for (auto iter = temp.begin(); iter != temp.end(); ++iter) {
    (*iter)->MarkAsInactive();
    RemoveDiscoverySession(*iter, base::DoNothing(), base::DoNothing());
  }
}

void BluetoothAdapter::DeleteDeviceForTesting(const std::string& address) {
  devices_.erase(address);
}

void BluetoothAdapter::RemoveTimedOutDevices() {
  for (auto it = devices_.begin(); it != devices_.end();) {
    BluetoothDevice* device = it->second.get();
    if (device->IsPaired() || device->IsConnected() ||
        device->IsGattConnected()) {
      ++it;
      continue;
    }

    base::Time last_update_time = device->GetLastUpdateTime();

    bool device_expired =
        (base::Time::NowFromSystemTime() - last_update_time) > timeoutSec;
    VLOG(3) << "device: " << device->GetAddress()
            << ", last_update: " << last_update_time
            << ", exp: " << device_expired;

    if (!device_expired) {
      ++it;
      continue;
    }

    VLOG(1) << "Removing device: " << device->GetAddress();
    auto next = it;
    next++;
    std::unique_ptr<BluetoothDevice> removed_device = std::move(it->second);
    devices_.erase(it);
    it = next;

    for (auto& observer : observers_)
      observer.DeviceRemoved(this, removed_device.get());
  }
}

// static
void BluetoothAdapter::RecordBluetoothDiscoverySessionStartOutcome(
    UMABluetoothDiscoverySessionOutcome outcome) {
  UMA_HISTOGRAM_ENUMERATION(
      "Bluetooth.DiscoverySession.Start.Outcome", static_cast<int>(outcome),
      static_cast<int>(UMABluetoothDiscoverySessionOutcome::COUNT));
}

// static
void BluetoothAdapter::RecordBluetoothDiscoverySessionStopOutcome(
    UMABluetoothDiscoverySessionOutcome outcome) {
  UMA_HISTOGRAM_ENUMERATION(
      "Bluetooth.DiscoverySession.Stop.Outcome", static_cast<int>(outcome),
      static_cast<int>(UMABluetoothDiscoverySessionOutcome::COUNT));
}

// static
constexpr base::TimeDelta BluetoothAdapter::timeoutSec =
    base::TimeDelta::FromSeconds(180);

}  // namespace device
