/*
 *
 *    Copyright (c) 2020-2021 Project CHIP Authors
 *    Copyright (c) 2015-2017 Nest Labs, 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.
 */

/**
 *    @file
 *          Provides an implementation of BleConnectionDelegate for Darwin platforms.
 */

#if !__has_feature(objc_arc)
#error This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC).
#endif

#include <ble/BleConfig.h>
#include <ble/BleError.h>
#include <ble/BleLayer.h>
#include <ble/BleUUID.h>
#include <lib/support/logging/CHIPLogging.h>
#include <platform/CHIPDeviceLayer.h>
#include <platform/Darwin/BleConnectionDelegate.h>
#include <platform/Darwin/BleScannerDelegate.h>
#include <platform/LockTracker.h>
#include <setup_payload/SetupPayload.h>

#import "UUIDHelper.h"

using namespace chip::Ble;

constexpr uint64_t kScanningWithDiscriminatorTimeoutInSeconds = 60;
constexpr uint64_t kScanningWithoutDelegateTimeoutInSeconds = 120;
constexpr uint64_t kCachePeripheralTimeoutInSeconds
    = static_cast<uint64_t>(CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MAX / 1000.0 * 8.0 * 0.625);
constexpr const char * kBleWorkQueueName = "org.csa-iot.matter.framework.ble.workqueue";

typedef NS_ENUM(uint8_t, BleConnectionMode) {
    kUndefined = 0,
    kScanningWithoutDelegate,
    kScanning,
    kConnecting,
};

@interface BleConnection : NSObject <CBCentralManagerDelegate, CBPeripheralDelegate>

@property (strong, nonatomic) dispatch_queue_t chipWorkQueue;
@property (strong, nonatomic) dispatch_queue_t workQueue;
@property (strong, nonatomic) CBCentralManager * centralManager;
@property (strong, nonatomic) CBPeripheral * peripheral;
@property (strong, nonatomic) CBUUID * shortServiceUUID;
@property (nonatomic, readonly, nullable) dispatch_source_t timer;
@property (nonatomic, readonly) BleConnectionMode currentMode;
@property (strong, nonatomic) NSMutableDictionary<CBPeripheral *, NSDictionary *> * cachedPeripherals;
@property (unsafe_unretained, nonatomic) bool found;
@property (unsafe_unretained, nonatomic) chip::SetupDiscriminator deviceDiscriminator;
@property (unsafe_unretained, nonatomic) void * appState;
@property (unsafe_unretained, nonatomic) BleConnectionDelegate::OnConnectionCompleteFunct onConnectionComplete;
@property (unsafe_unretained, nonatomic) BleConnectionDelegate::OnConnectionErrorFunct onConnectionError;
@property (unsafe_unretained, nonatomic) chip::DeviceLayer::BleScannerDelegate * scannerDelegate;
@property (unsafe_unretained, nonatomic) chip::Ble::BleLayer * mBleLayer;

- (id)initWithQueue:(dispatch_queue_t)queue;
- (id)initWithDelegate:(chip::DeviceLayer::BleScannerDelegate *)delegate queue:(dispatch_queue_t)queue;
- (id)initWithDiscriminator:(const chip::SetupDiscriminator &)deviceDiscriminator queue:(dispatch_queue_t)queue;
- (void)setBleLayer:(chip::Ble::BleLayer *)bleLayer;
- (void)start;
- (void)stop;
- (void)updateWithDelegate:(chip::DeviceLayer::BleScannerDelegate *)delegate;
- (void)updateWithDiscriminator:(const chip::SetupDiscriminator &)deviceDiscriminator;
- (void)updateWithPeripheral:(CBPeripheral *)peripheral;
- (BOOL)isScanningWithoutDelegate;
- (BOOL)isScanning;
- (BOOL)isConnecting;
- (void)addPeripheralToCache:(CBPeripheral *)peripheral data:(NSData *)data;
- (void)removePeripheralFromCache:(CBPeripheral *)peripheral;
- (void)removePeripheralsFromCache;

@end

namespace chip {
namespace DeviceLayer {
    namespace Internal {
        BleConnection * ble;
        dispatch_queue_t bleWorkQueue;

