//
//  KLTBluetoothManager.m
//  KaiLiTe
//
//  Created by boosal on 2016/9/8.
//  Copyright © 2016年 boosal. All rights reserved.
//

#import "KLTBluetoothManager.h"
#import "KLTFormat.h"
#import "KLTDatabaseHandler.h"
#import "CGMAlgo.h"
#import "KLTUserDefautKeyDefine.h"
#import "KLTLaunchConfiguration.h"
#import "KLTCommonDefine.h"
#import "KLTPrefixHeader.pch"
@interface KLTBluetoothManager ()

@property (nonatomic, assign) BOOL isInResend;
@property (nonatomic, strong) EDevice *eDevice;
@property (nonatomic, strong) CBPeripheral *bgConnectPeripheral;

@property (nonatomic, assign) BOOL isBgForceConnectDevice;
@property (nonatomic, assign) BOOL isFromPrefix22;
@property (nonatomic, strong) NSTimer *connectWatchTimer;
// 最多连接三次即超时
@property (nonatomic, assign) NSInteger connectWatchMaxTimes;
// 蓝牙管理状态
@property (nonatomic, assign) CBManagerState centralManagerState;

@end

@implementation KLTBluetoothManager

#pragma mark - init method

- (void)dealloc {
    if (_connectTimer) {
        [_connectTimer invalidate];
        _connectTimer = nil;
    }
    
    if (_bgConnectTimer) {
        [_bgConnectTimer invalidate];
        _bgConnectTimer = nil;
    }
    
    if (_rescanTimer) {
        [_rescanTimer invalidate];
        _rescanTimer = nil;
    }
    
    if (self.connectWatchTimer) {
        [self.connectWatchTimer invalidate];
        self.connectWatchTimer = nil;
    }
}

- (instancetype)init {
    self = [super init];
    if (self) {
        self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:dispatch_get_main_queue()];
        self.peripherals = [NSMutableArray array];
        self.status = BluetoothManagerStatusInitial;
        self.centralManager = [[CBCentralManager alloc] initWithDelegate:self
                                                                   queue:dispatch_get_main_queue()
                                                                 options:@{CBCentralManagerOptionRestoreIdentifierKey: @"com.drstore.bluetooth.central"}];
        self.isInResend = NO;
    }
    
    return self;
}

+ (KLTBluetoothManager *)sharedManager {
    static KLTBluetoothManager *bluetooth;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        bluetooth = [[self alloc] init];
    });

    return bluetooth;
}


#pragma mark - cbcenteralmanager delegate

- (void)centralManagerDidUpdateState:(CBCentralManager *)central {
    switch (central.state) {
        case CBManagerStateUnknown:
        case CBManagerStateResetting:
        case CBManagerStateUnsupported:
            KLTLog(@"该设备不支持蓝牙，请更换设备");
            [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"bluetoothOff"];
            [Notification_Center postNotificationName:@"BluetoothEnable" object:@(NO)];
            break;
        case CBManagerStateUnauthorized:
            KLTLog(@"Allen CBManagerStateUnauthorized");
            break;
        case CBManagerStatePoweredOff: {
            KLTLog(@"蓝牙没有打开，请先打开蓝牙");
            if (self.connectedPeripheral) {
                self.connectedPeripheral = nil;
                [self.peripherals removeAllObjects];
            }
            [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"bluetoothOff"];
            [Notification_Center postNotificationName:@"BluetoothEnable" object:@(NO)];
        }
            break;
        case CBManagerStatePoweredOn: {
            [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"bluetoothOff"];
            [Notification_Center postNotificationName:@"BluetoothEnable" object:@(YES)];
        }
            break;
        default:
            break;
    }

    self.centralManagerState = central.state;
}

- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *,id> *)advertisementData RSSI:(NSNumber *)RSSI {
    KLTLog(@" %@---%@-----\n%@ ",peripheral,advertisementData,RSSI);
    Verify *verifyModel = [ProtocalTools verify:advertisementData];
    if (verifyModel) {
        if (![self.peripherals containsObject:peripheral] && peripheral.name.length != 0) {
            Device *device = [[KLTDatabaseHandler shared] addDevice:peripheral];
            Advertise *advertise = [[KLTDatabaseHandler shared] addAdvertisement:advertisementData];
            device.advertise = advertise;
            advertise.device = device;
            [[KLTDatabaseHandler shared].appDelegate saveContext];
            KLTLog(@"has useable %@---%@-----\n%@ ",peripheral,advertisementData,RSSI);

            if (verifyModel.isBound) {
                if (self.currentDevice && [peripheral.identifier.UUIDString isEqualToString:self.currentDevice.identifier]) {
                    // 一般属于已连接过的蓝牙设备触发场景（manufactureData最后一个字节为01 别的手机设备搜索蓝牙时根据判断为01时不展示）
                    // 已经扫描到上一次连接记录的发射器，停止扫描并尝试连接
                    [self.peripherals addObject:peripheral];
                    [self connectPeripheral:peripheral];
                    return;
                }
            } else {
                // 未被连接的蓝牙设备manufactureData最后尾数00（已经连接01 不展示到搜索列表self.peripherals缓存中）才走此流程
                [self.peripherals addObject:peripheral];
            }
        }
        
        if ([self.bluetoothDelegate respondsToSelector:@selector(onFindDevices:connectedDevice:)]) {
            [self.bluetoothDelegate onFindDevices:_peripherals connectedDevice:nil];
        }
    }
}

- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral {
    KLTLog(@"%s", __FUNCTION__);
    self.isBgForceConnectDevice = NO;
    if (_bgConnectTimer) {
        [_bgConnectTimer invalidate];
        _bgConnectTimer = nil;
    }
    if (_rescanTimer) {
        [_rescanTimer invalidate];
        _rescanTimer = nil;
    }

    _currentDevice = nil;
    self.connectedPeripheral = peripheral;
    self.status = BluetoothManagerStatusConnected;
    [[KLTDatabaseHandler shared] updateDeviceWithDeviceId:[self.connectedPeripheral.identifier UUIDString] scannedTime:nil connectTime:[NSString getWholeStringWithDate:NSDate.date] disConnectTime:nil];
        
    Device *device = self.currentDevice;
    self.eDevice = [EDevice getEnumDevice:device.advertise.localName];
    [KLTLaunchConfiguration.sharedManager updateInitialPeriod:self.eDevice.initHour * 60 * 60];

    if ([self.bluetoothDelegate respondsToSelector:@selector(onFindDevices:connectedDevice:)]) {
        [self.bluetoothDelegate onFindDevices:self.peripherals connectedDevice:peripheral];
    }
    
    self.isInResend = YES;
    peripheral.delegate = self;
    [peripheral discoverServices:@[[CBUUID UUIDWithString:self.eDevice.eGattMessage.UUID_SERVICE]]];
    [self stopScan];
}

- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
    KLTLog(@"%s", __FUNCTION__);
    [self terminateConnection];
}

- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
    NSLog(@"%s", __FUNCTION__);
    self.bgConnectPeripheral = peripheral;
 
    [[KLTDatabaseHandler shared] updateDeviceWithDeviceId:[self.connectedPeripheral.identifier UUIDString]
                                                    scannedTime:nil
                                                   connectTime:nil
                                               disConnectTime:[NSString getWholeStringWithDate:NSDate.date]];
    
    self.connectedPeripheral = nil;
    self.status = BluetoothManagerStatusDisconnected;
 
    if (!KLTLocalSettingManager.shareInstance.canConnectOtherDevice) {
        if (!self.isBgForceConnectDevice) {
            [self connectPeripheral:peripheral];
            self.isBgForceConnectDevice = YES;
        }
 
        if (!_rescanTimer) {
            [_rescanTimer invalidate];
            _rescanTimer = nil;
            _rescanTimer = [NSTimer scheduledTimerWithTimeInterval:30
                                                            target:self
                                                          selector:@selector(startScan)
                                                          userInfo:nil
                                                           repeats:YES];
        }
    } else {
        self.isBgForceConnectDevice = NO;
 
        [self.peripherals removeObject:peripheral];
 
        if ([self.bluetoothDelegate respondsToSelector:@selector(onFindDevices:connectedDevice:)]) {
            [self.bluetoothDelegate onFindDevices:_peripherals connectedDevice:nil];
        }
    }
}

#pragma mark - peripheral delgate

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error {
    KLTLog(@"%s", __FUNCTION__);
    if (error) {
        [self terminateConnection];
        return;
    }
    
    for (CBService *service in peripheral.services) {
        [peripheral discoverCharacteristics:@[[CBUUID UUIDWithString:self.eDevice.eGattMessage.UUID_WRITE], [CBUUID UUIDWithString:self.eDevice.eGattMessage.UUID_READ]] forService:service];
    }
}

- (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
    if (![characteristic.UUID isEqual:[CBUUID UUIDWithString:self.eDevice.eGattMessage.UUID_READ]]) {
        return;
    }
    KLTLog(@"%s", __FUNCTION__);
    if (!characteristic.isNotifying) {
        [self.centralManager cancelPeripheralConnection:peripheral];
    }
}

- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
    KLTLog(@"%s", __FUNCTION__);
}

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error {
    KLTLog(@"%s", __FUNCTION__);
    if (error) {
        [self terminateConnection];
        return;
    }
        
    for (CBCharacteristic *characteristic in service.characteristics) {
        if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:self.eDevice.eGattMessage.UUID_WRITE]]) {
            self.writeReadCharacteristic = characteristic;
            if ([@"CT4" isEqualToString:self.eDevice.deviceType]) {
                // CT3 CT4处理首次绑定流程和重连流程
                [self requestResendCT3];
            }
        }
       
        if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:self.eDevice.eGattMessage.UUID_READ]]) {
            self.notifyCharacteristic = characteristic;
            [peripheral setNotifyValue:YES forCharacteristic:characteristic];
        }
    }
}

// 获取外设发来的数据，不论是read还是notify，获取数据都是从这个方法中读取。
//To receive data sent from the peripheral, whether through read or notify, the data is obtained from this method.
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
    if (error) {
        return;
    }
    if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:self.eDevice.eGattMessage.UUID_READ]]) {
        if (!characteristic.value || characteristic.value.length == 0) {
            return;
        }
        
        NSString *hex = [KLTFormat dataToHexString:characteristic.value isReverse:NO];
        NSString *command = [hex substringWithRange:NSMakeRange(0, 2)];
        if ([command isEqualToString:@"05"]) {
            // CT3、CT4的自检协议0x05响应(只检测电压>=3.9)
            HW_CHECK_RET ret = [ProtocalTools check_response:characteristic.value andEDevice:self.eDevice];
            if (HW_CHECK_SUCCESS == ret) {
                [KLTDatabaseHandler.shared updateDevice:self.currentDevice initialBeginDate:nil endDate:nil];
                // CT3设置时间协议0x03请求
                NSData *value = [ProtocalTools setDate_request:self.eDevice];
                [peripheral writeValue:value forCharacteristic:self.writeReadCharacteristic type:CBCharacteristicWriteWithoutResponse];
            } else if (HW_CHECK_FAIL_POWER == ret) {
                // CT3通知扫码页面处理绑定失败操作后的流程 (断开连接，返回主界面提示电量不足，更换电池)
                [Notification_Center postNotificationName:KLTAlertSelfCheckFailedNotify object:@(ret)];
                [self resetBleSensorData];
            } else if (HW_CHECK_FAIL == ret) {
                // 通知扫码页面处理绑定失败操作后的流程 (断开连接，返回主界面)
                self.status = BluetoothManagerStatusClosed;
                [self resetBleSensorData];
            }
        }
                        
        if ([command isEqualToString:@"22"]) {
            // CT4重传的数据，pullGlucose_series_request 0x22的返回
            //CT4 retransmission data returned by the pullGlucose_series_request (0x22) command
            [self handleResendDataWithPrefix22:characteristic.value];
        }

        if ([command isEqualToString:@"03"]) {
            // CT4的设置时间协议0x03响应
            if ([ProtocalTools setDate_response:characteristic.value andEDevice:self.eDevice]) {
                // CT3 CT4开始初始化协议0x06
                NSData *data = [ProtocalTools start_init_request:self.eDevice];
                [self.connectedPeripheral writeValue:data forCharacteristic:self.writeReadCharacteristic type:CBCharacteristicWriteWithoutResponse];
            } else {
                // 发射器绑定失败
                self.status = BluetoothManagerStatusClosed;
                [self resetBleSensorData];
            }
        }
        
        if ([command isEqualToString:@"06"]) {
            // 06：CT3初始化协议响应后发射低功耗
            //After CT3 initialization protocol response, the transmitter enters low power mode.
            if ([ProtocalTools init_response:characteristic.value andEDevice:self.eDevice]) {
                KLTLocalSettingManager.shareInstance.canConnectOtherDevice = NO;
                
                NSString *snLocalName = self.currentDevice.advertise.localName;
                // 创建新的runLog CSV
                KLTRunLog *runLog = [KLTAppDelegate getCurrentKLTRunLog];
                [runLog createNewCSV:snLocalName];
                
                // 开始初始化，倒计时3小时开始
                self.status = BluetoothManagerStatusInitialStart;
                self.isInResend = NO;
                
                NSTimeInterval aTimeInterval = [[NSDate date] timeIntervalSinceReferenceDate] + 180 * self.eDevice.initNumber;
                NSDate *newDate = [NSDate dateWithTimeIntervalSinceReferenceDate:aTimeInterval];
                [KLTDatabaseHandler.shared updateDevice:self.currentDevice initialBeginDate:[NSString getWholeStringWithDate:NSDate.date] endDate:[NSString getWholeStringWithDate:newDate]];
                self.dataType = ReceiveDataBeforeSetUserReference;
                
                // CT3 初始化协议后发射低功耗
                [self.connectedPeripheral writeValue:[ProtocalTools lowPower_request:self.eDevice] forCharacteristic:self.writeReadCharacteristic type:CBCharacteristicWriteWithoutResponse];

                [User_Defaults setObject:[NSString stringWithFormat:@"%@_%ld", snLocalName, (long)[[NSDate date] timeIntervalSince1970]] forKey:@"wearingRecordId"];
                [User_Defaults synchronize];
            } else {
                // 发射器绑定失败
                self.status = BluetoothManagerStatusClosed;
                [self resetBleSensorData];
            }
        }
        
        if ([command isEqualToString:@"07"]) {
            // CT3/CT4 每3分钟上来的数据
            //Data uploaded every 3 minutes from CT3/CT4
            KLTLog(@"==============>>> Data uploaded every 3 minutes from CT3/CT4");
            [self handleReceiveDataWithPrefix07:characteristic.value];
        }

        if ([command isEqualToString:@"0A"]) {
            // CT3/CT4解绑协议0x0A响应
            BOOL success = [ProtocalTools unBind_response:characteristic.value andEDevice:self.eDevice];
            if (success) {
                // 通知初始化页面或首页操作解绑后的流程
                self.status = BluetoothManagerStatusClosed;
                [self resetBleSensorData];
                if ([self.bluetoothDelegate respondsToSelector:@selector(onFindDevices:connectedDevice:)]) {
                    [self.bluetoothDelegate onFindDevices:self.peripherals connectedDevice:nil];
                }
            }
        }

        if ([command isEqualToString:@"11"]) {
            // Reset response received from CT3/CT4
            TransmitterReset *resetData = [ProtocalTools reset_response2:characteristic.value andEDevice:self.eDevice];
            if (resetData.isBind) {
                // Transmitter is still bound → send low-power mode command
                [peripheral writeValue:[ProtocalTools lowPower_request:self.eDevice] forCharacteristic:self.writeReadCharacteristic type:CBCharacteristicWriteWithoutResponse];
            } else {
                // Transmitter is unbound (e.g., reset + power cycle)
                self.status = BluetoothManagerStatusSensorLostPower;
            }
        }
    }
}


