// Copyright 2015 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_low_energy_device_mac.h"

#import <CoreFoundation/CoreFoundation.h>
#include <stddef.h>

#include "base/mac/mac_util.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/mac/sdk_forward_declarations.h"
#include "base/memory/ptr_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/sys_string_conversions.h"
#include "device/bluetooth/bluetooth_adapter_mac.h"
#include "device/bluetooth/bluetooth_adapter_mac_metrics.h"
#include "device/bluetooth/bluetooth_device.h"
#include "device/bluetooth/bluetooth_low_energy_peripheral_delegate.h"
#include "device/bluetooth/bluetooth_remote_gatt_characteristic_mac.h"
#include "device/bluetooth/bluetooth_remote_gatt_descriptor_mac.h"
#include "device/bluetooth/bluetooth_remote_gatt_service_mac.h"

// Remove when Chrome no longer supports 10.12.
#if defined(MAC_OS_X_VERSION_10_13)

// In the 10.13 SDK, CBPeripheral became a subclass of CBPeer, which defines
// -[CBPeer identifier] as partially available. Pretend it still exists on
// CBPeripheral. At runtime the implementation on CBPeer will be invoked.
@interface CBPeripheral (HighSierraSDK)
@property(readonly, nonatomic) NSUUID* identifier;
@end

#endif  // MAC_OS_X_VERSION_10_13