        void BleConnectionDelegateImpl::NewConnection(
            Ble::BleLayer * bleLayer, void * appState, const SetupDiscriminator & inDeviceDiscriminator)
        {
            assertChipStackLockedByCurrentThread();

            // Make a copy of the device discriminator for the block to capture.
            SetupDiscriminator deviceDiscriminator = inDeviceDiscriminator;

            ChipLogProgress(Ble, "%s", __FUNCTION__);
            if (!bleWorkQueue) {
                bleWorkQueue = dispatch_queue_create(kBleWorkQueueName, DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL);
            }

            dispatch_async(bleWorkQueue, ^{
                // If the previous connection delegate was not a try to connect to something, just reuse it instead of
                // creating a brand new connection but update the discriminator and the ble layer members.
                if (ble and ![ble isConnecting]) {
                    [ble setBleLayer:bleLayer];
                    ble.appState = appState;
                    ble.onConnectionComplete = OnConnectionComplete;
                    ble.onConnectionError = OnConnectionError;
                    [ble updateWithDiscriminator:deviceDiscriminator];
                    return;
                }

                [ble stop];
                ble = [[BleConnection alloc] initWithDiscriminator:deviceDiscriminator queue:bleWorkQueue];
                [ble setBleLayer:bleLayer];
                ble.appState = appState;
                ble.onConnectionComplete = OnConnectionComplete;
                ble.onConnectionError = OnConnectionError;
                ble.centralManager = [ble.centralManager initWithDelegate:ble queue:bleWorkQueue];
            });
        }

        void BleConnectionDelegateImpl::NewConnection(Ble::BleLayer * bleLayer, void * appState, BLE_CONNECTION_OBJECT connObj)
        {
            assertChipStackLockedByCurrentThread();

            ChipLogProgress(Ble, "%s", __FUNCTION__);

            if (!bleWorkQueue) {
                bleWorkQueue = dispatch_queue_create(kBleWorkQueueName, DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL);
            }

            dispatch_async(bleWorkQueue, ^{
                // The BLE_CONNECTION_OBJECT represent a CBPeripheral object. In order for it to be valid the central
                // manager needs to still be running.
                if (!ble || [ble isConnecting]) {
                    if (OnConnectionError) {
                        auto workQueue = chip::DeviceLayer::PlatformMgrImpl().GetWorkQueue();
                        dispatch_async(workQueue, ^{
                            OnConnectionError(appState, CHIP_ERROR_INCORRECT_STATE);
                        });
                    }
                    return;
                }

                [ble setBleLayer:bleLayer];
                ble.appState = appState;
                ble.onConnectionComplete = OnConnectionComplete;
                ble.onConnectionError = OnConnectionError;
                [ble updateWithPeripheral:(__bridge CBPeripheral *) connObj];
            });
        }

        void BleConnectionDelegateImpl::StartScan(BleScannerDelegate * delegate)
        {
            assertChipStackLockedByCurrentThread();

            ChipLogProgress(Ble, "%s", __FUNCTION__);

            if (!bleWorkQueue) {
                bleWorkQueue = dispatch_queue_create(kBleWorkQueueName, DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL);
            }

            dispatch_async(bleWorkQueue, ^{
                // If the previous connection delegate was not a try to connect to something, just reuse it instead of
                // creating a brand new connection but update the discriminator and the ble layer members.
                if (ble and ![ble isConnecting]) {
                    [ble updateWithDelegate:delegate];
                    return;
                }

                [ble stop];
                ble = [[BleConnection alloc] initWithDelegate:delegate queue:bleWorkQueue];
                ble.onConnectionComplete = OnConnectionComplete;
                ble.onConnectionError = OnConnectionError;
                ble.centralManager = [ble.centralManager initWithDelegate:ble queue:bleWorkQueue];
            });
        }

        void BleConnectionDelegateImpl::StopScan()
        {
            assertChipStackLockedByCurrentThread();
            CancelConnection();
        }

        CHIP_ERROR BleConnectionDelegateImpl::CancelConnection()
        {
            assertChipStackLockedByCurrentThread();

            ChipLogProgress(Ble, "%s", __FUNCTION__);
            if (bleWorkQueue == nil) {
                return CHIP_NO_ERROR;
            }

            dispatch_async(bleWorkQueue, ^{
                [ble stop];
                ble = nil;
            });

            bleWorkQueue = nil;
            return CHIP_NO_ERROR;
        }
    } // namespace Internal
} // namespace DeviceLayer
} // namespace chip