#pragma mark - 发射器通用接受数据处理、算法计算处理

// 发射器处理单条血糖数据的算法调用保存
//Is the algorithm used by the transmitter to process a single glucose data point also responsible for saving it?
- (void)handleCommonCT3GlucoseDataWithReceiveData:(ReceiveData *)receiveData {
    int glucoseId = receiveData.glucoseId.intValue;
//    if (glucoseId >= self.eDevice.initNumber - 1) {
        // CT3 id == 19 时就出值
        self.dataType = ReceiveDataAfterSetUserReference;
        self.resendType = ResendDataAfterSetUserBG;
        
        Device *currentDevice = self.currentDevice;
        GlucoseData *glucose = [[KLTDatabaseHandler shared] addCT3GlucoseDataWithReceiveData:receiveData];        
        KLTLog(@"计算glucose.gluADC = %@, glucose.errorCode = %@", glucose.gluADC, glucose.errorCode);
        [currentDevice addGlucoseDatasObject:glucose];
        KLTLog(@"==============>>> GlucoseData");
        KLTLog(@"GlucoseData Details:\n""gluADC: %@\n""glu: %@\n""errorCode: %@\n""temperature: %@\n""trend: %@\n""dataId: %@\n""operatingCurrent: %@\n""blankCurrent: %@\n""k: %@\n""iw: %@\n""calibrationStatus: %@\n""initialBeginDate: %@\n""receiveDateTime: %@\n""userBG: %@\n""device: %@",
               glucose.gluADC,glucose.glu,glucose.errorCode,glucose.temperature,glucose.trend,glucose.dataId,glucose.operatingCurrent,glucose.blankCurrent,glucose.k,glucose.iw,glucose.calibrationStatus,glucose.initialBeginDate,glucose.receiveDateTime,glucose.userBG,glucose.device.deviceName);

        if (!self.isInResend) {
            [Notification_Center postNotificationName:@"latestGluData" object:glucose];
            self.status = BluetoothManagerStatusGetGLU;
        }
        if (currentDevice.userBG) {
            // 用来存取下一个血糖点需要调用校准算法，后续血糖点则正常调用非校准传参算法
            currentDevice.userBG = nil;
        }
//    } else {
//        self.dataType = ReceiveDataBeforeSetUserReference;
//        self.resendType = ResendDataBeforeSetUserBG;
//        
//        //初始化期间接收到的数据存数据库的ReceiveData表中，不做处理
//        //The data received during initialization is stored in the ReceiveData table in the database without any processing.
//        [[KLTDatabaseHandler shared] updatePOCAlgoBeforeRef:receiveData];
//        KLTLog(@"计算receive.gluADC = %@, receive.error = %@", receiveData.gluADC, receiveData.error);
//        if (!self.isInResend) {
//            // 初始化期间收到异常电流数据提醒 (判断18分钟开始才会提醒"Sensor signal error")
//            [Notification_Center postNotificationName:KLTAlertCurrentInInitialNotify object:receiveData];
//        }
//    }
    
    receiveData.dataType = @(self.dataType);
    [[KLTDatabaseHandler shared].appDelegate saveContext];
}

