// Copyright 2016 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

#import "CBDriver.h"
#import "CBLog.h"
#import "CBScanningDriver.h"
#import "CBUtil.h"

// These 3 constants are from v.io/x/ref/lib/disocvery/plugins/ble/encoding.go
static NSString *kPackedCharacteristicUuidFmt = @"31ca10d5-0195-54fa-9344-25fcd7072e%x%x";
static const int kMaxNumPackedServices = 16;
static const int kMaxNumPackedCharacteristicsPerService = 16;

static const NSTimeInterval kFlushCachePeriod = 24 * 60 * 60;  // Every 24h
static const NSTimeInterval kMaxTimeForDiscoverServices = 90;

@class CBPeripheralScan, CBPeripheralServiceScan;

/**
 Scanning has two major components to it: waiting for the hardware to discover service uuids,
 and connecting to a device to retrieve all advertisement services & their data (by reading
 its charactertistics). Because all BLE calls are asynchronous and CoreBluetooth requires us to
 maintain strong references to the CBPeripheral, classes CBPeripheralScan and CBPeripheralSeviceScan
 were created to encapsulate and store all state.

 CBPeripheralScan controls scanning a discovered foreign BLE device

 CBPeripheralServiceScan controls connecting to a service and reading its characteristics.

 Each of these classes performs callbacks to their delegate when they have completed a task. The
 flow goes upwards, from CBPeripheralServiceScan to its parent CBPeripheralScan, which then
 reports any discovered service to CBScanningDriver which finally reports to the passed handler.

 The following pseduo-code encapsulates the main flow (in reality everything is async):

 // CBScanningDriver
 onPeripheralDiscovered(peripheral):
   if peripheral.visibleServiceUUIDs.filter(requestedServiceUuids, baseUuid, baseMask).isEmpty:
      return
   scan = CBPeripheralScan(peripheral, requestedServiceUuids, baseUuid, baseMask)
   scan.start()

 // CBPeripheralScan.start
 allServices = peripheral.getAllServiceUuids()
 v23Services = allServices.filter(requestedServiceUuids, baseUuid, baseMask)
 foreach service in v23Service:
   serviceScan = CBPeripheralServiceScan(service)
   serviceScan.start()

 // CBPeripheralServiceScan.start
 NSMutableDictionary data = service.allCharacteristics.map { characteristic -> characteristic.read()
 }
 onDiscoveredHandler(service, data) // Here is where we callback to the original requester,
 // although in reality this is bubbled all the way back up the chain to CBScanningDriver who
 // is the one who owns and calls the handler.
 */

/** Callbacks from CBPeripheralScan */
@protocol CBPeripheralScanDelegate<NSObject>
- (void)peripheralScanDidComplete:(CBPeripheralScan *)peripheralScan;
// Returns true if a given serviceUuid matches the current scan query.
- (BOOL)uuidMatchesScanFilter:(CBUUID *)serviceUuid;
@end

/** Callbacks from CBPeripheralServiceScan */
@protocol CBPeripheralServiceScanDelegate<NSObject>
- (void)serviceScanDidComplete:(CBPeripheralServiceScan *)serviceScan;
@optional
- (void)updateLastActivity;
@end

/** CBPeripheralScan controls scanning a discovered foreign BLE device. */
@interface CBPeripheralScan : NSObject<CBPeripheralDelegate, CBPeripheralServiceScanDelegate>
@property(nonatomic, weak) id<CBPeripheralScanDelegate, CBPeripheralServiceScanDelegate> delegate;
@property(nonatomic, strong) NSDate *_Nonnull lastActivity;
@property(nonatomic, strong) CBPeripheral *_Nonnull peripheral;
@property(nonatomic, strong) NSNumber *_Nonnull rssi;
@property(nonatomic, strong) NSMutableSet<CBPeripheralServiceScan *> *_Nonnull serviceScans;
@property(nonatomic, strong) NSMutableSet<CBPeripheralServiceScan *> *_Nonnull completedScans;
- (id)initWithPeripheral:(CBPeripheral *_Nonnull)peripheral
                    rssi:(NSNumber *)rssi
                delegate:(id<CBPeripheralScanDelegate, CBPeripheralServiceScanDelegate>)delegate;