@interface BleConnection ()
@end

@implementation BleConnection

- (id)initWithQueue:(dispatch_queue_t)queue
{
    self = [super init];
    if (self) {
        self.shortServiceUUID = [UUIDHelper GetShortestServiceUUID:&chip::Ble::CHIP_BLE_SVC_ID];
        _chipWorkQueue = chip::DeviceLayer::PlatformMgrImpl().GetWorkQueue();
        _workQueue = queue;
        _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
        _centralManager = [CBCentralManager alloc];
        _found = false;
        _cachedPeripherals = [[NSMutableDictionary alloc] init];
        _currentMode = kUndefined;

        dispatch_source_set_event_handler(_timer, ^{
            [self stop];
            [self dispatchConnectionError:BLE_ERROR_APP_CLOSED_CONNECTION];
        });
    }

    return self;
}

- (id)initWithDelegate:(chip::DeviceLayer::BleScannerDelegate *)delegate queue:(dispatch_queue_t)queue
{
    self = [self initWithQueue:queue];
    if (self) {
        _scannerDelegate = delegate;
        _currentMode = (delegate == nullptr) ? kScanningWithoutDelegate : kScanning;
        [self resetTimer];
    }

    return self;
}

- (id)initWithDiscriminator:(const chip::SetupDiscriminator &)deviceDiscriminator queue:(dispatch_queue_t)queue
{
    self = [self initWithQueue:queue];
    if (self) {
        _deviceDiscriminator = deviceDiscriminator;
        _currentMode = kConnecting;
        [self resetTimer];
    }

    return self;
}

- (BOOL)isScanningWithoutDelegate
{
    return _currentMode == kScanningWithoutDelegate;
}

- (BOOL)isScanning
{
    return _currentMode == kScanning;
}

- (BOOL)isConnecting
{
    return _currentMode == kConnecting;
}

- (void)resetTimer
{
    if ([self isConnecting]) {
        auto timeout = static_cast<int64_t>(kScanningWithDiscriminatorTimeoutInSeconds * NSEC_PER_SEC);
        dispatch_source_set_timer(_timer, dispatch_walltime(nullptr, timeout), DISPATCH_TIME_FOREVER, 5 * NSEC_PER_SEC);
    } else if ([self isScanningWithoutDelegate]) {
        auto timeout = static_cast<int64_t>(kScanningWithoutDelegateTimeoutInSeconds * NSEC_PER_SEC);
        dispatch_source_set_timer(_timer, dispatch_walltime(nullptr, timeout), DISPATCH_TIME_FOREVER, 5 * NSEC_PER_SEC);
    } else if ([self isScanning]) {
        dispatch_source_cancel(_timer);
    } else {
        // It should not happens.
        [self stop];
        [self dispatchConnectionError:CHIP_ERROR_INCORRECT_STATE];
    }
}

// All our callback dispatch must happen on _chipWorkQueue
- (void)dispatchConnectionError:(CHIP_ERROR)error
{
    dispatch_async(_chipWorkQueue, ^{
        if (self.onConnectionError != nil) {
            self.onConnectionError(self.appState, error);
        }
    });
}

- (void)dispatchConnectionComplete:(CBPeripheral *)peripheral
{
    dispatch_async(_chipWorkQueue, ^{
        if (self.onConnectionComplete != nil) {
            self.onConnectionComplete(self.appState, (__bridge void *) peripheral);
        }
    });
}

// Start CBCentralManagerDelegate

- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
    switch (central.state) {
    case CBManagerStatePoweredOn:
        ChipLogDetail(Ble, "CBManagerState: ON");
        [self start];
        break;
    case CBManagerStatePoweredOff:
        ChipLogDetail(Ble, "CBManagerState: OFF");
        [self stop];
        [self dispatchConnectionError:BLE_ERROR_APP_CLOSED_CONNECTION];
        break;
    case CBManagerStateUnauthorized:
        ChipLogDetail(Ble, "CBManagerState: Unauthorized");
        break;
    case CBManagerStateResetting:
        ChipLogDetail(Ble, "CBManagerState: RESETTING");
        break;
    case CBManagerStateUnsupported:
        ChipLogDetail(Ble, "CBManagerState: UNSUPPORTED");
        break;
    case CBManagerStateUnknown:
        ChipLogDetail(Ble, "CBManagerState: UNKNOWN");
        break;
    }
}

