//
//  PPDeviceManager.m
//  PaoPao
//
//  Created by lvwang2002 on 14/12/11.
//  Copyright (c) 2014年 paopao. All rights reserved.
//

#import "ENBLEDeviceManager.h"
#import "NSArray+LinqExtensions.h"

@implementation ENBLEDeviceManager{
    CBCentralManager *_centralManager;
    NSMutableArray *_supportMacs;
    
    NSArray *_searchedPeripherals; //搜索到得mac设备
    NSArray *_connectedPeripherals; //链接到得设备
    
    NSDictionary *_deviceInfo;
    BOOL _isScan;
    
    NSTimer *_timer;
  
    dispatch_queue_t _scanQueue;
	dispatch_queue_t _centerQueue;
	dispatch_queue_t _postQueue;
    NSArray *_supportDeviceServerUDID;
    NSArray *_supportDeviceNames;
  
	NSMutableArray *_holdDevices;
	NSArray *bleDevices;
	
	ENSearchedType _searchedType;
	
	NSTimer *_searchedDeviceTimer;
	NSTimer *_updateSearchedDeviceTimer;
	
	CBPeripheral *_peripheral;
}
#pragma mark
#pragma mark centerBlueManagere Delegate

-(instancetype)init{
   self = [super init];
    if (self) {
        _supportMacs = [[NSMutableArray alloc]initWithCapacity:20];
        _searchedPeripherals = [[NSArray alloc] init];
        _connectedPeripherals = [[NSArray alloc] init];
//       _supportDeviceServerUDID =  @[];
      _supportDeviceNames = @[@"BLE-",@"iGate",@"ENUO_",@"Glucose",@"INVS300",@"RBP",@"ClinkBlood",@"O",@"TH-",@"ENUO-G"];
      _holdDevices =[[NSMutableArray alloc] initWithCapacity:20];
			_isScan = NO;
			_searchedType = ENSearchedAllType;
			_BTStatus = ENBTPreparedStatus;
			_postQueue = dispatch_queue_create("com.device.post.bleCenter", NULL);
			[ENDLog share].isDisplayLog = true;
			
			_searchedDeviceTimer =[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(searchedDevices) userInfo:nil repeats:YES];
			
			_updateSearchedDeviceTimer  = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(upgradeSearchedDevices) userInfo:nil repeats:YES];
			
    }
    return self;
}

+(instancetype)shareDeviceManager{
	static ENBLEDeviceManager *deviceManager;
	static dispatch_once_t onceToken;
	dispatch_once(&onceToken, ^{
		deviceManager = [[ENBLEDeviceManager alloc] init];
		[deviceManager run];
	});
	
	return deviceManager;
}

-(void)run{
		_centerQueue = dispatch_queue_create("com.device.bleCenter", NULL);
    _centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:_centerQueue];
	
}

-(BLEDevice *)getDeviceWithUUID:(NSUUID *)uuid{
		NSArray *devices = [_holdDevices linq_where:^BOOL(id item) {
			return [[item getUUID] isEqual:uuid];
		}];
	
		if(devices.count == 0){
			return nil;
		}
	
		return devices[0];
}



- (void)centralManagerDidUpdateState:(CBCentralManager *)central{
    switch (central.state) {
			case CBCentralManagerStatePoweredOff:{
				NSLog(@"CoreBluetooth BLE hardware is Powered off");
				self.BTStatus = ENBTPowerOffStatus;
				[self poweroffHand];
				
				dispatch_async(dispatch_get_main_queue(), ^{
					if([self.deviceManagerDelegate respondsToSelector:@selector(didUpdateBTStatus:)]){
						[self.deviceManagerDelegate  didUpdateBTStatus:ENBTPowerOffStatus];
					};
				});
			}
				break;

        case CBCentralManagerStatePoweredOn:{
            NSLog(@"CoreBluetooth BLE hardware is Powered on and ready");
					self.BTStatus = ENBTPowerOnStatus;
					dispatch_async(dispatch_get_main_queue(), ^{
						if([self.deviceManagerDelegate respondsToSelector:@selector(didUpdateBTStatus:)]){
							[self.deviceManagerDelegate  didUpdateBTStatus:ENBTPowerOnStatus];
						};
					});
			
        }
            break;
        case CBCentralManagerStateResetting:
            NSLog(@"CoreBluetooth BLE hardware is resetting");
            break;
        case CBCentralManagerStateUnauthorized:
            NSLog(@"CoreBluetooth BLE state is unauthorized");
            break;
        case CBCentralManagerStateUnknown:
            NSLog(@"CoreBluetooth BLE state is unknown");
            break;
        case CBCentralManagerStateUnsupported:
            NSLog(@"CoreBluetooth BLE hardware is unsupported on this platform");
            break;
        default:
            break;
    }
}