- (void)start:(NSArray<CBUUID *> *_Nullable)scanUuids;
- (NSMutableSet<CBUUID *> *_Nonnull)seenUUIDs;
@end

/** CBPeripheralServiceScan controls connecting to a service and reading its characteristics. */
@interface CBPeripheralServiceScan : NSObject<CBPeripheralDelegate>
@property(nonatomic, weak) id<CBPeripheralServiceScanDelegate> delegate;
@property(nonatomic, strong) CBService *_Nonnull service;
@property(nonatomic, strong) NSMutableSet<CBCharacteristic *> *_Nonnull queryingCharacteristics;
@property(nonatomic, strong) NSMutableDictionary<CBUUID *, NSData *> *_Nonnull characteristics;
@property(nonatomic, strong) NSNumber *_Nonnull rssi;
- (id)initWithService:(CBService *_Nonnull)service
                 rssi:(NSNumber *)rssi
             delegate:(id<CBPeripheralServiceScanDelegate>)delegate;
- (void)start;
@end

@interface CBScanningDriver ()<CBPeripheralScanDelegate, CBPeripheralServiceScanDelegate>
@property(nonatomic, assign) BOOL isScanning;
@property(nonatomic, strong) NSArray<CBUUID *> *_Nullable scanUuids;
@property(nonatomic, strong) CBUUID *_Nullable baseUuid;
@property(nonatomic, strong) CBUUID *_Nullable maskUuid;
@property(nonatomic, strong) CBOnDiscoveredHandler _Nullable onDiscoveredHandler;
@property(nonatomic, strong) NSMutableSet<CBPeripheralScan *> *_Nonnull scans;
@end

@implementation CBScanningDriver

- (id _Nullable)initWithQueue:(dispatch_queue_t _Nonnull)queue {
  if (self = [super init]) {
    self.queue = queue;
    self.central = [[CBCentralManager alloc] initWithDelegate:self queue:self.queue];
    [self _initDiscovery];
  }
  return self;
}

- (void)dealloc {
  CBDispatchSync(self.queue, ^{
    self.central.delegate = nil;
    if ([self isHardwarePoweredOn]) {
      [self.central stopScan];
    }
  });
}

/** Schedules flushing the scan cache using the default scan cache period which is currently
 one day. The reason is that we want to avoid re-connecting to services unless their advertised
 UUIDs change since updated discovery information results in a bit-flip in existing advertised
 UUIDs. To prevent a situation where we have a buggy situation that never otherwise resolves,
 we create a maximum time of 24h to hold onto our cache of devices & seen service UUIDs.
 */
- (void)scheduleFlush {
  dispatch_time_t flushCacheDelay =
      dispatch_time(DISPATCH_TIME_NOW, (int64_t)(kFlushCachePeriod * NSEC_PER_SEC));
  __weak typeof(self) this = self;
  dispatch_after(flushCacheDelay, self.queue, ^{
    [this flushScanCache];
  });
}

/** Removes all previously seen devices & service UUIDs from our cache. If we were in the middle
 of a scan, that data is preserved and the scan is restarted
 */
- (void)flushScanCache {
  NSArray *scanUuids = self.scanUuids;
  CBUUID *baseUuid = self.baseUuid;
  CBUUID *maskUuid = self.maskUuid;
  CBOnDiscoveredHandler onDiscoveredHandler = self.onDiscoveredHandler;
  BOOL wasScanning = self.isScanning;
  if (wasScanning) {
    [self stopScan];
  }
  [self _initDiscovery];
  if (wasScanning) {
    NSError *err = nil;
    [self startScan:scanUuids
           baseUuid:baseUuid
           maskUuid:maskUuid
            handler:onDiscoveredHandler
              error:&err];
    if (err) {
      CBErrorLog(@"Unable to restart scan post-flush: %@", err);
    }
  }
}

- (void)_initDiscovery {
  self.isScanning = NO;
  self.scanUuids = nil;
  self.baseUuid = nil;
  self.maskUuid = nil;
  self.onDiscoveredHandler = nil;
  self.scans = [NSMutableSet new];
  [self scheduleFlush];
}