- (void)centralManager:(CBCentralManager *)central
    didDiscoverPeripheral:(CBPeripheral *)peripheral
        advertisementData:(NSDictionary *)advertisementData
                     RSSI:(NSNumber *)RSSI
{
    NSDictionary * servicesData = [advertisementData objectForKey:CBAdvertisementDataServiceDataKey];
    NSData * serviceData;
    for (CBUUID * serviceUUID in servicesData) {
        if ([serviceUUID.data isEqualToData:_shortServiceUUID.data]) {
            serviceData = [servicesData objectForKey:serviceUUID];
            break;
        }
    }

    if (!serviceData) {
        return;
    }

    NSNumber * isConnectable = [advertisementData objectForKey:CBAdvertisementDataIsConnectable];
    if ([isConnectable boolValue] == NO) {
        ChipLogError(Ble, "A device (%p) with a matching Matter UUID has been discovered but it is not connectable.", peripheral);
        return;
    }

    const uint8_t * bytes = (const uint8_t *) [serviceData bytes];
    if ([serviceData length] != 8) {
        NSMutableString * hexString = [NSMutableString stringWithCapacity:([serviceData length] * 2)];
        for (NSUInteger i = 0; i < [serviceData length]; i++) {
            [hexString appendString:[NSString stringWithFormat:@"%02lx", (unsigned long) bytes[i]]];
        }
        ChipLogError(Ble,
            "A device (%p) with a matching Matter UUID has been discovered but the service data len does not match our expectation "
            "(serviceData = %s)",
            peripheral, [hexString UTF8String]);
        return;
    }

    uint8_t opCode = bytes[0];
    if (opCode != 0 && opCode != 1) {
        ChipLogError(Ble,
            "A device (%p) with a matching Matter UUID has been discovered but the service data opCode not match our expectation "
            "(opCode = %u).",
            peripheral, opCode);
        return;
    }

    uint16_t discriminator = (bytes[1] | (bytes[2] << 8)) & 0xfff;

    if ([self isConnecting]) {
        if (![self checkDiscriminator:discriminator]) {
            ChipLogError(Ble,
                "A device (%p) with a matching Matter UUID has been discovered but the service data discriminator not match our "
                "expectation (discriminator = %u).",
                peripheral, discriminator);
            return;
        }

        ChipLogProgress(Ble, "Connecting to device %p with discriminator: %d", peripheral, discriminator);
        [self connect:peripheral];
        [self stopScanning];
    } else {
        [self addPeripheralToCache:peripheral data:serviceData];
    }
}

- (BOOL)checkDiscriminator:(uint16_t)discriminator
{
    return _deviceDiscriminator.MatchesLongDiscriminator(discriminator);
}

- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
    [peripheral setDelegate:self];
    [peripheral discoverServices:nil];
}

// End CBCentralManagerDelegate

// Start CBPeripheralDelegate

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
{
    if (nil != error) {
        ChipLogError(Ble, "BLE:Error finding Chip Service in the device: [%s]", [error.localizedDescription UTF8String]);
    }

    for (CBService * service in peripheral.services) {
        if ([service.UUID.data isEqualToData:_shortServiceUUID.data] && !self.found) {
            [peripheral discoverCharacteristics:nil forService:service];
            self.found = true;
            break;
        }
    }

    if (!self.found || error != nil) {
        ChipLogError(Ble, "Service not found on the device.");
        [self dispatchConnectionError:CHIP_ERROR_INCORRECT_STATE];
    }
}

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
{
    if (nil != error) {
        ChipLogError(
            Ble, "BLE:Error finding Characteristics in Chip service on the device: [%s]", [error.localizedDescription UTF8String]);
    }

    // XXX error ?
    [self dispatchConnectionComplete:peripheral];
}