- (void)centralManager:(CBCentralManager *)central willRestoreState:(NSDictionary *)dict{
    NSLog(@"willRestoreState :%@",dict);
}

- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI{

    if(!_isScan){
        NSLog(@"已经停止扫描");
        return;
    }

    NSString *deviceName = peripheral.name;
	

    BOOL isSupport = [_supportDeviceNames linq_any:^BOOL(id item) {
        return [deviceName hasPrefix:item];
    }];
    
    if(!isSupport){
//			[[ENDLog share] log:@"搜索到不支持设备"];
        return;
    }
	

	
		//判断是否是指定的设备
		BOOL isConnectedType  = [self isSearchedTypeWithDeviceName:deviceName];
		if(!isConnectedType){
			return;
		}

		ENLog(@"device name:");
		ENLog(deviceName);

    NSUUID *uuid = peripheral.identifier;
	
		BLEDevice *device = [self getBleDevice:uuid];
		BOOL isNewly = YES;
		if (device == nil) {
			NSString *scanContent =[NSString stringWithFormat:@"Did discover peripheral. peripheral: %@ rssi: %@, UUID: %@ advertisementData: %@ ", peripheral, RSSI, peripheral.identifier, advertisementData];
			ENLog(scanContent);
			//如果为空,则说明还没有接受管控,直接加入到管控列表.
			device = [[BLEDevice alloc] initWithPeripheral:peripheral CentralManager:_centralManager DeviceManager:self];
			device.advertisementData = advertisementData;
			peripheral.delegate = device;
			[_holdDevices addObject:device];
		}else{
			isNewly = NO;
		}
	
	device.searchDate = [NSDate date]; //刷新设备发现时间
	
	
		dispatch_async(dispatch_get_main_queue(), ^{
			if([_deviceManagerDelegate respondsToSelector:@selector(didDiscoverDevice:IsNewly:)]){
				[_deviceManagerDelegate didDiscoverDevice:device IsNewly:isNewly];
			}
		});

}



- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{
		//告知外部连接成功
	dispatch_async(dispatch_get_main_queue(), ^{
		BLEDevice *device = [self getBleDevice:peripheral.identifier];
		[device setConnectStatus:DeviceConnectedStatus];
		if([_deviceManagerDelegate respondsToSelector:@selector(didConnectedDevice:)]){
			[_deviceManagerDelegate didConnectedDevice:device];
		}
        [device setConnectedDevice];
	});
	
	
	[peripheral discoverServices:nil];
	
	
	
		//请求一次读取信号强度
	[peripheral performSelector:@selector(readRSSI) withObject:nil afterDelay:1];
}


- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{
	//断开连接后,在连接设备中去掉该项,可以重新开始扫描.
	ENLog(@"设备断开连接");
	BLEDevice *device = [self getBleDevice:peripheral.identifier];
	peripheral.delegate = nil;
	
	if(device == nil){
		ENLog(@"断开设备已经从存储数组中删除");
		return;
	}
	
	@try {
		[_holdDevices removeObject:device];
	} @catch (NSException *exception) {
		ENLog(@"删除不存在设备,报错");
	}
	
	device.connectStatus = DeviceDisconnectedStatus;
	
	dispatch_async(dispatch_get_main_queue(), ^{
		if([device.deviceDelegate respondsToSelector:@selector(didDisconnectDevice:)]){
			[device.deviceDelegate didDisconnectDevice:device];
		}
	});
}


- (NSString *)getHexStringWithValue:(int)values{
    NSString *newHexStr = [NSString stringWithFormat:@"%x",values&0xff];
    if([newHexStr length]==1)
        newHexStr = [NSString stringWithFormat:@"0%@",newHexStr];
    else
        newHexStr = [NSString stringWithFormat:@"%@",newHexStr];
    
    newHexStr = [NSString stringWithFormat:@"0x%@",newHexStr];
    
    return newHexStr ;
}



