//
//  RNBluetooth.m
//  qm-hardwarekit
//
//  Created by 夏迎霖 on 2017/11/30.
//  Copyright © 2017年 Marc Shilling. All rights reserved.
//

#import "RNBluetoothModule.h"
#import <React/RCTConvert.h>


BabyBluetooth *baby;

#define FOUNDED @"Bluetooth.device.founded"
#define DISCOUNT @"Bluetooth.discount"
#define OFF @"Bluetooth.off"
#define OVER @"Bluetooth.discovery.over"
#define BONDED  @"Bluetooth.device.bonded"

@implementation RNBluetoothModule
NSTimeInterval sec = 10;

RCT_EXPORT_MODULE(RNBluetooth)

RCT_REMAP_METHOD(discovery, resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject){
    if(nil != baby) {
        //        [baby cancelAllPeripheralsConnection];
        [baby cancelScan];
        baby
        .scanForPeripherals()
        .begin()
        .stop(sec);
        
        [self Time];
        
        resolve(@{@"value" : @(true)});
    } else {
        resolve(@{@"value" : @(false)});
    }
}


- (void)Time{
    __block int timeOut = 10;
    
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    dispatch_source_t _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0,queue);
    
    dispatch_source_set_timer(_timer,dispatch_walltime(NULL, 0),1.0*NSEC_PER_SEC, 0); //每秒执行
    
    dispatch_source_set_event_handler(_timer, ^{
        if(timeOut < 0){ //倒计时结束，关闭
            dispatch_source_cancel(_timer);
            dispatch_async(dispatch_get_main_queue(), ^{
                //设置界面的按钮显示 根据自己需求设置
                [baby cancelScan];
                [self scanningEquipment];
            });
        }else{
            //            int seconds = timeOut % 60;
            timeOut--;
        }
    });
    dispatch_resume(_timer);
}


// 关闭蓝牙扫描
RCT_EXPORT_METHOD(cancelDiscovery) {
    if(nil != baby) {
        [baby cancelScan];
        [self scanningEquipment];
    }
}

//获取已配对的
//ios不存在系统保存已配对的列表
//为保证与android接口统一，已经连接成功的设备默认存在userdefault中
RCT_REMAP_METHOD(paired,
                 resolve:(RCTPromiseResolveBlock)resolve
                 reject:(RCTPromiseRejectBlock)reject){
    NSUserDefaults* ud = [NSUserDefaults standardUserDefaults];
    NSArray* array = [ud objectForKey:BONDED];
    
    NSMutableArray *newArray = [[NSMutableArray alloc]init];
    for (NSDictionary* dic in array) {
        CBPeripheral* per = [baby findConnectedPeripheral:dic[@"name"]];
        NSMutableDictionary *item = [NSMutableDictionary dictionaryWithDictionary:dic];
        [item setObject: @(per ? 1 : 0) forKey:@"bondState"];
        [newArray addObject: dic];
    }
    resolve(@{@"value": newArray});
}


//连接蓝牙设备
RCT_EXPORT_METHOD(connect:(NSString *)address){
    
    if(nil != baby){
        [self babyDelegate];
    }
    
    NSUserDefaults* ud = [NSUserDefaults standardUserDefaults];
    NSArray* array = [ud objectForKey:BONDED];
    if(array){
        [baby cancelScan];
        for (int i = 0; i < array.count; ++i) {
            NSDictionary* dic =  array[i];
            CBPeripheral* per = [baby retrievePeripheralWithUUIDString:dic[@"address"]];
            if(per) {
                NSLog(@"%@ 重新连接蓝牙成功！",per.name);
            }
        }
    } else {
        
        //2 扫描、连接
        [baby setBlockOnDiscoverToPeripherals:^(CBCentralManager *central, CBPeripheral *peripheral, NSDictionary *advertisementData, NSNumber *RSSI) {
            
            [baby AutoReconnect:peripheral];
            
            if([address isEqualToString:address]) {
                [baby cancelScan];
                baby.having(peripheral)
                .connectToPeripherals()
                .discoverServices()
                .discoverCharacteristics()
                .readValueForCharacteristic()
                .discoverDescriptorsForCharacteristic()
                .readValueForDescriptors()
                .begin();
                return;
            }
        }];
        
        //        [baby cancelAllPeripheralsConnection];
        baby
        .scanForPeripherals()
        .begin()
        .stop(sec);
        [self Time];
    }
}