- (void)peripheral:(CBPeripheral *)peripheral
    didWriteValueForCharacteristic:(CBCharacteristic *)characteristic
                             error:(NSError *)error
{
    if (nil == error) {
        chip::Ble::ChipBleUUID svcId;
        chip::Ble::ChipBleUUID charId;
        [BleConnection fillServiceWithCharacteristicUuids:characteristic svcId:&svcId charId:&charId];
        dispatch_async(_chipWorkQueue, ^{
            _mBleLayer->HandleWriteConfirmation((__bridge void *) peripheral, &svcId, &charId);
        });
    } else {
        ChipLogError(
            Ble, "BLE:Error writing Characteristics in Chip service on the device: [%s]", [error.localizedDescription UTF8String]);
        dispatch_async(_chipWorkQueue, ^{
            _mBleLayer->HandleConnectionError((__bridge void *) peripheral, BLE_ERROR_GATT_WRITE_FAILED);
        });
    }
}

- (void)peripheral:(CBPeripheral *)peripheral
    didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic
                                          error:(NSError *)error
{
    bool isNotifying = characteristic.isNotifying;

    if (nil == error) {
        chip::Ble::ChipBleUUID svcId;
        chip::Ble::ChipBleUUID charId;
        [BleConnection fillServiceWithCharacteristicUuids:characteristic svcId:&svcId charId:&charId];

        dispatch_async(_chipWorkQueue, ^{
            if (isNotifying) {
                _mBleLayer->HandleSubscribeComplete((__bridge void *) peripheral, &svcId, &charId);
            } else {
                _mBleLayer->HandleUnsubscribeComplete((__bridge void *) peripheral, &svcId, &charId);
            }
        });
    } else {
        ChipLogError(Ble, "BLE:Error subscribing/unsubcribing some characteristic on the device: [%s]",
            [error.localizedDescription UTF8String]);
        dispatch_async(_chipWorkQueue, ^{
            if (isNotifying) {
                // we're still notifying, so we must failed the unsubscription
                _mBleLayer->HandleConnectionError((__bridge void *) peripheral, BLE_ERROR_GATT_UNSUBSCRIBE_FAILED);
            } else {
                // we're not notifying, so we must failed the subscription
                _mBleLayer->HandleConnectionError((__bridge void *) peripheral, BLE_ERROR_GATT_SUBSCRIBE_FAILED);
            }
        });
    }
}

- (void)peripheral:(CBPeripheral *)peripheral
    didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic
                              error:(NSError *)error
{
    if (nil == error) {
        chip::Ble::ChipBleUUID svcId;
        chip::Ble::ChipBleUUID charId;
        [BleConnection fillServiceWithCharacteristicUuids:characteristic svcId:&svcId charId:&charId];

        dispatch_async(_chipWorkQueue, ^{
            // build a inet buffer from the rxEv and send to blelayer.
            auto msgBuf = chip::System::PacketBufferHandle::NewWithData(characteristic.value.bytes, characteristic.value.length);

            if (msgBuf.IsNull()) {
                ChipLogError(Ble, "Failed at allocating buffer for incoming BLE data");
                _mBleLayer->HandleConnectionError((__bridge void *) peripheral, CHIP_ERROR_NO_MEMORY);
            } else if (!_mBleLayer->HandleIndicationReceived((__bridge void *) peripheral, &svcId, &charId, std::move(msgBuf))) {
                // since this error comes from device manager core
                // we assume it would do the right thing, like closing the connection
                ChipLogError(Ble, "Failed at handling incoming BLE data");
            }
        });
    } else {
        ChipLogError(
            Ble, "BLE:Error receiving indication of Characteristics on the device: [%s]", [error.localizedDescription UTF8String]);
        dispatch_async(_chipWorkQueue, ^{
            _mBleLayer->HandleConnectionError((__bridge void *) peripheral, BLE_ERROR_GATT_INDICATE_FAILED);
        });
    }
}

// End CBPeripheralDelegate

- (void)start
{
    dispatch_resume(_timer);

    // If a peripheral has already been found, try to connect to it once BLE starts,
    // otherwise start scanning to find the peripheral to connect to.
    if (_peripheral != nil) {
        [self connect:_peripheral];
    } else {
        [self startScanning];
    }
}