- (BOOL)startScan:(NSArray<CBUUID *> *_Nonnull)uuids
         baseUuid:(CBUUID *_Nonnull)baseUuid
         maskUuid:(CBUUID *_Nonnull)maskUuid
          handler:(CBOnDiscoveredHandler _Nonnull)handler
            error:(NSError *_Nullable *_Nullable)error {
  __block NSError *localError = nil;
  // CoreBluetooth prefers nil to signal scan all devices
  if (uuids.count == 0) {
    uuids = nil;
  }
  CBDispatchSync(self.queue, ^{
    switch (self.central.state) {
      case CBCentralManagerStateUnsupported:
        localError = [NSError errorWithDomain:kCBDriverErrorDomain
                                         code:CBDriverErrorUnsupportedHardware
                                     userInfo:@{
                                       NSLocalizedDescriptionKey : @"Unsupported hardware"
                                     }];
        return;
      case CBCentralManagerStateUnauthorized:
        localError = [NSError errorWithDomain:kCBDriverErrorDomain
                                         code:CBDriverErrorUnauthorized
                                     userInfo:@{
                                       NSLocalizedDescriptionKey : @"Unauthorized"
                                     }];
        return;
      default:
        break;
    }
    self.scanUuids = uuids;
    self.baseUuid = baseUuid;
    self.maskUuid = maskUuid;
    self.onDiscoveredHandler = handler;
    self.isScanning = YES;
    if ([self isHardwarePoweredOn]) {
      [self.central scanForPeripheralsWithServices:self.scanUuids
                                           options:@{
                                             CBCentralManagerScanOptionAllowDuplicatesKey : @NO
                                           }];
    }
  });
  if (localError) {
    if (error) {
      *error = localError;
    }
    return NO;
  }
  return YES;
}

- (void)stopScan {
  CBDispatchSync(self.queue, ^{
    if ([self isHardwarePoweredOn]) {
      [self.central stopScan];
      for (CBPeripheralScan *scan in self.scans) {
        [self.central cancelPeripheralConnection:scan.peripheral];
      }
    }
    self.isScanning = NO;
    self.scanUuids = nil;
    self.baseUuid = nil;
    self.maskUuid = nil;
    self.onDiscoveredHandler = nil;
    // We don't just call _initDiscovery because that removes our cache of scanned peripherals
    // which we want to keep.
  });
}

- (void)cancelPendingScans {
  for (CBPeripheralScan *scan in self.scans.allObjects) {
    [self peripheralScanDidComplete:scan];
  }
}

#pragma mark - CBCentralManagerDelegate callbacks

- (void)centralManagerDidUpdateState:(CBCentralManager *)central {
  switch (central.state) {
    case CBCentralManagerStatePoweredOn:
      CBInfoLog(@"CBCentralManagerStateOn");
      if (self.isScanning) {
        [self.central scanForPeripheralsWithServices:self.scanUuids options:nil];
      }
      break;
    case CBCentralManagerStatePoweredOff:
      CBInfoLog(@"CBCentralManagerStateOff");
      [self cancelPendingScans];
      break;
    case CBCentralManagerStateResetting:
      CBInfoLog(@"CBCentralManagerStateResetting");
      [self cancelPendingScans];
      break;
    case CBCentralManagerStateUnauthorized:
      CBInfoLog(@"CBCentralManagerStateUnauthorized");
      [self cancelPendingScans];
      break;
    case CBCentralManagerStateUnknown:
      CBInfoLog(@"CBCentralManagerStateUnknown");
      [self cancelPendingScans];
      break;
    case CBCentralManagerStateUnsupported:
      CBInfoLog(@"CBCentralManagerStateUnsupported");
      [self cancelPendingScans];
      break;
  }
}

- (BOOL)canHandleDiscovery:(CBPeripheral *)peripheral {
  if (![self isHardwarePoweredOn]) {
    CBPeripheralScan *existingScan = [self scanForPeripheral:peripheral];
    if (existingScan) {
      // Unlikely but just in case....
      CBErrorLog(@"Discovered peripheral with existing scan %@ but hardware is now off, dropping",
                 existingScan);
      [self peripheralScanDidComplete:existingScan];
      // Remove from cache -- we're powered off so something weird is going on
      [self.scans removeObject:existingScan];
    }
    return NO;
  }
  if (!self.isScanning) {
    CBErrorLog(@"Discovered peripheral even though we're not scanning -- "
               @"turning off hardware scan");
    // Make sure this isn't a delayed message after hardware getting turned off.
    if ([self isHardwarePoweredOn]) {
      [self.central stopScan];
    }
    return NO;
  }
  return YES;
}