// 断开连接
RCT_EXPORT_METHOD(disconnect:(NSString *)address){
    if(nil != baby) {
        NSArray* array = [baby findConnectedPeripherals];
        for (int i = 0; i < array.count; ++i) {
            CBPeripheral* peripheral = array[i];
            if([address isEqualToString: [peripheral.identifier UUIDString]]){
                [baby cancelPeripheralConnection: peripheral];
                NSLog(@"%@ 执行断开连接", peripheral.name);
            }
        }
    } else {
        NSLog(@"id=%@ 执行断开失败[未找到连接的对象]", address);
    }
}



//***********************************************************************************************************************************************************************
//                                                                     初始化/销毁设备信息以及事件通知
//***********************************************************************************************************************************************************************
RCT_EXPORT_METHOD(toBluetooth) {
    if([[UIDevice currentDevice] systemVersion].floatValue < 10.0) {
        NSURL *url = [NSURL URLWithString:@"prefs:root=Bluetooth"];
        if([[UIApplication sharedApplication] canOpenURL:url]) {
            [[UIApplication sharedApplication] openURL:url];
        }
    } else {
        NSURL *url = [NSURL URLWithString:@"App-Prefs:root=Bluetooth"];
        if ([[UIApplication sharedApplication]canOpenURL:url]) {
            [[UIApplication sharedApplication]openURL:url];
        }
    }
}

// 初始化蓝牙设备
RCT_EXPORT_METHOD(create){
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(calendarEventReminderReceived:)name:FOUNDED object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(discount:)name:DISCOUNT object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(bound:)name:BONDED object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(bluetoothOff:)name:OFF object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(scanningEquipment)name:OVER object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(bluetoothOff:)name:BabyNotificationAtCentralManagerDidUpdateState object:nil];
    
    if(nil == baby){
        baby = [BabyBluetooth shareBabyBluetooth];
        [self babyDelegate];
    }
}

// 离开页面关闭扫描 删除通知
RCT_EXPORT_METHOD(destroy){
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    [baby cancelScan];
    //    [baby cancelAllPeripheralsConnection];
    //    baby = nil;
}