/** 开始扫描 */
-(void)startScan{
  //如果不为空的话,直接开始扫描就可以,为空的
  if(_scanQueue){
    _isScan = YES;
    return;
  }
	
  _isScan = YES;
  _scanQueue = dispatch_queue_create("com.device.scanqueue", NULL);
  dispatch_async(_scanQueue, ^{
    while (1) {
      if(!_isScan){
				[NSThread sleepForTimeInterval:0.5];
        continue;
      }
      
      dispatch_async(dispatch_get_main_queue(), ^{
        ENLog(@"enable scan");
        [_centralManager scanForPeripheralsWithServices:nil
																								options:nil];
      });
      
			[NSThread sleepForTimeInterval:2.5];
      dispatch_async(dispatch_get_main_queue(), ^{
        ENLog(@"disable scan");
        [_centralManager stopScan];
      });
			[NSThread sleepForTimeInterval:0.5];
    }
  });
}

/** 停止扫描 */
-(void)stopScan{
    [_centralManager stopScan];
    _isScan = NO;
}

-(void)emptySearchedPeripherals{
    _searchedPeripherals = [[NSArray alloc]init];
}

//蓝牙关断处理方法.
-(void)poweroffHand{
    ENLog(@"设备断开连接");
    _isScan = NO;

	for (BLEDevice *device in _holdDevices) {
		[device disconnect];
		dispatch_async(dispatch_get_main_queue(), ^{
			if([device.deviceDelegate respondsToSelector:@selector(didDisconnectDevice:)]){
				[device.deviceDelegate didDisconnectDevice:device];
			}
		});
	}
	
	_holdDevices = [[NSMutableArray alloc] initWithCapacity:20];
}


/** 根据指定的设备得到 */
-(BLEDevice *)getBleDevice:(NSUUID *)uuid{
  NSArray *devices = [_holdDevices linq_where:^BOOL(id item) {
      BLEDevice *device = item;
      return [device.getUUID isEqual:uuid];
  }];
  
  if([devices count]<=0){
    return nil;
  }else{
    return devices[0];
  }
};

/** 处理错误 */
-(void)uhoh:(BLEDevice *)device{
	[_holdDevices removeObject:device];
  [device disconnect];
}


/** 判断是否有设备连接 */
-(BOOL)hasDeviceConnectedWithType:(ENSearchedType)type{
	NSArray *connectedDevices = [_holdDevices linq_where:^BOOL(id item) {
		BLEDevice *device = (BLEDevice *)item;

		if(type == ENSearchedKetoneType){
			NSString *deviceName = [device getDeviceName];
			return (device.connectStatus == DeviceConnectedStatus && [deviceName hasPrefix:@"BLE-ENUO"])
            || (device.connectStatus == DeviceConnectedStatus && [deviceName hasPrefix:@"ENUO-G"])
            || (device.connectStatus == DeviceConnectedStatus && type == ENSearchedAllType);
		}else{
			ENSearchedType deviceType = [self getDeviceTypeWithDeviceName:[device getDeviceName]];
			
			return ((device.connectStatus == DeviceConnectedStatus && type == deviceType) ||
							(device.connectStatus == DeviceConnectedStatus && type == ENSearchedAllType));
		}
	}];
	
	return (connectedDevices.count > 0);
}

/** 判断是否有设备正在连接 */
-(BOOL)hasDeviceConnectingWithType:(ENSearchedType)type{
	NSArray *connectingDevices = [_holdDevices linq_where:^BOOL(id item) {
		BLEDevice *device = (BLEDevice *)item;
		if(type == ENSearchedKetoneType){
			NSString *deviceName = [device getDeviceName];
			return (device.connectStatus == DeviceConnectingStatus &&[deviceName hasPrefix:@"BLE-ENUO"])
            || (device.connectStatus == DeviceConnectingStatus &&[deviceName hasPrefix:@"ENUO-G"])
            || (device.connectStatus == DeviceConnectingStatus && type == ENSearchedAllType);
		}else{
			ENSearchedType deviceType = [self getDeviceTypeWithDeviceName:[device getDeviceName]];
			
			return ((device.connectStatus == DeviceConnectingStatus && type == deviceType) ||
							(device.connectStatus == DeviceConnectingStatus && type == ENSearchedAllType));
		}
	}];
	
	return (connectingDevices.count > 0);
}



/** 指定类型连接 */
-(void)setSearchedDeviceType:(ENSearchedType)searchedDeviceType{
	_searchedType = searchedDeviceType;
}