- (NSSet *)targetServiceUuidsInAdData:(NSDictionary<NSString *, id> *_Nonnull)adData {
  // Extract and find service UUIDs that we care about
  NSMutableSet *serviceUuids = [NSMutableSet new];
  NSArray<CBUUID *> *dataServiceUuids = adData[CBAdvertisementDataServiceUUIDsKey];
  if (dataServiceUuids) [serviceUuids addObjectsFromArray:dataServiceUuids];
  NSArray<CBUUID *> *overflowServiceUuids = adData[CBAdvertisementDataOverflowServiceUUIDsKey];
  if (overflowServiceUuids) [serviceUuids addObjectsFromArray:overflowServiceUuids];
  NSSet *matchingUuids = [self filterMatchingUUIDs:serviceUuids];
  return matchingUuids;
}

- (void)centralManager:(CBCentralManager *)central
 didDiscoverPeripheral:(CBPeripheral *)peripheral
     advertisementData:(NSDictionary<NSString *, id> *)adData
                  RSSI:(NSNumber *)RSSI {
  if (![self canHandleDiscovery:peripheral]) {
    return;
  }
  CBDebugLog(@"Discovered peripheral %@ with ad data %@", peripheral, adData);
  NSSet *serviceUuids = [self targetServiceUuidsInAdData:adData];
  if (!serviceUuids.count) {
    CBDebugLog(@"No matching UUIDs -- ignoring discovered peripheral with service uuids %@",
               serviceUuids);
    return;
  }
  CBPeripheralScan *existingScan = [self scanForPeripheral:peripheral];
  if (existingScan) {
    // Are there any new UUIDs being advertised?
    NSMutableSet *newUuids = [serviceUuids mutableCopy];
    [newUuids minusSet:[existingScan seenUUIDs]];
    if (!newUuids.count) {
      // Nothing new -- ignore the duplicate notice.
      CBDebugLog(@"No new service UUIDs -- ignoring");
      return;
    }
    // There are new things we haven't seen before... so we either need to restart this
    // scan or if this scan is in the middle of discovering services then we can safely
    // ignore this (since it's about to see the same thing).
    if (!existingScan.delegate || existingScan.serviceScans.count ||
        // We're still waiting for discover services to come back.. make sure it isn't hung-up
        fabs(existingScan.lastActivity.timeIntervalSinceNow) > kMaxTimeForDiscoverServices) {
      // We have existing service scans... so we can safely restart this scan. Remove the old
      // and we'll create a new one below.
      CBInfoLog(@"Restarting scan of peripheral: %@", existingScan);
      existingScan.peripheral.delegate = nil;
      [self.scans removeObject:existingScan];
    } else {
      // We're waiting for the services to be discovered -- ignore the rotation.
      CBDebugLog(@"Waiting for peripheral to have its services discovered -- ignoring ad");
      return;
    }
  }
  // Start the scan by connecting to it
  CBPeripheralScan *scan =
      [[CBPeripheralScan alloc] initWithPeripheral:peripheral rssi:RSSI delegate:self];
  [self.scans addObject:scan];
  switch (peripheral.state) {
    case CBPeripheralStateConnected:
      [scan start:self.scanUuids];
      break;
    case CBPeripheralStateConnecting:
      break;
    default:  // Disconnected or Disconnecting (depending on SDK)
      CBDebugLog(@"Connecting to peripheral %@", peripheral);
      [central connectPeripheral:peripheral options:nil];
      break;
  }
}

- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral {
  CBInfoLog(@"didConnectPeripheral: %@", peripheral);
  CBPeripheralScan *scan = [self scanForPeripheral:peripheral];
  if (!scan) {
    CBInfoLog(@"Peripheral not queued -- ignoring");
    if ([self isHardwarePoweredOn]) {
      [central cancelPeripheralConnection:peripheral];
    }
    return;
  }
  if (!self.isScanning || ![self isHardwarePoweredOn]) {
    CBInfoLog(@"Dropping connected peripheral: isScanning=%d isHardwarePoweredOn=%d",
              self.isScanning, [self isHardwarePoweredOn]);
    [self peripheralScanDidComplete:scan];
    return;
  }
  [scan start:self.scanUuids];
}

- (void)centralManager:(CBCentralManager *)central
    didFailToConnectPeripheral:(CBPeripheral *)peripheral
                         error:(nullable NSError *)error {
  CBErrorLog(@"didFailToConnectPeripheral %@ error %@", peripheral, error);
  if (!self.isScanning) {
    CBInfoLog(@"Not scanning anymore -- disconnecting peripheral");
  }
  CBPeripheralScan *scan = [self scanForPeripheral:peripheral];
  if (!scan) {
    CBInfoLog(@"Peripheral not queued -- ignoring");
    return;
  }
  CBErrorLog(@"Unable to read characteristics for peripheral %@", peripheral);
  [self peripheralScanDidComplete:scan];
}

- (void)centralManager:(CBCentralManager *)central
    didDisconnectPeripheral:(CBPeripheral *)peripheral
                      error:(nullable NSError *)error {
  CBInfoLog(@"didDisconnectPeripheral %@ error %@", peripheral, error);
  CBPeripheralScan *scan = [self scanForPeripheral:peripheral];
  if (!scan) {
    CBDebugLog(@"Peripheral not queued -- ignoring");
    return;
  }
  if (scan.completedScans.count != scan.serviceScans.count) {
    CBInfoLog(@"Lost connection to peripheral mid-query");
    [self peripheralScanDidComplete:scan];
  }
}

#pragma mark - Driver Util

- (CBPeripheralScan *_Nullable)scanForPeripheral:(CBPeripheral *_Nonnull)peripheral {
  for (CBPeripheralScan *scan in self.scans) {
    if ([scan.peripheral isEqual:peripheral]) {
      return scan;
    }
  }
  return nil;
}

- (NSSet *)filterMatchingUUIDs:(NSSet *)allUuids {
  NSMutableSet *matchingUuids = [NSMutableSet new];
  for (CBUUID *uuid in allUuids) {
    if ([self uuidMatchesScanFilter:uuid]) {
      [matchingUuids addObject:uuid];
    }
  }
  return matchingUuids;
}

- (BOOL)uuidMatchesScanFilter:(CBUUID *)serviceUuid {
  if ([self.scanUuids containsObject:serviceUuid]) {
    CBDebugLog(@"Found matching service %@", serviceUuid.UUIDString);
    return YES;
  }
  if (self.baseUuid && self.maskUuid) {
    if (serviceUuid.data.length != self.maskUuid.data.length) {
      CBDebugLog(@"Not applying mask to different length UUID %@", serviceUuid);
      return NO;
    }
    // Find UUIDs that match base with the mask applied
    NSMutableData *maskedUuidData = [NSMutableData dataWithData:serviceUuid.data];
    const char *maskBytes = self.maskUuid.data.bytes;
    char *maskedUuidBytes = maskedUuidData.mutableBytes;
    for (int i = 0; i < self.maskUuid.data.length; i++) {
      maskedUuidBytes[i] = maskedUuidBytes[i] & maskBytes[i];
    }
    CBUUID *maskedUuid = [CBUUID UUIDWithData:maskedUuidData];
    if ([maskedUuid isEqual:self.baseUuid]) {
      CBDebugLog(@"Found service %@ via mask", serviceUuid.UUIDString);
      return YES;
    }
  }
  return NO;
}

- (NSString *)debugDescription {
  if (!self.queue) return @"[CBScanningDriver missing queue -- broken state]";
  __block NSString *out = nil;
  CBDispatchSync(self.queue, ^{
    out = [NSString stringWithFormat:@"[CBScanningDriver isHardwareOn=%d isScanning=%d "
                                     @"scanForUuids=%@, scans=%@]",
                                     self.isHardwarePoweredOn, self.isScanning, self.scanUuids,
                                     self.scans];
  });
  return out;
}