- (void)stop
{
    [self stopScanning];
    [self removePeripheralsFromCache];
    _cachedPeripherals = nil;
    _scannerDelegate = nil;

    if (!_centralManager || !_peripheral) {
        return;
    }

    // Properly closing the underlying ble connections needs to happens
    // on the chip work queue. At the same time the SDK is trying to
    // properly unsubscribe and shutdown the connection, so if we nullify
    // the centralManager and the peripheral members too early it won't be
    // able to reach those.
    // This is why closing connections happens as 2 async steps.
    dispatch_async(_chipWorkQueue, ^{
        _mBleLayer->CloseAllBleConnections();

        dispatch_async(_workQueue, ^{
            _centralManager.delegate = nil;
            _centralManager = nil;
            _peripheral = nil;
        });
    });
}

- (void)startScanning
{
    if (!_centralManager) {
        return;
    }

    [_centralManager scanForPeripheralsWithServices:@[ _shortServiceUUID ] options:nil];
}

- (void)stopScanning
{
    if (!_centralManager) {
        return;
    }
    dispatch_source_cancel(_timer);
    [_centralManager stopScan];
}

- (void)connect:(CBPeripheral *)peripheral
{
    if (!_centralManager || !peripheral) {
        return;
    }

    _peripheral = peripheral;
    [_centralManager connectPeripheral:peripheral options:nil];
}

- (void)updateWithDelegate:(chip::DeviceLayer::BleScannerDelegate *)delegate
{
    _scannerDelegate = delegate;
    _currentMode = (delegate == nullptr) ? kScanningWithoutDelegate : kScanning;

    if (_currentMode == kScanning) {
        for (CBPeripheral * cachedPeripheral in _cachedPeripherals) {
            NSData * serviceData = _cachedPeripherals[cachedPeripheral][@"data"];
            dispatch_async(_chipWorkQueue, ^{
                ChipBLEDeviceIdentificationInfo info;
                memcpy(&info, [serviceData bytes], sizeof(info));
                _scannerDelegate->OnBleScanAdd((__bridge void *) cachedPeripheral, info);
            });
        }
    }

    [self resetTimer];
}

- (void)updateWithDiscriminator:(const chip::SetupDiscriminator &)deviceDiscriminator
{
    _deviceDiscriminator = deviceDiscriminator;
    _scannerDelegate = nil;
    _currentMode = kConnecting;

    CBPeripheral * peripheral = nil;
    for (CBPeripheral * cachedPeripheral in _cachedPeripherals) {
        NSData * serviceData = _cachedPeripherals[cachedPeripheral][@"data"];
        ChipBLEDeviceIdentificationInfo info;
        memcpy(&info, [serviceData bytes], sizeof(info));

        if ([self checkDiscriminator:info.GetDeviceDiscriminator()]) {
            peripheral = cachedPeripheral;
            break;
        }
    }

    [self removePeripheralsFromCache];

    if (peripheral) {
        ChipLogProgress(Ble, "Connecting to cached device: %p", peripheral);
        [self connect:peripheral];
        [self stopScanning];
    } else {
        [self resetTimer];
    }
}

- (void)updateWithPeripheral:(CBPeripheral *)peripheral
{
    _scannerDelegate = nil;
    _currentMode = kConnecting;

    ChipLogProgress(Ble, "Connecting to device: %p", peripheral);
    [self connect:peripheral];
    [self stopScanning];
}

- (void)addPeripheralToCache:(CBPeripheral *)peripheral data:(NSData *)data
{
    dispatch_source_t timeoutTimer;

    bool shouldLogData = true;
    if ([_cachedPeripherals objectForKey:peripheral]) {
        shouldLogData = ![data isEqualToData:_cachedPeripherals[peripheral][@"data"]];
        if (shouldLogData) {
            ChipLogProgress(Ble, "Updating peripheral %p from the cache", peripheral);
        }

        timeoutTimer = _cachedPeripherals[peripheral][@"timer"];
    } else {
        ChipLogProgress(Ble, "Adding peripheral %p to the cache", peripheral);
        auto delegate = _scannerDelegate;
        if (delegate) {
            dispatch_async(_chipWorkQueue, ^{
                ChipBLEDeviceIdentificationInfo info;
                auto bytes = (const uint8_t *) [data bytes];
                memcpy(&info, bytes, sizeof(info));
                delegate->OnBleScanAdd((__bridge void *) peripheral, info);
            });
        }

        timeoutTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, _workQueue);
        dispatch_source_set_event_handler(timeoutTimer, ^{
            [self removePeripheralFromCache:peripheral];
        });
        dispatch_resume(timeoutTimer);
    }

    auto timeout = static_cast<int64_t>(kCachePeripheralTimeoutInSeconds * NSEC_PER_SEC);
    dispatch_source_set_timer(timeoutTimer, dispatch_walltime(nullptr, timeout), DISPATCH_TIME_FOREVER, 5 * NSEC_PER_SEC);

    _cachedPeripherals[peripheral] = @{
        @"data" : data,
        @"timer" : timeoutTimer,
    };

    if (shouldLogData) {
        ChipBLEDeviceIdentificationInfo info;
        auto bytes = (const uint8_t *) [data bytes];
        memcpy(&info, bytes, sizeof(info));

        ChipLogProgress(Ble, "  - Version: %u", info.GetAdvertisementVersion());
        ChipLogProgress(Ble, "  - Discriminator: %u", info.GetDeviceDiscriminator());
        ChipLogProgress(Ble, "  - VendorId: %u", info.GetVendorId());
        ChipLogProgress(Ble, "  - ProductId: %u", info.GetVendorId());
    }
}

