//
//  IdreaderManager.m
//  RNIdreader
//
//  Created by len on 2019/4/29.
//  Copyright © 2019 Facebook. All rights reserved.
//

#import "IdreaderManager.h"

#import <CTSIBleTool/CTSIBleTool.h>
#import <CommonCrypto/CommonDigest.h>
#import "DES3EncryptUtil.h"
#import "XMLDictionary.h"

@interface IdreaderManager()<CTSIBleDelegate,CBCentralManagerDelegate,CBPeripheralDelegate>
@property (nonatomic, strong) CTSIBleTool *srBleTool;
@property (nonatomic, strong) CBCentralManager *manager;
@property (nonatomic, strong) CBPeripheral *currentDevice;
@property (nonatomic, strong) NSMutableArray *deviceList;

@property (nonatomic, copy) IDRMDeviceCallback deviceBlock;
@property (nonatomic, copy) IDRMResultCallback resultBlock;
@property (nonatomic, copy) IDRMErrorCallback errorBlock;
@property (nonatomic, copy) IDRMErrorCallback readErrorBlock;
@end

@implementation IdreaderManager

+ (id)shareManager {
    static IdreaderManager *sharedInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[IdreaderManager alloc] init];
    });
    return sharedInstance;
}

- (instancetype)init {
    self = [super init];
    if (self) {
        self.srBleTool = [[CTSIBleTool alloc] init:self];
        self.manager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
    }
    return self;
}

- (BOOL)isOpenBluetooth {
    return self.manager.state != CBCentralManagerStatePoweredOff;
}

- (void)settingBluetooth {
    NSURL *bluetoothURL = [NSURL URLWithString:@"Prefs:root=Bluetooth"];

    if (@available(iOS 10.0, *)) {
        [[UIApplication sharedApplication] openURL:bluetoothURL options:@{} completionHandler:nil];
    } else {
        // Fallback on earlier versions
        if ([[UIApplication sharedApplication] canOpenURL:bluetoothURL]) {
            [[UIApplication sharedApplication] openURL:bluetoothURL];
        }
    }
}

- (NSString *)factoryName {
    return [self.srBleTool factoryName];
}

- (void)scan:(IDRMDeviceCallback)block error:(IDRMErrorCallback)error {
    self.deviceBlock = block;
    self.errorBlock = error;
    
    if (self.manager.state == CBCentralManagerStatePoweredOff) {
        if (self.errorBlock) self.errorBlock(@"尚未打开蓝牙，请在设置中打开");
        return;
    }
    
    self.deviceList = nil;
    self.manager.delegate = self;
    [self.manager scanForPeripheralsWithServices:nil options:@{CBCentralManagerScanOptionAllowDuplicatesKey : @YES}];
    
    
}

- (void)stopScan {
    [self.manager stopScan];
}

- (void)read:(NSString *)bid callback:(IDRMResultCallback)callback error:(IDRMErrorCallback)error {
    self.resultBlock = callback;
    self.readErrorBlock = error;
    
    [self stopScan];
    
    if (self.manager.state == CBCentralManagerStatePoweredOn) {
        for (CBPeripheral *per in self.deviceList) {
            if ([per.identifier.UUIDString isEqualToString:bid]) {
                self.currentDevice = per;
                break;
            }
        }
        [self performSelectorInBackground:@selector(connectReader:) withObject:self.currentDevice];
    }else {
        if (self.readErrorBlock) self.readErrorBlock(@"尚未打开蓝牙，请在设置中打开");
    }
}

- (void)connectReader:(CBPeripheral *)peripheral{
    
    BOOL ret = [self.srBleTool connectBt:peripheral usingCBManager:self.manager];
    if (ret) {
        //        sleep(1);
        //        dispatch_async(dispatch_get_global_queue(0,0),^{
        
        NSString *timestamp = [NSString stringWithFormat:@"%f", [[NSDate date] timeIntervalSince1970] * 1000];
        
        NSString *signatureStr = [NSString stringWithFormat:@"%@%@%@%@%@",
                                  self.appId,
                                  self.appSecret,
                                  self.businessExt,
                                  self.nonce,
                                  timestamp];
        NSString *signature = [self getSha1String:signatureStr];
        NSLog(@"signature:%@",signature);
        
        NSDictionary *resultDic = [NSDictionary dictionaryWithDictionary:[self.srBleTool cloudReadCert:self.appId :timestamp :self.nonce :self.businessExt :signature]];
        NSNumber *resultFlag = [resultDic objectForKey:@"resultFlag"];
        
        if ([resultFlag intValue] == 0) {
            NSString *resultContent = [resultDic objectForKey:@"resultContent"];
            NSLog(@"resultContent:%@",resultContent);
            NSString *xmlStr = [DES3EncryptUtil decrypt:resultContent key:self.appSecret_3des];
            NSLog(@"xmlStr:%@",xmlStr);
            
            NSDictionary *xmlDoc = [NSDictionary dictionaryWithXMLString:xmlStr];
            NSLog(@"dictionary: %@", xmlDoc);
            NSString *parseStr = [xmlDoc objectForKey:@"decodeId"];
            NSLog(@"parseStr:%@",parseStr);
            dispatch_async(dispatch_get_main_queue(), ^{
                self.resultBlock(xmlDoc);
            });
            
        }else {
            dispatch_async(dispatch_get_main_queue(), ^{
                if (self.readErrorBlock) {
                    self.readErrorBlock([NSString stringWithFormat:@"读取失败 %@:%@",[resultDic objectForKey:@"resultFlag"],[resultDic objectForKey:@"errorMsg"]]);
                }
            });
        }
        [self.srBleTool disconnectBt];
    }else {
        dispatch_async(dispatch_get_main_queue(), ^{
            if (self.readErrorBlock) self.readErrorBlock(@"连接读头失败");
        });
    }
}