#pragma mark - Scan Delegates

- (void)peripheralScanDidComplete:(CBPeripheralScan *)peripheralScan {
  CBInfoLog(@"Done scanning peripheral %@", peripheralScan.peripheral);
  peripheralScan.peripheral.delegate = nil;
  if ([self isHardwarePoweredOn]) {
    [self.central cancelPeripheralConnection:peripheralScan.peripheral];
  }
}

- (void)serviceScanDidComplete:(CBPeripheralServiceScan *)serviceScan {
  CBInfoLog(@"serviceScanDidComplete: %@", serviceScan);
  if (self.onDiscoveredHandler) {
    int rssi = serviceScan.rssi.intValue;
    // From:
    // https://developer.apple.com/library/mac/documentation/IOBluetooth/Reference/IOBluetoothDevice_reference/#//apple_ref/occ/instm/IOBluetoothDevice/RSSI
    // "If the value cannot be read (e.g. the device is disconnected) or is not available on a
    // module, a value of +127 will be returned."
    if (rssi == 127) {
      CBDebugLog(@"RSSI of +127 found, reporting at 0 to Go");
      rssi = 0;
    }
    CBDebugLog(@"Notifying of service %@ with characteristics %@ and rssi of %d",
               serviceScan.service.UUID, serviceScan.characteristics, rssi);
    self.onDiscoveredHandler(serviceScan.service.UUID, serviceScan.characteristics, rssi);
  }
}

- (BOOL)isHardwarePoweredOn {
  return self.central.state == CBCentralManagerStatePoweredOn;
}

@end

#pragma mark - Peripheral Scoped Scanning

@implementation CBPeripheralScan

- (id)initWithPeripheral:(CBPeripheral *_Nonnull)peripheral
                    rssi:(NSNumber *)rssi
                delegate:(id<CBPeripheralScanDelegate, CBPeripheralServiceScanDelegate>)delegate {
  if (self = [super init]) {
    [self updateLastActivity];
    self.peripheral = peripheral;
    // This is potentially a cycle in 9.0 (weak -> assign in API change), however we are tracking
    // this scan and when it's done we will undo the cycle.
    self.peripheral.delegate = self;
    self.delegate = delegate;
    self.rssi = rssi;
    self.serviceScans = [NSMutableSet new];
  }
  return self;
}

- (void)start:(NSArray<CBUUID *> *_Nullable)scanUuids {
  if (self.peripheral.state != CBPeripheralStateConnected) {
    CBErrorLog(@"Peripheral not connected -- can't discover services on %@", self.peripheral);
    [self.delegate peripheralScanDidComplete:self];
    return;
  }
  [self updateLastActivity];
  CBDebugLog(@"Discovering services on %@", self.peripheral);
  if (scanUuids.count) {
    [self.peripheral discoverServices:scanUuids];
  } else {
    [self.peripheral discoverServices:nil];
  }
}

#pragma mark - CBPeripheralDelegate callbacks

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(nullable NSError *)error {
  [self updateLastActivity];
  if (error) {
    CBErrorLog(@"didDiscoverServices on %@ error %@", peripheral, error);
    [self.delegate peripheralScanDidComplete:self];
    return;
  }
  if (!peripheral.services.count) {
    CBDebugLog(@"Peripheral %@ has no services", peripheral);
    [self.delegate peripheralScanDidComplete:self];
    return;
  }
  // Filter for Vanadium services
  NSMutableSet<CBService *> *discoveredServices = [NSMutableSet new];
  NSMutableSet<CBUUID *> *discoveredUuids = [NSMutableSet new];
  for (CBService *service in peripheral.services) {
    if ([self.delegate uuidMatchesScanFilter:service.UUID]) {
      [discoveredServices addObject:service];
      [discoveredUuids addObject:service.UUID];
    }
  }
  NSMutableSet *knownUuids = [self seenUUIDs];
  // Find the ones we previously knew about, but aren't part of the current set.
  [knownUuids minusSet:discoveredUuids];
  for (CBUUID *expiredService in knownUuids) {
    CBPeripheralServiceScan *existingScan = [self scanForServiceUUID:expiredService];
    if (existingScan) {
      CBInfoLog(@"Removing service that isn't part of the current discovered set: %@",
                existingScan);
      [self.serviceScans removeObject:existingScan];
      [self.completedScans removeObject:existingScan];
    }
  }
  // Scan anything new
  for (CBService *service in discoveredServices) {
    CBPeripheralServiceScan *existingScan = [self scanForServiceUUID:service.UUID];
    if (existingScan) {
      CBDebugLog(@"Ignoring known service UUID %@", service.UUID);
      return;
    }
    CBDebugLog(@"Starting scan for new service UUID %@", service.UUID);
    CBPeripheralServiceScan *serviceScan =
        [[CBPeripheralServiceScan alloc] initWithService:service rssi:self.rssi delegate:self];
    [self.serviceScans addObject:serviceScan];
    [serviceScan start];
  }
}