// 发射器处理单条血糖数据的通用解析
//Generic parsing of a single blood glucose data packet by the transmitter
- (ReceiveData *)handleCommonReceiveGluData:(Glucose *)gluData commandText:(NSString *)commandText {
    Device *currentDevice = self.currentDevice;
    //接收到的数据先存放到ReceiveDataInfo表
    ReceiveData *receive = [KLTDatabaseHandler.shared addReceiveCT3DataWithDevice:currentDevice];
    
    NSDate *startInitDate = [KLTFormat getDateFromString:currentDevice.initialBeginDate];
    NSDate *gluDate = [NSDate dateWithTimeInterval:(gluData.gluID + 1) * self.eDevice.initHour*60*60/self.eDevice.initNumber sinceDate:startInitDate];
    NSInteger unitFlags = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitWeekday | NSCalendarUnitHour | NSCalendarUnitMinute;
    NSDateComponents *components = [[NSCalendar currentCalendar] components:unitFlags fromDate:gluDate];
    receive.year = @(components.year);
    receive.month = @(components.month);
    receive.day = @(components.day);
    receive.hour = @(components.hour);
    receive.minute = @(components.minute);
    receive.receiveDateTime = [NSString stringWithFormat:@"%@-%02d-%02d %02d:%02d",receive.year,[receive.month intValue],[receive.day intValue],[receive.hour intValue],[receive.minute intValue]];

    receive.glucoseId = @(gluData.gluID);
    receive.operatingCurrent = @(gluData.iw);
    receive.blankCurrent = @(gluData.ib);
    receive.temperature = @(gluData.T);
    receive.dataType = @(self.resendType);
    receive.commandStr = commandText;
    receive.device = currentDevice;
    [currentDevice addReceiveDatasObject:receive];
    [[KLTDatabaseHandler shared].appDelegate saveContext];
    
    return receive;
}

#pragma mark - CT3 绑定/重连流程、血糖拉取/每3分钟接收

// CT3连接、重连流程
- (void)requestResendCT3 {
    Device *currentDevice = self.currentDevice;
    if (KLTLocalSettingManager.shareInstance.canConnectOtherDevice) {
        // 直接开始自检协议
        [self.connectedPeripheral writeValue:[ProtocalTools check_request:self.eDevice] forCharacteristic:self.writeReadCharacteristic type:CBCharacteristicWriteWithoutResponse];
    } else {
        // 二次重连 0x22快传批量数据
        NSInteger maxGlucoseId = [[KLTDatabaseHandler shared] getLatestAndMaxGlucoseIdOfDevice:currentDevice];
        [self pullGlucouseSeriesRequestWithGlucoseId:maxGlucoseId];
    }
}

// CT3/CT4 每3分钟上来的数据
//Data uploaded every 3 minutes from CT3/CT4
- (void)handleReceiveDataWithPrefix07:(NSData *)receiveData {
    if (self.status == BluetoothManagerStatusResendStart || self.isInResend) {
        // 重发数据期间不处理新收到的数据
        return;
    }
    
    NSInteger maxGlucoseId = [[KLTDatabaseHandler shared] getLatestAndMaxGlucoseIdOfDevice:self.currentDevice];
    Glucose *gluData = [ProtocalTools getGlucose:receiveData andEDevice:self.eDevice];
    if (gluData.gluID == maxGlucoseId + 1) {
        [self handleReceiveDataWithPrefix07Glucose:gluData];
    } else if (gluData.gluID > maxGlucoseId + 1) {
        // 如果拿到的数据大于下一条数据的gluID 证明需要重新拉取中间漏掉的数据（22拉取协议）
        [self pullGlucouseSeriesRequestWithGlucoseId:maxGlucoseId];
    }
}

- (void)pullGlucouseSeriesRequestWithGlucoseId:(NSInteger)glucoseId {
    NSInteger remain_points = self.eDevice.endNumber - (glucoseId + 1);
    if (remain_points <= 0) {
        [self closeBleSensor];
    } else {
        // 数据没拉取完继续拉取蓝牙断开期间的数据（0x22拉取协议）
        //Continue retrieving the remaining data that wasn't pulled before, including the data generated during the Bluetooth disconnection (using the 0x22 retrieval protocol).
        NSInteger pullNums = 20;
        if (remain_points < pullNums) {
            pullNums = remain_points;
        }
        
        NSData *data = [ProtocalTools pullGlucose_series_request:glucoseId + 1 andNumber:pullNums andEDevice:self.eDevice];
        [self.connectedPeripheral writeValue:data forCharacteristic:self.writeReadCharacteristic type:CBCharacteristicWriteWithoutResponse];
        self.status = BluetoothManagerStatusResendStart;
        self.isInResend = YES;
    }
}