/** 判断设备是否是指定的设备 */
-(BOOL)isSearchedTypeWithDeviceName:(NSString *)deviceName{
	if(_searchedType == ENSearchedAllType){
		return true;
	}else if(_searchedType == ENSearchedGlucoType) {
		if([deviceName hasPrefix:@"Glucose"]
           || [deviceName hasPrefix:@"BLE-ENUO"]
           || [deviceName hasPrefix:@"ENUO-G"]){
			return true;
		}else{
			return false;
		}
	}else if(_searchedType == ENSearchedBPType){
		if([deviceName hasPrefix:@"RBP"] ||
			 [deviceName hasPrefix:@"ClinkBlood"]){
			return true;
		}else{
			return false;
		}
	}else if(_searchedType == ENSearchedCholesterolType ){
		if([deviceName hasPrefix:@"iGate"]){
			return true;
		}else{
			return false;
		}
	}else if(_searchedType == ENSearchedKetoneType){
		if([deviceName hasPrefix:@"BLE-ENUO"]){
			return true;
		}else{
			return false;
		}
	}
	return  false;
}

-(NSArray *)getSearchedDevices{
	return [_holdDevices copy];
}


-(void)postUpdateDeviceList{
    dispatch_async(dispatch_get_main_queue(), ^{
        [self searchedDevices];
    });
}


/** 更新界面 */
-(void)searchedDevices{
	dispatch_async(dispatch_get_main_queue(), ^{
		if([self.deviceManagerDelegate respondsToSelector:@selector(didUpdateSearchedDevices:)]){
			NSArray *typeDevices = [_holdDevices linq_where:^BOOL(id item) {
				BLEDevice *device = (BLEDevice *)item;
				ENSearchedType type  = [self getDeviceTypeWithDeviceName:[device getDeviceName]];
				return ((_searchedType == ENSearchedAllType) || (_searchedType == type));
			}];
			
			[self.deviceManagerDelegate didUpdateSearchedDevices:typeDevices];
		}
	});
}

/** 更新搜索列表的内容 */
-(void)upgradeSearchedDevices{
  //	ENLog(@"1S刷新扫描设备列表");
	NSArray *updateDevices = [_holdDevices linq_where:^BOOL(id item) {
		BLEDevice *device = (BLEDevice *)item;
		if((fabs([device.searchDate timeIntervalSinceDate:[NSDate date]])>=10.0) &&
			 device.connectStatus == DeviceSearchedStatus){
			return NO;
		}else{
			return YES;
		}
	}];
	
	NSString *log =[NSString stringWithFormat:@"update device count:%lu",(unsigned long)updateDevices.count];
	//ENLog(log);
	
	_holdDevices  = [updateDevices mutableCopy];
}

/** 设置是否输出 */
-(void)setIsShowLog:(BOOL)isShow{
	[ENDLog share].isDisplayLog = isShow;
}

/** 当前连接的设备 */
-(BLEDevice *)getCurrentConnectedDeviceWithType:(ENSearchedType)type{
	NSArray *connectedDevices = [_holdDevices linq_where:^BOOL(id item) {
		BLEDevice *device = (BLEDevice *)item;
		ENSearchedType deviceType = [self getDeviceTypeWithDeviceName:[device getDeviceName]];
		return ((device.connectStatus == DeviceConnectedStatus && type == deviceType) ||
						(device.connectStatus == DeviceConnectedStatus && type == ENSearchedAllType));
	}];
	
	return connectedDevices.count>0?[connectedDevices firstObject]:nil;
}

/** 根据名字获取类型 ,不包括血酮 */
-(ENSearchedType)getDeviceTypeWithDeviceName:(NSString *)deviceName{
	if([deviceName hasPrefix:@"Glucose"]
       || [deviceName hasPrefix:@"BLE-ENUO"]
       || [deviceName hasPrefix:@"ENUO-G"]){
		return ENSearchedGlucoType;
	}else if([deviceName hasPrefix:@"RBP"] ||
		 [deviceName hasPrefix:@"ClinkBlood"]){
		return ENSearchedBPType;
	}else if([deviceName hasPrefix:@"iGate"]){
		return ENSearchedCholesterolType;
	}
	
	return ENSearchedAllType;
}

/** 删除设备 */
-(void)removeDevice:(BLEDevice *)device{
	@try {
		[_holdDevices removeObject:device];
	} @catch (NSException *exception) {
		
	} @finally {
		
	}
}

/** 断开连接 */
-(void)disconnectAllDevices{
	for(BLEDevice *device in _holdDevices){
		[device disconnect];
	}
}

-(dispatch_queue_t)getPostQueue{
	return _postQueue;
}

@end