- (void)peripheral:(CBPeripheral *)peripheral
 didModifyServices:(NSArray<CBService *> *)invalidatedServices {
  [self updateLastActivity];
  CBInfoLog(@"peripheral %@ didModifyServices by invalidating %@", peripheral, invalidatedServices);
  NSMutableArray *invalidatedScans = [NSMutableArray new];
  for (CBPeripheralServiceScan *scan in self.serviceScans) {
    for (CBService *invalidatedService in invalidatedServices) {
      if ([scan.service.UUID isEqual:invalidatedService.UUID]) {
        // Because the upper chain might modify self.serviceScans we must first extract this scan
        // before we can safety end the scan.
        [invalidatedScans addObject:scan];
        break;  // out of inner loop only
      }
    }
  }
  for (CBPeripheralServiceScan *scan in invalidatedScans) {
    CBDebugLog(@"Invalidated scan %@", scan);
    [self serviceScanDidComplete:scan];
  }
}

- (void)peripheral:(CBPeripheral *)peripheral
    didDiscoverCharacteristicsForService:(CBService *)service
                                   error:(nullable NSError *)error {
  [self updateLastActivity];
  // Forward to the right scan
  for (CBPeripheralServiceScan *scan in self.serviceScans) {
    if ([scan.service.UUID isEqual:service.UUID]) {
      [scan peripheral:peripheral didDiscoverCharacteristicsForService:service error:error];
      break;
    }
  }
}

- (void)peripheral:(CBPeripheral *)peripheral
    didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic
                              error:(nullable NSError *)error {
  [self updateLastActivity];
  // Forward to the right scan
  for (CBPeripheralServiceScan *scan in self.serviceScans) {
    if ([scan.service.UUID isEqual:characteristic.service.UUID]) {
      [scan peripheral:peripheral didUpdateValueForCharacteristic:characteristic error:error];
      break;
    }
  }
}

#pragma mark - Scan delegate

- (void)serviceScanDidComplete:(CBPeripheralServiceScan *)serviceScan {
  [self.completedScans addObject:serviceScan];
  [self.delegate serviceScanDidComplete:serviceScan];
  if (self.completedScans.count == self.serviceScans.count) {
    // We're done with this periperal scan
    [self.delegate peripheralScanDidComplete:self];
  }
}

- (void)updateLastActivity {
  self.lastActivity = [NSDate date];
}

#pragma mark - CBPeripheralScan Util

- (NSMutableSet<CBUUID *> *_Nonnull)seenUUIDs {
  NSMutableSet<CBUUID *> *set = [NSMutableSet new];
  for (CBPeripheralServiceScan *scan in self.serviceScans) {
    [set addObject:scan.service.UUID];
  }
  for (CBPeripheralServiceScan *scan in self.completedScans) {
    [set addObject:scan.service.UUID];
  }
  return set;
}

- (CBPeripheralServiceScan *_Nullable)scanForServiceUUID:(CBUUID *)serviceUUID {
  for (CBPeripheralServiceScan *scan in self.serviceScans) {
    if ([scan.service.UUID isEqual:serviceUUID]) {
      return scan;
    }
  }
  return nil;
}

- (NSString *)description {
  NSString *format = @"[CBPeripheralScan peripheral=%@ rssi=%@ serviceScans=%@ completedScans=%@]";
  return [NSString
      stringWithFormat:format, self.peripheral, self.rssi, self.serviceScans, self.completedScans];
}