#pragma mark SunriseBleToolDelegate

- (void)BR_connectResult:(BOOL)isconnected{
    NSLog(@"BR_connectResult:%@",isconnected?@"True":@"False");
}

// 蓝牙列表
- (void)didGetDeviceList:(NSArray *)deviceList{
    self.deviceList = [deviceList mutableCopy];
    if (self.deviceBlock) self.deviceBlock(self.deviceList);
}

- (void)CBluetoothBack:(NSString *)time {
    // ???
}


- (void)CNetworkBack:(NSString *)time {
    // ???
}


#pragma mark CBCentralManagerDelegate
- (void)centralManagerDidUpdateState:(CBCentralManager *)central{
    switch (central.state) {
            //判断状态开始扫瞄周围设备 第一个参数为空则会扫瞄所有的可连接设备  你可以
            //指定一个CBUUID对象 从而只扫瞄注册用指定服务的设备
            //scanForPeripheralsWithServices方法调用完后会调用代理CBCentralManagerDelegate的
            //- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI方法
        case CBCentralManagerStatePoweredOn:
            [self.manager scanForPeripheralsWithServices:nil options:@{CBCentralManagerScanOptionAllowDuplicatesKey : @YES}];
            break;
        case CBCentralManagerStatePoweredOff:
            if (self.errorBlock) self.errorBlock(@"尚未打开蓝牙，请在设置中打开");
            break;
            
        default:
            break;
    }
}

- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheraln advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI{
    //发现设备
    
    
    if (self.deviceList == nil) {
        self.deviceList = [NSMutableArray array];
    }
    if ([self.deviceList containsObject:peripheraln]) {
        return;
    }
    if (peripheraln.name.length != 0) {
        [self.deviceList addObject:peripheraln];
        if (self.deviceBlock) {
            self.deviceBlock(self.deviceList);
        }
    }
}

- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{
    NSLog(@"has connected");
    
    //此时设备已经连接上了  你要做的就是找到该设备上的指定服务 调用完该方法后会调用代理CBPeripheralDelegate（现在开始调用另一个代理的方法了）的
    //- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
    //    [self.peripheral discoverServices:@[[CBUUID UUIDWithString:kServiceUUID]]];
    
}

- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{
    //此时连接发生错误
    NSLog(@"connected periphheral failed");
    if (self.readErrorBlock) self.readErrorBlock(@"蓝牙连接发生错误");
}


#pragma mark CBPeripheralDelegate
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error{
    if (error==nil) {
        //在这个方法中我们要查找到我们需要的服务  然后调用discoverCharacteristics方法查找我们需要的特性
        //该discoverCharacteristics方法调用完后会调用代理CBPeripheralDelegate的
        //- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
        //        for (CBService *service in peripheral.services) {
        //            if ([service.UUID isEqual:[CBUUID UUIDWithString:kServiceUUID]]) {
        //                [peripheral discoverCharacteristics:@[[CBUUID UUIDWithString:kCharacteristicUUID]] forService:service];
        //            }
        //        }
    }
}

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error{
    if (error==nil) {
        //在这个方法中我们要找到我们所需的服务的特性 然后调用setNotifyValue方法告知我们要监测这个服务特性的状态变化
        //当setNotifyValue方法调用后调用代理CBPeripheralDelegate的- (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
        //        for (CBCharacteristic *characteristic in service.characteristics) {
        //            if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:kCharacteristicUUID]]) {
        //
        //                [peripheral setNotifyValue:YES forCharacteristic:characteristic];
        //            }
        //        }
    }
}

- (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
    if (error==nil) {
        //调用下面的方法后 会调用到代理的- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
        [peripheral readValueForCharacteristic:characteristic];
    }
}


- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
    
}


- (dispatch_queue_t)methodQueue
{
    return dispatch_get_main_queue();
}

- (NSString *)getSha1String:(NSString *)srcString{
    const char *cstr = [srcString cStringUsingEncoding:NSUTF8StringEncoding];
    NSData *data = [NSData dataWithBytes:cstr length:srcString.length];
    uint8_t digest[CC_SHA1_DIGEST_LENGTH];
    CC_SHA1(data.bytes, data.length, digest);
    NSMutableString* result = [NSMutableString stringWithCapacity:CC_SHA1_DIGEST_LENGTH *2];
    for(int i =0; i < CC_SHA1_DIGEST_LENGTH; i++) {
        [result appendFormat:@"%02x", digest[i]];
    }
    return [result uppercaseString];
}

@end
