//
//  Copyright © 2018年 dahua. All rights reserved.
//

#import "DHNetSDKSearchManager.h"
#import "DHNetSDKInterface.h"
#import "DHDeviceNetInfo.h"
#import <LCBaseModule/UIDevice+LeChange.h>
#import <LCBaseModule/DHNetWorkHelper.h>
#import <LCBaseModule/DHModuleConfig.h>
#import <LCBaseModule/DHFileManager.h>
#import <LCBaseModule/DHMobileInfo.h>
#import <LCAddDeviceModule/LCAddDeviceModule-Swift.h>

@interface DHNetSDKSearchManager()

@property (nonatomic, strong) NSMutableDictionary<NSString *, DHDeviceNetInfo*> *netInfoDic;
@property (nonatomic, assign) long searchHandle;
@property (nonatomic, copy) dispatch_queue_t queue;
@property (nonatomic, copy) dispatch_queue_t searchQueue;
@property (nonatomic, strong) NSTimer *timer;
@property (nonatomic, assign) NSInteger tickCount;
@property (nonatomic, assign) NSTimeInterval lastFindTime; /**< 记录上次NETSDK回调结果的时间 */
@property (nonatomic, assign) NSInteger searchSequence; /**< 搜索的序号 */
@property (nonatomic, copy) NSString *lastSSID;//上次连接的wifi的ssid,用于网络环境变化重新搜索设备

@end

@implementation DHNetSDKSearchManager

#pragma mark - circle life

- (instancetype)init
{
    if(self = [super init])
    {
        [self initNetSdk];
        _netInfoDic = @{}.mutableCopy;
		_queue = dispatch_queue_create("syncOperation", DISPATCH_QUEUE_CONCURRENT);
		_searchQueue = dispatch_queue_create("searchQueue", DISPATCH_QUEUE_SERIAL);
		_tickCount = 0;
		
#if DEBUG
		_showDebugLog = NO;
#else
		_showDebugLog = YES;
#endif
    }
    return self;
}

- (void)dealloc {
	[[NSNotificationCenter defaultCenter] removeObserver:self];
}

#pragma mark - Notification
- (void)addObservers {
	//防止重复添加
	[self removeObservers];
	
	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillResignActive:)
												 name:UIApplicationWillResignActiveNotification object:nil]; //监听是否触发home键挂起程序,(把程序放在后台执行其他操作)
	
	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidBecomeActive:)
												 name:UIApplicationDidBecomeActiveNotification object:nil]; //监听是否重新进入程序程序.(回到程序)
	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(networkDidChanged:)
												 name:@"LCNotificationWifiNetWorkDidSwitch" object:nil];//从一个wifi网络切换到另外一个wifi网络也要重新获取设备列表
}