@end

#pragma mark - Peripheral's Service Scoped Scanning

@implementation CBPeripheralServiceScan

- (id)initWithService:(CBService *_Nonnull)service
                 rssi:(NSNumber *)rssi
             delegate:(id<CBPeripheralServiceScanDelegate>)delegate {
  if (self = [super init]) {
    self.service = service;
    self.delegate = delegate;
    self.rssi = rssi;
    self.queryingCharacteristics = [NSMutableSet new];
    self.characteristics = [NSMutableDictionary new];
  }
  return self;
}

- (void)start {
  NSArray<CBUUID *> *uuids = [CBPeripheralServiceScan possibleCharacteristicUUIDs];
  if (self.service.peripheral.state != CBPeripheralStateConnected) {
    CBErrorLog(@"Can't discover characteristics for service %@ -- we're not connected",
               self.service.UUID);
    [self.delegate serviceScanDidComplete:self];
    return;
  }
  [self.delegate updateLastActivity];
  [self.service.peripheral discoverCharacteristics:uuids forService:self.service];
}

#pragma mark - CBPeripheralDelegate callbacks relevant to this service

- (void)peripheral:(CBPeripheral *)peripheral
    didDiscoverCharacteristicsForService:(CBService *)service
                                   error:(nullable NSError *)error {
  CBDebugLog(@"didDiscoverCharacteristicsForService %@ error %@", service.UUID, error);
  [self.delegate updateLastActivity];
  if (error) {
    CBErrorLog(@"Unable to discover characteristics for service: %@", service.UUID);
    [self.delegate serviceScanDidComplete:self];
    return;
  }
  if (!service.characteristics.count) {
    CBInfoLog(@"No characteristics for service %@", service.UUID);
    [self.delegate serviceScanDidComplete:self];
  } else {
    CBInfoLog(@"Getting characteristics for service %@", service.UUID);
    for (CBCharacteristic *characteristic in service.characteristics) {
      if ((characteristic.properties & CBCharacteristicPropertyRead) == 0) {
        CBDebugLog(@"Skipping un-readable characteristic %@", characteristic);
      } else {
        [self.queryingCharacteristics addObject:characteristic];
        CBDebugLog(@"Reading value for characteristic %@", characteristic);
        [peripheral readValueForCharacteristic:characteristic];
      }
    }
  }
}

- (void)peripheral:(CBPeripheral *)peripheral
    didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic
                              error:(nullable NSError *)error {
  CBDebugLog(@"didUpdateValueForCharacteristic %@ error %@", characteristic, error);
  [self.delegate updateLastActivity];
  if (error) {
    CBErrorLog(@"Unable to get value for characteristic %@ due to error %@", characteristic, error);
  } else {
    NSData *data = characteristic.value;
    if (data.length) {
      self.characteristics[characteristic.UUID] = data;
    }
  }
  // Are we done with this service scan?
  [self.queryingCharacteristics removeObject:characteristic];
  if (!self.queryingCharacteristics.count) {
    [self.delegate serviceScanDidComplete:self];
  } else {
    CBDebugLog(@"Waiting on %d characteristics", self.queryingCharacteristics.count);
  }
}

#pragma mark - CBPeripheralServiceScan Util

- (NSString *)description {
  return [NSString stringWithFormat:@"[CBPeripheralServiceScan service=%@ rssi=%@ "
                                    @"queryingCharacteristics=%@ characteristics=%@]",
                                    self.service.UUID, self.rssi, self.queryingCharacteristics,
                                    self.characteristics];
}

+ (NSArray<CBUUID *> *)possibleCharacteristicUUIDs {
  static NSArray *_cached = nil;
  if (!_cached) {
    // Compute all possible UUIDs
    NSMutableArray *uuids = [NSMutableArray new];
    for (int i = 0; i < kMaxNumPackedServices; i++) {
      for (int j = 0; j < kMaxNumPackedCharacteristicsPerService; j++) {
        NSString *uuid = [NSString stringWithFormat:kPackedCharacteristicUuidFmt, i, j];
        [uuids addObject:[CBUUID UUIDWithString:uuid]];
      }
    }
    _cached = uuids;
  }
  return _cached;
}

@end