- (void)removePeripheralFromCache:(CBPeripheral *)peripheral
{
    auto entry = [_cachedPeripherals objectForKey:peripheral];
    if (entry) {
        ChipLogProgress(Ble, "Removing peripheral %p from the cache", peripheral);

        dispatch_source_cancel(entry[@"timer"]);
        [_cachedPeripherals removeObjectForKey:peripheral];

        auto delegate = _scannerDelegate;
        if (delegate) {
            dispatch_async(_chipWorkQueue, ^{
                delegate->OnBleScanRemove((__bridge void *) peripheral);
            });
        }
    }
}

- (void)removePeripheralsFromCache
{
    for (CBPeripheral * peripheral in [_cachedPeripherals allKeys]) {
        [self removePeripheralFromCache:peripheral];
    }
}

/**
 * private static method to copy service and characteristic UUIDs from CBCharacteristic to a pair of ChipBleUUID objects.
 * this is used in calls into Chip layer to decouple it from CoreBluetooth
 *
 * @param[in] characteristic the source characteristic
 * @param[in] svcId the destination service UUID
 * @param[in] charId the destination characteristic UUID
 *
 */
+ (void)fillServiceWithCharacteristicUuids:(CBCharacteristic *)characteristic
                                     svcId:(chip::Ble::ChipBleUUID *)svcId
                                    charId:(chip::Ble::ChipBleUUID *)charId
{
    static const size_t FullUUIDLength = 16;
    if ((FullUUIDLength != sizeof(charId->bytes)) || (FullUUIDLength != sizeof(svcId->bytes))
        || (FullUUIDLength != characteristic.UUID.data.length)) {
        // we're dead. we expect the data length to be the same (16-byte) across the board
        ChipLogError(Ble, "UUID of characteristic is incompatible");
        return;
    }

    memcpy(charId->bytes, characteristic.UUID.data.bytes, sizeof(charId->bytes));
    memset(svcId->bytes, 0, sizeof(svcId->bytes));

    // Expand service UUID back to 16-byte long as that's what the BLE Layer expects
    // this is a buffer pre-filled with BLE service UUID Base
    // byte 0 to 3 are reserved for shorter versions of BLE service UUIDs
    // For 4-byte service UUIDs, all bytes from 0 to 3 are used
    // For 2-byte service UUIDs, byte 0 and 1 shall be 0
    uint8_t serviceFullUUID[FullUUIDLength]
        = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB };

    switch (characteristic.service.UUID.data.length) {
    case 2:
        // copy the 2-byte service UUID onto the right offset
        memcpy(serviceFullUUID + 2, characteristic.service.UUID.data.bytes, 2);
        break;
    case 4:
        // flow through
    case 16:
        memcpy(serviceFullUUID, characteristic.service.UUID.data.bytes, characteristic.service.UUID.data.length);
        break;
    default:
        // we're dead. we expect the data length to be the same (16-byte) across the board
        ChipLogError(Ble, "Service UUIDs are incompatible");
    }
    memcpy(svcId->bytes, serviceFullUUID, sizeof(svcId->bytes));
}

- (void)setBleLayer:(chip::Ble::BleLayer *)bleLayer
{
    _mBleLayer = bleLayer;
}

@end