// CT3 CT4重传的数据，pullGlucose_series_request 22的返回
//Retransmitted data from CT3 and CT4, response of pullGlucose_series_request 0x22
- (void)handleResendDataWithPrefix22:(NSData *)resendData {
    NSArray<Glucose *> *glucoseList = [ProtocalTools getGlucose_series:resendData andEDevice:self.eDevice];
    if (glucoseList.count == 0) {
        // 重传数据完毕
        self.isInResend = NO;
        self.status = BluetoothManagerStatusResendEnd;
        [Notification_Center postNotificationName:@"DidHandleResendData" object:nil];
        
        // CT3/CT4发送重置协议这条命令0x11，结束重传状态
        [self.connectedPeripheral writeValue:[ProtocalTools reset_request:self.eDevice] forCharacteristic:self.writeReadCharacteristic type:CBCharacteristicWriteWithoutResponse];
    } else {
        for (Glucose *glucose in glucoseList) {
            ReceiveData *receive = [self handleCommonReceiveGluData:glucose commandText:@"22"];
            self.isFromPrefix22 = YES;
            [self handleCommonCT3GlucoseDataWithReceiveData:receive];
        }
    
        [Notification_Center postNotificationName:KLTUpdateDataNotify object:NULL];
        NSLog(@"----------------------------------------------called handleResendDataWithPrefix22 for KLTUpdateDataNotify");
        NSInteger maxGlucoseId = [KLTDatabaseHandler.shared getLatestAndMaxGlucoseIdOfDevice:self.currentDevice];
        NSInteger remain_points = self.eDevice.endNumber - (maxGlucoseId + 1);
        if (remain_points <= 0) {
            [self closeBleSensor];
        } else {
            // 数据没拉取完继续拉取蓝牙断开期间的数据（0x22拉取协议）
            NSInteger pullNums = 20;
            if (remain_points < pullNums) {
                pullNums = remain_points;
            }
            NSData *data = [ProtocalTools pullGlucose_series_request:maxGlucoseId + 1 andNumber:pullNums andEDevice:self.eDevice];
            [self.connectedPeripheral writeValue:data forCharacteristic:self.writeReadCharacteristic type:CBCharacteristicWriteWithoutResponse];
        }
    }
}

// CT3/CT4 正常3分钟一次接收的单条数据
- (void)handleReceiveDataWithPrefix07Glucose:(Glucose *)gluData {
    ReceiveData *receive = [self handleCommonReceiveGluData:gluData commandText:@"07"];
    [Notification_Center postNotificationName:@"didReceiveNewData" object:receive];
    self.isFromPrefix22 = NO;
    [self handleCommonCT3GlucoseDataWithReceiveData:receive];
    [Notification_Center postNotificationName:@"DidHandleResendDataNoReload" object:nil];
    [Notification_Center postNotificationName:KLTUpdateDataNotify object:NULL];
    NSLog(@"----------------------------------------------called handleReceiveDataWithPrefix07Glucose for KLTUpdateDataNotify");
    NSInteger remain_points = [KLTDatabaseHandler.shared numberOfLifeCycleSensorWithDevice:self.currentDevice endNumber:self.eDevice.endNumber];
    if (remain_points <= 0) {
        [self closeBleSensor];
    }
}

#pragma mark - 断开连接后的本地数据重置处理

- (void)resetBleSensorData {
    // 断开与外设的连接，取消对characteristic的监听
    [self terminateConnection];

    Device *currentDevice = self.currentDevice;
    if (currentDevice) {
        currentDevice.userBG = nil;
        currentDevice.connectedDateTime = nil;
        currentDevice.disconnectedDateTime = nil;
        currentDevice.initialBeginDate = nil;
        currentDevice.initialEndDate = nil;
        [[KLTDatabaseHandler shared].appDelegate saveContext];
    }
    _currentDevice = nil;
    self.dataType = ReceiveDataBeforeSetUserReference;
    self.resendType = ResendDataBeforeSetUserBG;
    
    [self.peripherals removeAllObjects];
    self.connectedPeripheral = nil;
    
    [_connectTimer invalidate];
    _connectTimer = nil;
    [_rescanTimer invalidate];
    _rescanTimer = nil;

    [User_Defaults removeObjectForKey:KLTLocalDeviceQRCodeInfoKey];
    KLTLocalSettingManager.shareInstance.canConnectOtherDevice = YES;
    [User_Defaults setObject:nil forKey:@"silenceStart"];
    [User_Defaults setObject:nil forKey:@"alertKindOnSilence"];
    [User_Defaults synchronize];
}