//设置蓝牙委托
-(void)babyDelegate{
    if(nil == baby) {
        return;
    }
    
    //设置扫描到设备的委托
    [baby setBlockOnDiscoverToPeripherals:^(CBCentralManager *central, CBPeripheral *peripheral, NSDictionary *advertisementData, NSNumber *RSSI) {
        NSLog(@"搜索到了设备:%@",peripheral.name);
        [[NSNotificationCenter defaultCenter] postNotificationName:FOUNDED object:[self to: peripheral]];
    }];
    
    //设置设备连接失败的委托
    [baby setBlockOnFailToConnect:^(CBCentralManager *central, CBPeripheral *peripheral, NSError *error) {
        NSLog(@"设备：%@--连接失败", peripheral.name);
        [[NSNotificationCenter defaultCenter] postNotificationName:DISCOUNT object: [self to: peripheral]];
    }];
    
    //设置设备断开连接的委托
    [baby setBlockOnDisconnect:^(CBCentralManager *central, CBPeripheral *peripheral, NSError *error) {
        NSLog(@"设备：%@--断开连接", peripheral.name);
        [[NSNotificationCenter defaultCenter] postNotificationName:DISCOUNT object:[self to: peripheral]];
    }];
    
    //设置设备连接成功的委托,同一个baby对象，使用不同的channel切换委托回调
    [baby setBlockOnConnected:^(CBCentralManager *central, CBPeripheral *peripheral) {
        NSLog(@"设备：%@--连接成功",peripheral.name);
        
        NSMutableDictionary* dic = [self to: peripheral];
        [[NSNotificationCenter defaultCenter] postNotificationName:BONDED object:dic];
        
        //设置已经匹配成功的设备
        NSUserDefaults* ud = [NSUserDefaults standardUserDefaults];
        NSArray* array = [ud objectForKey:BONDED];
        if(array) {
            NSMutableArray* t = [array mutableCopy];
            if ([array containsObject: dic] == NO){
                [t addObject:dic];
            }
            array = [t copy];
        } else {
            array = @[[self to: peripheral]];
        }
        [ud setObject:array forKey:BONDED];
        [ud synchronize];
        
        [baby AutoReconnect:peripheral];
    }];
    
    //设置读取characteristics的委托
    [baby setBlockOnReadValueForCharacteristic:^(CBPeripheral *peripheral, CBCharacteristic *characteristics, NSError *error) {
        NSLog(@"characteristic name:%@ value is:%@", characteristics.UUID, characteristics.value);
    }];
    
    //设置发现characteristics的descriptors的委托
    [baby setBlockOnDiscoverDescriptorsForCharacteristic:^(CBPeripheral *peripheral, CBCharacteristic *characteristic, NSError *error) {
        NSLog(@"===characteristic name:%@",characteristic.service.UUID);
        for (CBDescriptor *d in characteristic.descriptors) {
            NSLog(@"CBDescriptor name is :%@",d.UUID);
        }
    }];
    
    //设置读取Descriptor的委托
    [baby setBlockOnReadValueForDescriptors:^(CBPeripheral *peripheral, CBDescriptor *descriptor, NSError *error) {
        NSLog(@"Descriptor name:%@ value is:%@",descriptor.characteristic.UUID, descriptor.value);
    }];
    
    [baby setBlockOnDiscoverCharacteristics:^(CBPeripheral *peripheral, CBService *service, NSError *error) {
        NSLog(@"===service name:%@",service.UUID);
    }];
    //过滤器
    //设置查找设备的过滤器
    [baby setFilterOnDiscoverPeripherals:^BOOL(NSString *peripheralName, NSDictionary *advertisementData, NSNumber *RSSI) {
        //设置查找规则是名称大于1 ， the search rule is peripheral.name length > 1
        if (peripheralName.length > 1) {
            return YES;
        }
        return NO;
    }];
}



// 扫描到设备就发送消息
- (void)calendarEventReminderReceived:(NSNotification *)notification {
    if(nil == notification.object) {
        return;
    }
    dispatch_async(dispatch_get_main_queue(), ^{
        if (self.bridge) {
            [self sendEventWithName:FOUNDED body:notification.object];
        }
    });
}

// 扫描到设备就发送消息
- (void)bound:(NSNotification *)notification {
    if(nil == notification.object) {
        return;
    }
    dispatch_async(dispatch_get_main_queue(), ^{
        if (self.bridge) {
            [self sendEventWithName:BONDED body:notification.object];
        }
    });
}



// 蓝牙扫描结束
- (void)scanningEquipment{
    dispatch_async(dispatch_get_main_queue(), ^{
        // 蓝牙扫描结束通知
        if (self.bridge) {
            [self sendEventWithName:OVER body:nil];
        }
    });
}

// 蓝牙设备断开
- (void)discount:(NSNotification *)notification{
    
    dispatch_async(dispatch_get_main_queue(), ^{
        if (self.bridge) {
            [self sendEventWithName:DISCOUNT body:notification.object];
        }
    });
}

// 系统蓝牙关闭
- (void)bluetoothOff:(NSNotification *)notification{
    if(nil == notification.object) {
        return;
    }
    CBCentralManager* central = [notification.object objectForKey:@"central"];
    if(CBCentralManagerStatePoweredOff == central.state){
        dispatch_async(dispatch_get_main_queue(), ^{
            if (self.bridge) {
                [self sendEventWithName:OFF body:nil];
            }
        });
    }
    
}

-(NSMutableDictionary*) to: (CBPeripheral*) peripheral {
    NSMutableDictionary *dic = [NSMutableDictionary dictionary];
    [dic setObject:[NSString stringWithFormat:@"%@",[peripheral.identifier UUIDString]] forKey:@"address"];
    [dic setObject:peripheral.name ?peripheral.name : @"--" forKey:@"name"];
    [dic setObject:@(peripheral.state == CBPeripheralStateConnected ? 0 : -1) forKey:@"bondState"];
    return dic;
}

- (NSArray<NSString *> *)supportedEvents{
    return @[FOUNDED, OVER, DISCOUNT, BONDED, OFF];
}

@end