- (void)removeObservers {
	[[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)applicationWillResignActive:(NSNotification *)notification
{
	if(self.timer != nil) {
		[self.timer fire];
		[self.timer invalidate];
		self.timer = nil;
	}
	
	DH_LOG_FUN
	
	dispatch_async(self.searchQueue, ^{
		if(self.searchHandle) {
			NSLog(@"DHNetSDKSearchManager::Stop search in resign active:%ld, sequence:%ld", self.searchHandle, (long)self.searchSequence);
			[[DHNetSDKInterface sharedInstance] stopSearchDevices:self.searchHandle];
			self.searchHandle = 0;
		}
	});
}

- (void)applicationDidBecomeActive:(NSNotification *)notification
{
	if(self.isSearching)
	{
		[self startSearch];
	}
}

- (void)networkDidChanged:(NSNotificationCenter *)notification {
	// DTS000583328 偶现崩溃 [DHMobileInfo sharedInstance].WIFISSID
	if (!self.isSearching) {
		return;
	}
	
    //针对软ap添加的bug
    NSString *wifiSSID = [[DHMobileInfo sharedInstance].WIFISSID uppercaseString];
    if (![wifiSSID isEqualToString:self.lastSSID] && wifiSSID.length) {
        self.lastSSID = wifiSSID;
        [self.netInfoDic removeAllObjects];
        if(self.isSearching) {
            [self startSearch];
        }
    }
}

#pragma mark - interface

- (void)startSearch
{
	if(self.timer != nil) {
		[self.timer fire];
		[self.timer invalidate];
		self.timer = nil;
	}
	
	DH_LOG_FUN
	
	NSInteger tick = 2;
	self.timer = [NSTimer scheduledTimerWithTimeInterval:tick target:self selector:@selector(timeTick) userInfo:nil repeats:YES];
	self.isSearching = YES;
	[self timeTick];
	
	//添加通知
	[self addObservers];
}

- (void)timeTick
{
	//wifi连接连接过程中,可能会出现无法识别的情况,不能加此判断
	//只处理ios13以下系统,不是WiFi状态时,不进行检测
	if (DH_IOS_VERSION < 13 &&
		[DHNetWorkHelper sharedInstance].emNetworkStatus != AFNetworkReachabilityStatusReachableViaWiFi) {
		return;
	}
	
	//【*】打印当前的WIFI信息、定位软AP相关问题
	if (self.tickCount % 10 == 0) {
		NSLog(@"DHNetSDKSearchManager::当前WIFI信息 %@, Mask:%@, Router:%@, IP:%@",
			  DHMobileInfo.sharedInstance.WIFISSID,
			  UIDevice.lc_getMaskAddress,
			  [UIDevice lc_getRouterAddress],
			  UIDevice.lc_getIPAddress);
	}
	
	//计时不中断
	self.tickCount++;
	
	NSInteger intervalCheck = 10;
	if(self.tickCount % intervalCheck == 0) {
		[self clearnUnReceiveDevice];
	}
	
	if (self.tickCount % 5 == 0) {
		if (_showDebugLog) {
			dispatch_barrier_async(self.queue, ^{
				NSLog(@"当前搜索到的设备:\n%@",self.netInfoDic.allKeys);
			});
		}
	}
	
	// 距离上次回调时间大于3s,才重新开始重新搜索
	NSTimeInterval currentTime = NSDate.date.timeIntervalSince1970;
	if (fabs(currentTime - self.lastFindTime) < 3) {
		NSLog(@"DHNetSDKSearchManager:: Ignore tick process...");
		return;
	}
	
	// 已经停止了,不需要再重新搜索
	if (self.isSearching == false) {
		NSLog(@"DHNetSDKSearchManager:: Search is stopped, return...");
		return;
	}
	
	dispatch_async(self.searchQueue, ^{
		if(self.searchHandle) {
			NSLog(@"DHNetSDKSearchManager::Stop search in timetick:%ld, sequence:%ld", self.searchHandle, (long)self.searchSequence);
			[[DHNetSDKInterface sharedInstance] stopSearchDevices:self.searchHandle];
			self.searchHandle = 0;
		}
		
		//【*】记录下当前搜索的序号
		//【*】优化:采用传IP+不传IP交替搜索
		NSString *localIp = (self.searchSequence % 2) == 0 ? UIDevice.lc_getIPAddress : nil;
		
		self.searchSequence++;
		NSInteger sequence = self.searchSequence;
		
		self.searchHandle = [[DHNetSDKInterface sharedInstance] startSearchDevices:^(DHDeviceNetInfo *netInfo) {
			dispatch_barrier_async(self.queue, ^{
				netInfo.searchSequence = sequence;
				if (self.showDebugLog) {
					NSLog(@"DHNetSDKSearchManager::-find device: %@ - %@,搜索序号:%ld, Init type:%lu, status: %lu",
						  netInfo.deviceType, netInfo.serialNo, (long)netInfo.searchSequence, (unsigned long)netInfo.deviceInitType, (unsigned long)netInfo.deviceInitStatus);
				}
	
				//避免找到deviceId为空的情况
				if (netInfo.serialNo.length > 0) {
					DHNetSDKSearchManager.sharedInstance.netInfoDic[netInfo.serialNo] = netInfo;
				}
				
				self.lastFindTime = NSDate.date.timeIntervalSince1970;
			});
		} byLocalIp: localIp];
		
		NSLog(@"DHNetSDKSearchManager:: Start search with handle:%ld, search sequence:%ld", self.searchHandle, (long)self.searchSequence);
		
		if(self.searchHandle == 0) {
			unsigned int errorCode = [DHNetSDKInterface getLastError];
			NSLog(@"NetSDKInteface:: Load wifilist failed with errorCode:...0x%x", errorCode);
			NSLog(@"DHNetSDKSearchManager::CLIENT_StartSearchDevices-fail");
			
            DHAddDeviceLogModel *model = [[DHAddDeviceLogModel alloc] init];
            model.method = @"startSearchDevices";
            model.res = model.resFail;
            model.errCode = errorCode;
            [[DHAddDeviceLogManager shareInstance] addDeviceNetSDKLogWithModel:model];
		}
	});
}

- (void)stopSearch {
	//停止通知
	[self removeObservers];
	
	dispatch_barrier_async(self.queue, ^{
		[self.netInfoDic removeAllObjects];
	});
	
	if(self.timer != nil) {
		[self.timer fire];
		[self.timer invalidate];
		self.timer = nil;
	}
	
	dispatch_async(self.searchQueue, ^{
		if(self.searchHandle) {
			NSLog(@"DHNetSDKSearchManager::Stop search in stop:%ld, sequence:%ld", self.searchHandle, (long)self.searchSequence);
			[[DHNetSDKInterface sharedInstance] stopSearchDevices:self.searchHandle];
			self.searchHandle = 0;
		}
	});
	
	self.searchSequence = 0;
	self.lastFindTime = 0;
	self.isSearching = NO;
}

- (id<ISearchDeviceNetInfo>)getNetInfoByID:(NSString *)deviceID;
{
	__block id<ISearchDeviceNetInfo> device;
	dispatch_barrier_sync(self.queue, ^{
		device = self.netInfoDic[deviceID];
	});

    return device;
}

#pragma mark - Custom
- (void)clearnUnReceiveDevice
{
	dispatch_barrier_async(self.queue, ^{
		//把所有未标记的从dic中一出  已标记的变成未标记 等待下一次的搜索
		NSArray<NSString *> *allKeys = [self.netInfoDic allKeys].copy;
		
		for (NSString *key in allKeys)
		{
			DHDeviceNetInfo *device = self.netInfoDic[key];
			if(!device.isVaild)
			{
				NSLog(@"%@ 在这次搜索中被移除", key);
				[self.netInfoDic removeObjectForKey:key];
			}
			else if (device.searchSequence != self.searchSequence)
			{
				//【*】21589:只有当前的搜索结束了,才将缓存中未搜索到的设备有效状态重置
				NSLog(@"DHNetSDKSearchManager:: 重置设备有效状态,设备 %@, 搜索序号: %ld, 当前序号:%ld", device.deviceSN, (long)device.searchSequence, (long)self.searchSequence);
				self.netInfoDic[key].isVaild = NO;
			}
		}
	});
}

#pragma mark - private method


-(void)initNetSdk
{
	[DHNetSDKInterface initSDK];
	
#if DEBUG
	NSString *path = [[DHFileManager supportFolder] stringByAppendingPathComponent:@"cache"];
	[DHNetSDKInterface logOpen: path];
#endif
}

#pragma mark - singleton
static DHNetSDKSearchManager *_instance = nil;
+ (instancetype)sharedInstance
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [[self alloc] init];
    });
    return _instance;
}

+ (id)allocWithZone:(struct _NSZone *)zone
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [super allocWithZone:zone];
    });
    return _instance;
}

- (id)copyWithZone:(NSZone *)zone{
    return _instance;
}
@end