#pragma mark - other method

- (void)endScan {
    // 20s后扫描设备超时未连上再次尝试连接
    if (self.currentDevice && BluetoothManagerStatusScanStart == self.status) {
        for (CBPeripheral *per in self.peripherals) {
            if ([per.identifier.UUIDString isEqualToString:self.currentDevice.identifier]) {
                KLTLog(@"endScan connectPeripheral...");
                [self connectPeripheral:per];
                return;
            }
        }
    }
    
    [self stopScan];
    self.status = BluetoothManagerStatusTimeOut;
}

// 停止扫描
- (void)stopScan {
    self.status = BluetoothManagerStatusScanStop;
    [self.centralManager stopScan];

    [_connectTimer invalidate];
    _connectTimer = nil;
}

// 开始扫描
//- (void)startScan {
//    self.connectedPeripheral = nil;
//    [self.peripherals removeAllObjects];
//
//    if (self.centralManager.state != CBManagerStatePoweredOn) {
//        return;
//    }
//    KLTLog(@"Allen manager start scan %d", __LINE__);
//
//    if ([[User_Defaults objectForKey:@"bgmode"] intValue] == 1) {
//        self.status = BluetoothManagerStatusDisconnected;
//        
//        [[KLTDatabaseHandler shared] updateDeviceWithDeviceId:[self.bgConnectPeripheral.identifier UUIDString] scannedTime:nil connectTime:nil disConnectTime:[KLTFormat getDateString]];
//        self.connectedPeripheral = nil;
//
//        if (!KLTLocalSettingManager.shareInstance.canConnectOtherDevice) {
//            /* 如果当前周期还没结束且处于后台，则强制连接发射器 */
//            if (!self.isBgForceConnectDevice) {
//                [self connectPeripheral:self.bgConnectPeripheral];
//                self.isBgForceConnectDevice = YES;
//            }
//            
//            if (!_rescanTimer) {
//                [_rescanTimer invalidate];
//                _rescanTimer = nil;
//                _rescanTimer = [NSTimer scheduledTimerWithTimeInterval:30 target:self selector:@selector(startScan) userInfo:nil repeats:YES];
//            }
//        }
//        return;
//    }
//    
//    self.isBgForceConnectDevice = NO;
//    self.status = BluetoothManagerStatusScanStart;
//    // 如果用特定的UUID传参可能找不到任何设备
//    // [self.centralManager scanForPeripheralsWithServices:@[[CBUUID UUIDWithString:SERVICE_UUID]] options:nil];
//    // 扫描多台外设
//    NSDictionary *scanOptions = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:CBCentralManagerScanOptionAllowDuplicatesKey];
//    [self.centralManager scanForPeripheralsWithServices:nil options:scanOptions];
//    // 用定时器来监控扫描超时的情况、监控扫描时间的定时器
//    _connectTimer = [NSTimer scheduledTimerWithTimeInterval:20.f target:self selector:@selector(endScan) userInfo:nil repeats:NO];
//}

- (void)startScan {
    self.connectedPeripheral = nil;
    [self.peripherals removeAllObjects];
 
    if (self.centralManager.state != CBManagerStatePoweredOn) {
        NSLog(@"Bluetooth is not powered on. Aborting scan.");
        // Do not change status here – just wait for BluetoothEnable notification
        // The UI layer listens for BluetoothEnable and will start scan once BLE is ready.
        return;
    }
 
    NSLog(@"Allen manager start scan %d", __LINE__);
    self.status = BluetoothManagerStatusScanStart;
    self.isBgForceConnectDevice = NO;
 
    NSDictionary *scanOptions = @{ CBCentralManagerScanOptionAllowDuplicatesKey: @(YES) };
    [self.centralManager scanForPeripheralsWithServices:nil options:scanOptions];
 
    _connectTimer = [NSTimer scheduledTimerWithTimeInterval:20.0
                                                     target:self
                                                   selector:@selector(endScan)
                                                   userInfo:nil
                                                    repeats:NO];
}

// 断开与外设的连接，取消对characteristic的监听
- (void)terminateConnection {
    for (CBPeripheral *peripheral in self.peripherals) {
        if (peripheral.services != nil) {
            for (CBService *service in peripheral.services) {
                if (service.characteristics != nil) {
                    for (CBCharacteristic *characteristic in service.characteristics) {
                        if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:self.eDevice.eGattMessage.UUID_READ]]) {
                            if (characteristic.isNotifying) {
                                [peripheral setNotifyValue:NO forCharacteristic:characteristic];
                                return;
                            }
                        }
                    }
                }
            }
        }
    }

    if (self.connectedPeripheral) {
        [self.centralManager cancelPeripheralConnection:self.connectedPeripheral];
    }
}