namespace device {

BluetoothLowEnergyDeviceMac::BluetoothLowEnergyDeviceMac(
    BluetoothAdapterMac* adapter,
    CBPeripheral* peripheral)
    : BluetoothDeviceMac(adapter),
      peripheral_(peripheral, base::scoped_policy::RETAIN),
      connected_(false),
      discovery_pending_count_(0) {
  DCHECK(BluetoothAdapterMac::IsLowEnergyAvailable());
  DCHECK(peripheral_);
  peripheral_delegate_.reset([[BluetoothLowEnergyPeripheralDelegate alloc]
      initWithBluetoothLowEnergyDeviceMac:this]);
  [peripheral_ setDelegate:peripheral_delegate_];
  identifier_ = GetPeripheralIdentifier(peripheral);
  hash_address_ = GetPeripheralHashAddress(peripheral);
  UpdateTimestamp();
}

BluetoothLowEnergyDeviceMac::~BluetoothLowEnergyDeviceMac() {
  if (IsGattConnected()) {
    GetMacAdapter()->DisconnectGatt(this);
  }

  [peripheral_ setDelegate:nil];
}

std::string BluetoothLowEnergyDeviceMac::GetIdentifier() const {
  return identifier_;
}

uint32_t BluetoothLowEnergyDeviceMac::GetBluetoothClass() const {
  return 0x1F00;  // Unspecified Device Class
}

std::string BluetoothLowEnergyDeviceMac::GetAddress() const {
  return hash_address_;
}

BluetoothDevice::VendorIDSource BluetoothLowEnergyDeviceMac::GetVendorIDSource()
    const {
  return VENDOR_ID_UNKNOWN;
}

uint16_t BluetoothLowEnergyDeviceMac::GetVendorID() const {
  return 0;
}

uint16_t BluetoothLowEnergyDeviceMac::GetProductID() const {
  return 0;
}

uint16_t BluetoothLowEnergyDeviceMac::GetDeviceID() const {
  return 0;
}

uint16_t BluetoothLowEnergyDeviceMac::GetAppearance() const {
  // TODO(crbug.com/588083): Implementing GetAppearance()
  // on mac, win, and android platforms for chrome
  NOTIMPLEMENTED();
  return 0;
}

base::Optional<std::string> BluetoothLowEnergyDeviceMac::GetName() const {
  if ([peripheral_ name])
    return base::SysNSStringToUTF8([peripheral_ name]);
  return base::nullopt;
}

bool BluetoothLowEnergyDeviceMac::IsPaired() const {
  return GetMacAdapter()->IsBluetoothLowEnergyDeviceSystemPaired(identifier_);
}

bool BluetoothLowEnergyDeviceMac::IsConnected() const {
  return IsGattConnected();
}

bool BluetoothLowEnergyDeviceMac::IsGattConnected() const {
  // |connected_| can be false while |[peripheral_ state]| is
  // |CBPeripheralStateConnected|. This happens
  // BluetoothAdapterMac::DidConnectPeripheral() is called and
  // BluetoothLowEnergyDeviceMac::DidConnectGatt() has not been called yet.
  return connected_;
}

bool BluetoothLowEnergyDeviceMac::IsConnectable() const {
  // Only available for Chrome OS.
  NOTIMPLEMENTED();
  return false;
}

bool BluetoothLowEnergyDeviceMac::IsConnecting() const {
  return ([peripheral_ state] == CBPeripheralStateConnecting);
}

bool BluetoothLowEnergyDeviceMac::ExpectingPinCode() const {
  return false;
}

bool BluetoothLowEnergyDeviceMac::ExpectingPasskey() const {
  return false;
}

bool BluetoothLowEnergyDeviceMac::ExpectingConfirmation() const {
  return false;
}

void BluetoothLowEnergyDeviceMac::GetConnectionInfo(
    const ConnectionInfoCallback& callback) {
  NOTIMPLEMENTED();
}

void BluetoothLowEnergyDeviceMac::SetConnectionLatency(
    ConnectionLatency connection_latency,
    const base::Closure& callback,
    const ErrorCallback& error_callback) {
  NOTIMPLEMENTED();
}

void BluetoothLowEnergyDeviceMac::Connect(
    PairingDelegate* pairing_delegate,
    const base::Closure& callback,
    const ConnectErrorCallback& error_callback) {
  NOTIMPLEMENTED();
}

void BluetoothLowEnergyDeviceMac::SetPinCode(const std::string& pincode) {
  NOTIMPLEMENTED();
}

void BluetoothLowEnergyDeviceMac::SetPasskey(uint32_t passkey) {
  NOTIMPLEMENTED();
}

void BluetoothLowEnergyDeviceMac::ConfirmPairing() {
  NOTIMPLEMENTED();
}

void BluetoothLowEnergyDeviceMac::RejectPairing() {
  NOTIMPLEMENTED();
}

void BluetoothLowEnergyDeviceMac::CancelPairing() {
  NOTIMPLEMENTED();
}

void BluetoothLowEnergyDeviceMac::Disconnect(
    const base::Closure& callback,
    const ErrorCallback& error_callback) {
  NOTIMPLEMENTED();
}

void BluetoothLowEnergyDeviceMac::Forget(const base::Closure& callback,
                                         const ErrorCallback& error_callback) {
  NOTIMPLEMENTED();
}

void BluetoothLowEnergyDeviceMac::ConnectToService(
    const BluetoothUUID& uuid,
    const ConnectToServiceCallback& callback,
    const ConnectToServiceErrorCallback& error_callback) {
  NOTIMPLEMENTED();
}

void BluetoothLowEnergyDeviceMac::ConnectToServiceInsecurely(
    const BluetoothUUID& uuid,
    const ConnectToServiceCallback& callback,
    const ConnectToServiceErrorCallback& error_callback) {
  NOTIMPLEMENTED();
}

void BluetoothLowEnergyDeviceMac::CreateGattConnectionImpl() {
  if (!IsGattConnected()) {
    GetMacAdapter()->CreateGattConnection(this);
  }
}

void BluetoothLowEnergyDeviceMac::DisconnectGatt() {
  GetMacAdapter()->DisconnectGatt(this);
}

void BluetoothLowEnergyDeviceMac::DidDiscoverPrimaryServices(NSError* error) {
  --discovery_pending_count_;
  if (discovery_pending_count_ < 0) {
    // This should never happen, just in case it happens with a device,
    // discovery_pending_count_ is set back to 0.
    VLOG(1) << *this
            << ": BluetoothLowEnergyDeviceMac::discovery_pending_count_ "
            << discovery_pending_count_;
    discovery_pending_count_ = 0;
    return;
  }
  RecordDidDiscoverPrimaryServicesResult(error);
  if (error) {
    // TODO(http://crbug.com/609320): Need to pass the error.
    // TODO(http://crbug.com/609844): Decide what to do if discover failed
    // a device services.
    VLOG(1) << *this << ": Can't discover primary services: "
            << BluetoothAdapterMac::String(error);
    return;
  }

  if (!IsGattConnected()) {
    // Don't create services if the device disconnected.
    VLOG(1) << *this << ": DidDiscoverPrimaryServices, gatt not connected.";
    return;
  }
  VLOG(1) << *this << ": DidDiscoverPrimaryServices, pending count: "
          << discovery_pending_count_;

  for (CBService* cb_service in GetPeripheral().services) {
    BluetoothRemoteGattServiceMac* gatt_service =
        GetBluetoothRemoteGattServiceMac(cb_service);
    if (!gatt_service) {
      gatt_service = new BluetoothRemoteGattServiceMac(this, cb_service,
                                                       true /* is_primary */);
      auto result_iter = gatt_services_.insert(std::make_pair(
          gatt_service->GetIdentifier(), base::WrapUnique(gatt_service)));
      DCHECK(result_iter.second);
      VLOG(1) << *gatt_service << ": New service.";
      adapter_->NotifyGattServiceAdded(gatt_service);
    } else {
      VLOG(1) << *gatt_service << ": Known service.";
    }
  }
  if (discovery_pending_count_ == 0) {
    for (auto it = gatt_services_.begin(); it != gatt_services_.end(); ++it) {
      BluetoothRemoteGattService* gatt_service = it->second.get();
      BluetoothRemoteGattServiceMac* gatt_service_mac =
          static_cast<BluetoothRemoteGattServiceMac*>(gatt_service);
      gatt_service_mac->DiscoverCharacteristics();
    }
    SendNotificationIfDiscoveryComplete();
  }
}

void BluetoothLowEnergyDeviceMac::DidDiscoverCharacteristics(
    CBService* cb_service,
    NSError* error) {
  RecordDidDiscoverCharacteristicsResult(error);
  if (error) {
    // TODO(http://crbug.com/609320): Need to pass the error.
    // TODO(http://crbug.com/609844): Decide what to do if discover failed
    VLOG(1) << *this << ": Can't discover characteristics: "
            << BluetoothAdapterMac::String(error);
    return;
  }

  if (!IsGattConnected()) {
    VLOG(1) << *this << ": DidDiscoverCharacteristics, gatt disconnected.";
    // Don't create characteristics if the device disconnected.
    return;
  }
  if (IsGattServicesDiscoveryComplete()) {
    // This should never happen, just in case it happens with a device, this
    // notification should be ignored.
    VLOG(1) << *this
            << ": Discovery complete, ignoring DidDiscoverCharacteristics.";
    return;
  }

  BluetoothRemoteGattServiceMac* gatt_service =
      GetBluetoothRemoteGattServiceMac(cb_service);
  DCHECK(gatt_service);
  gatt_service->DidDiscoverCharacteristics();
  SendNotificationIfDiscoveryComplete();
}

void BluetoothLowEnergyDeviceMac::DidModifyServices(
    NSArray* invalidatedServices) {
  VLOG(1) << *this << ": DidModifyServices: "
          << " invalidated services "
          << base::SysNSStringToUTF8([invalidatedServices description]);
  for (CBService* cb_service in invalidatedServices) {
    BluetoothRemoteGattServiceMac* gatt_service =
        GetBluetoothRemoteGattServiceMac(cb_service);
    DCHECK(gatt_service);
    VLOG(1) << gatt_service->GetUUID().canonical_value();
    std::unique_ptr<BluetoothRemoteGattService> scoped_service =
        std::move(gatt_services_[gatt_service->GetIdentifier()]);
    gatt_services_.erase(gatt_service->GetIdentifier());
    adapter_->NotifyGattServiceRemoved(scoped_service.get());
  }
  device_uuids_.ClearServiceUUIDs();
  SetGattServicesDiscoveryComplete(false);
  adapter_->NotifyDeviceChanged(this);
  DiscoverPrimaryServices();
}

void BluetoothLowEnergyDeviceMac::DidUpdateValue(
    CBCharacteristic* characteristic,
    NSError* error) {
  BluetoothRemoteGattCharacteristicMac* gatt_characteristic_mac =
      GetBluetoothRemoteGattCharacteristicMac(characteristic);
  DCHECK(gatt_characteristic_mac);
  gatt_characteristic_mac->DidUpdateValue(error);
}

void BluetoothLowEnergyDeviceMac::DidWriteValue(
    CBCharacteristic* characteristic,
    NSError* error) {
  BluetoothRemoteGattCharacteristicMac* gatt_characteristic_mac =
      GetBluetoothRemoteGattCharacteristicMac(characteristic);
  DCHECK(gatt_characteristic_mac);
  gatt_characteristic_mac->DidWriteValue(error);
}

void BluetoothLowEnergyDeviceMac::DidUpdateNotificationState(
    CBCharacteristic* characteristic,
    NSError* error) {
  BluetoothRemoteGattCharacteristicMac* gatt_characteristic_mac =
      GetBluetoothRemoteGattCharacteristicMac(characteristic);
  DCHECK(gatt_characteristic_mac);
  gatt_characteristic_mac->DidUpdateNotificationState(error);
}

void BluetoothLowEnergyDeviceMac::DidDiscoverDescriptors(
    CBCharacteristic* cb_characteristic,
    NSError* error) {
  RecordDidDiscoverDescriptorsResult(error);
  if (error) {
    // TODO(http://crbug.com/609320): Need to pass the error.
    // TODO(http://crbug.com/609844): Decide what to do if discover failed
    VLOG(1) << *this << ": Can't discover descriptors: "
            << BluetoothAdapterMac::String(error);
    return;
  }
  if (!IsGattConnected()) {
    VLOG(1) << *this << ": DidDiscoverDescriptors, disconnected.";
    // Don't discover descriptors if the device disconnected.
    return;
  }
  if (IsGattServicesDiscoveryComplete()) {
    // This should never happen, just in case it happens with a device, this
    // notification should be ignored.
    VLOG(1) << *this
            << ": Discovery complete, ignoring DidDiscoverDescriptors.";
    return;
  }
  BluetoothRemoteGattServiceMac* gatt_service =
      GetBluetoothRemoteGattServiceMac(cb_characteristic.service);
  DCHECK(gatt_service);
  gatt_service->DidDiscoverDescriptors(cb_characteristic);
  SendNotificationIfDiscoveryComplete();
}

void BluetoothLowEnergyDeviceMac::DidUpdateValueForDescriptor(
    CBDescriptor* cb_descriptor,
    NSError* error) {
  BluetoothRemoteGattDescriptorMac* gatt_descriptor =
      GetBluetoothRemoteGattDescriptorMac(cb_descriptor);
  DCHECK(gatt_descriptor);
  gatt_descriptor->DidUpdateValueForDescriptor(error);
}

void BluetoothLowEnergyDeviceMac::DidWriteValueForDescriptor(
    CBDescriptor* cb_descriptor,
    NSError* error) {
  BluetoothRemoteGattDescriptorMac* gatt_descriptor =
      GetBluetoothRemoteGattDescriptorMac(cb_descriptor);
  DCHECK(gatt_descriptor);
  gatt_descriptor->DidWriteValueForDescriptor(error);
}

// static
std::string BluetoothLowEnergyDeviceMac::GetPeripheralIdentifier(
    CBPeripheral* peripheral) {
  DCHECK(BluetoothAdapterMac::IsLowEnergyAvailable());
  NSUUID* uuid = [peripheral identifier];
  NSString* uuidString = [uuid UUIDString];
  return base::SysNSStringToUTF8(uuidString);
}

// static
std::string BluetoothLowEnergyDeviceMac::GetPeripheralHashAddress(
    CBPeripheral* peripheral) {
  return GetPeripheralHashAddress(GetPeripheralIdentifier(peripheral));
}

// static
std::string BluetoothLowEnergyDeviceMac::GetPeripheralHashAddress(
    base::StringPiece device_identifier) {
  const size_t kCanonicalAddressNumberOfBytes = 6;
  char raw[kCanonicalAddressNumberOfBytes];
  crypto::SHA256HashString(device_identifier, raw, sizeof(raw));
  return BluetoothDevice::CanonicalizeAddress(
      base::HexEncode(raw, sizeof(raw)));
}

void BluetoothLowEnergyDeviceMac::DidConnectPeripheral() {
  VLOG(1) << *this << ": GATT connected.";
  if (!connected_) {
    connected_ = true;
    DidConnectGatt();
    DiscoverPrimaryServices();
  } else {
    // -[<CBCentralManagerDelegate> centralManager:didConnectPeripheral:] can be
    // called twice because of a macOS bug. This second call should be ignored.
    // See crbug.com/681414.
    VLOG(1) << *this << ": Already connected, ignoring event.";
  }
}

void BluetoothLowEnergyDeviceMac::DiscoverPrimaryServices() {
  VLOG(1) << *this << ": DiscoverPrimaryServices, pending count "
          << discovery_pending_count_;
  ++discovery_pending_count_;
  [GetPeripheral() discoverServices:nil];
}

void BluetoothLowEnergyDeviceMac::SendNotificationIfDiscoveryComplete() {
  DCHECK(!IsGattServicesDiscoveryComplete());
  // Notify when all services have been discovered.
  bool discovery_complete =
      discovery_pending_count_ == 0 &&
      std::find_if_not(
          gatt_services_.begin(),
          gatt_services_.end(), [](GattServiceMap::value_type & pair) {
            BluetoothRemoteGattService* gatt_service = pair.second.get();
            return static_cast<BluetoothRemoteGattServiceMac*>(gatt_service)
                ->IsDiscoveryComplete();
          }) == gatt_services_.end();
  if (discovery_complete) {
    VLOG(1) << *this << ": Discovery complete.";
    device_uuids_.ReplaceServiceUUIDs(gatt_services_);
    SetGattServicesDiscoveryComplete(true);
    adapter_->NotifyGattServicesDiscovered(this);
    adapter_->NotifyDeviceChanged(this);
  }
}

BluetoothAdapterMac* BluetoothLowEnergyDeviceMac::GetMacAdapter() {
  return static_cast<BluetoothAdapterMac*>(this->adapter_);
}

BluetoothAdapterMac* BluetoothLowEnergyDeviceMac::GetMacAdapter() const {
  return static_cast<BluetoothAdapterMac*>(this->adapter_);
}

CBPeripheral* BluetoothLowEnergyDeviceMac::GetPeripheral() {
  return peripheral_;
}

BluetoothRemoteGattServiceMac*
BluetoothLowEnergyDeviceMac::GetBluetoothRemoteGattServiceMac(
    CBService* cb_service) const {
  for (auto it = gatt_services_.begin(); it != gatt_services_.end(); ++it) {
    BluetoothRemoteGattService* gatt_service = it->second.get();
    BluetoothRemoteGattServiceMac* gatt_service_mac =
        static_cast<BluetoothRemoteGattServiceMac*>(gatt_service);
    if (gatt_service_mac->GetService() == cb_service)
      return gatt_service_mac;
  }
  return nullptr;
}

BluetoothRemoteGattCharacteristicMac*
BluetoothLowEnergyDeviceMac::GetBluetoothRemoteGattCharacteristicMac(
    CBCharacteristic* cb_characteristic) const {
  CBService* cb_service = [cb_characteristic service];
  BluetoothRemoteGattServiceMac* gatt_service_mac =
      GetBluetoothRemoteGattServiceMac(cb_service);
  if (!gatt_service_mac) {
    return nullptr;
  }
  return gatt_service_mac->GetBluetoothRemoteGattCharacteristicMac(
      cb_characteristic);
}

BluetoothRemoteGattDescriptorMac*
BluetoothLowEnergyDeviceMac::GetBluetoothRemoteGattDescriptorMac(
    CBDescriptor* cb_descriptor) const {
  CBService* cb_service = [[cb_descriptor characteristic] service];
  BluetoothRemoteGattServiceMac* gatt_service_mac =
      GetBluetoothRemoteGattServiceMac(cb_service);
  if (!gatt_service_mac) {
    return nullptr;
  }
  return gatt_service_mac->GetBluetoothRemoteGattDescriptorMac(cb_descriptor);
}

void BluetoothLowEnergyDeviceMac::DidDisconnectPeripheral(NSError* error) {
  connected_ = false;
  VLOG(1) << *this << ": Disconnected from peripheral.";
  RecordDidDisconnectPeripheralResult(error);
  if (error) {
    VLOG(1) << *this
            << ": Bluetooth error: " << BluetoothAdapterMac::String(error);
  }
  SetGattServicesDiscoveryComplete(false);
  // Removing all services at once to ensure that calling GetGattService on
  // removed service in GattServiceRemoved returns null.
  GattServiceMap gatt_services_swapped;
  gatt_services_swapped.swap(gatt_services_);
  gatt_services_swapped.clear();
  device_uuids_.ClearServiceUUIDs();
  // There are two cases in which this function will be called:
  //   1. When the connection to the device breaks (either because
  //      we closed it or the device closed it).
  //   2. When we cancel a pending connection request.
  if (create_gatt_connection_error_callbacks_.empty()) {
    // If there are no pending callbacks then the connection broke (#1).
    DidDisconnectGatt();
    return;
  }
  // Else we canceled the connection request (#2).
  // TODO(http://crbug.com/585897): Need to pass the error.
  DidFailToConnectGatt(BluetoothDevice::ConnectErrorCode::ERROR_FAILED);
}

std::ostream& operator<<(std::ostream& out,
                         const BluetoothLowEnergyDeviceMac& device) {
  // TODO(crbug.com/703878): Should use
  // BluetoothLowEnergyDeviceMac::GetNameForDisplay() instead.
  base::Optional<std::string> name = device.GetName();
  const char* is_gatt_connected =
      device.IsGattConnected() ? "GATT connected" : "GATT disconnected";
  return out << "<BluetoothLowEnergyDeviceMac " << device.GetAddress() << "/"
             << &device << ", " << is_gatt_connected << ", \""
             << name.value_or("Unnamed device") << "\">";
}

}  // namespace device