// 连接外设
- (void)connectPeripheral:(CBPeripheral *)peripheral {
    self.status = BluetoothManagerStatusTryToConnect;

    if (self.centralManager && peripheral) {
        [self.centralManager connectPeripheral:peripheral options:nil];
    }
}

// 解绑发射器BLE设备
- (void)closeBleSensor {
    if (self.connectedPeripheral && self.writeReadCharacteristic) {
        NSData *data = [ProtocalTools unBind_request:self.eDevice];
        if ([self.eDevice.deviceType isEqualToString:@"CT4"]) {
            [self.connectedPeripheral writeValue:data forCharacteristic:self.writeReadCharacteristic type:CBCharacteristicWriteWithoutResponse];
        } else {
            [self.connectedPeripheral writeValue:data forCharacteristic:self.writeReadCharacteristic type:CBCharacteristicWriteWithResponse];
        }
    }
}

// 未连接上发射器时强制解绑
- (void)forceEndBleSensor {
    [self.centralManager stopScan];
    
    // 通知初始化页面或首页操作解绑后的流程
    self.status = BluetoothManagerStatusClosed;
    [self resetBleSensorData];
    if ([self.bluetoothDelegate respondsToSelector:@selector(onFindDevices:connectedDevice:)]) {
        [self.bluetoothDelegate onFindDevices:_peripherals connectedDevice:nil];
    }
}

- (Device *)currentDevice {
    if (!_currentDevice) {
        if (self.connectedPeripheral) {
            // 已连接到发射器
            _currentDevice = [[KLTDatabaseHandler shared] queryDeviceWithId:self.connectedPeripheral.identifier.UUIDString];
        } else {
            // 最近连接过的一个设备 之前连接过发射器，失联中
            _currentDevice = [[KLTDatabaseHandler shared] isLatestDeviceDisconnected];
        }
    }
    return _currentDevice;
}

- (void)setStatus:(BluetoothManagerStatus)newStatus {
    _status = newStatus;
    
    //  Notify observers
    [[NSNotificationCenter defaultCenter] postNotificationName:@"BLEStatusUpdated" object:@(newStatus)];
 
    // Print with foreground/background context
    dispatch_async(dispatch_get_main_queue(), ^{
        [self logBluetoothStatus:newStatus];
    });
}
 
- (void)logBluetoothStatus:(BluetoothManagerStatus)status {
    NSString *stateString = UIApplication.sharedApplication.applicationState == UIApplicationStateBackground ? @"Background" : @"Foreground";
    NSLog(@"[BLE] App is in %@ — Status Code******: %ld", stateString, (long)status);
}
- (void)centralManager:(CBCentralManager *)central willRestoreState:(NSDictionary<NSString *,id> *)dict {
    NSLog(@" [RestoreState] iOS triggered state restoration");
 
    NSArray *peripherals = dict[CBCentralManagerRestoredStatePeripheralsKey];
    for (CBPeripheral *peripheral in peripherals) {
        if (!peripheral.identifier) {
            NSLog(@" Skipping peripheral: missing identifier");
            continue;
        }
 
        NSString *peripheralId = peripheral.identifier.UUIDString;
        NSLog(@" Restoring peripheral: %@", peripheralId);
 
        self.connectedPeripheral = peripheral;
        self.connectedPeripheral.delegate = self;
 
        Device *device = [[KLTDatabaseHandler shared] queryDeviceWithId:peripheralId];
        if (!device || !device.advertise || !device.advertise.localName) {
            NSLog(@"No valid device info found in DB for %@", peripheralId);
            continue;
        }
 
        self.eDevice = [EDevice getEnumDevice:device.advertise.localName];
        if (!self.eDevice || !self.eDevice.eGattMessage || !self.eDevice.eGattMessage.UUID_SERVICE) {
            NSLog(@" Invalid eDevice config. Cannot reconnect.");
            continue;
        }
 
        NSLog(@"Attempting reconnect...");
        [self.centralManager connectPeripheral:peripheral options:nil];
    }
 
    NSArray *scanServices = dict[CBCentralManagerRestoredStateScanServicesKey];
    NSDictionary *scanOptions = dict[CBCentralManagerRestoredStateScanOptionsKey];
 
    if (scanServices.count > 0) {
        NSLog(@" Restored scan services: %@", scanServices);
    }
    if (scanOptions) {
        NSLog(@"Restored scan options: %@", scanOptions);
    }
}

@end