/**
 * WebSocket 工具函数库
 * 整个项目中只会纯在一个WebSocket实例对象（便于兼容）
 * 
 * 先initWs、再进行registerEvents，最后才能sendWsMsg
 * 
 * initWs 初始化WebSocket 连接
 * registerEvents 注册监听事件
 * destroyEvents 销毁已注册的监听事件
 * sendWsMsg 发送WebSocket消息（统一发送字符串类型参数，便于兼容）
 * closeWs 关闭WebSocket连接
 * */

import { baseUrl } from '@/config/baseConfig.js'

const wsUrl = baseUrl('wsUrl') // 连接地址

let socketTaskAr = []

/**
 * 检测WebSocket实例是否已经存在
 * */
 function checkWSInstance () {
	 return !!getApp().globalData.webSocketInstance
 }
 
 function loopCheckWSInstance (cb = null, params) {
	 const _time = setInterval(() => {
		 if (checkWSInstance()) {
			 clearInterval(_time)
			 cb && cb(params)
		 }
	 }, 300)
 }

/**
 * 初始化WebSocket 连接
 * @param {Object} self 页面实例（_vm）
 * @param {Object} params 附加参数 { send, forever, msg }
 * 							send: false/true 表示首次链接完成之后，调用消息发送
 * 							forever: false/true 表示只要调用initWs，且forever为true，就是调用消息发送
 * 							msg: 表示发送的消息内容
 * */
export function initWs (self, params = null) {
	if (checkWSInstance()) {
		if (params) {
			if (params.forever) {
				sendWsMsg(params.msg || '')
			}
		}
	} else {
		const _appGlobalData = getApp().globalData
		try {
			if (_appGlobalData.socketTask) return;
			const _accessTokenAndMacKey = JSON.parse(uni.getStorageSync('oauthAccessToken'));
			
			// 创建连接
			_appGlobalData.socketTask = uni.connectSocket({
				url: wsUrl + `?token=${_accessTokenAndMacKey.accessToken}`,
				complete: () => {}
			})
			// 各个事件钩子监听
			_appGlobalData.socketTask.onOpen((res) => {
				console.log('onOpen')
				if (self) {
					_appGlobalData.webSocketInstance = _appGlobalData.socketTask
					socketTaskAr.push(_appGlobalData.socketTask)
				}
				if (params) {
					if (params.send || params.forever) {
						sendWsMsg(params.msg || '')
					}
				}
			})
			_appGlobalData.socketTask.onClose((res) => {
				console.log('onClose')
				// 清除已存在的实例对象
				_appGlobalData.socketTask = null
				_appGlobalData.webSocketInstance = null
			})
			_appGlobalData.socketTask.onError((res) => {
				console.log('onError: 将尝试重新连接webSocket服务！')
				// 清除已存在的实例对象
				if (checkWSInstance()) {
					_appGlobalData.socketTask = null
					_appGlobalData.webSocketInstance = null
				}
				// 尝试重新连接webSocket服务，次数限定50次
				let count = 0
				const total = 50
				const _timeer = setInterval(() => {
					count++
					if (count <= total) {
						initWs(self)
					} else {
						clearInterval(_timeer)
					}
				}, 5 * 1000)
			})
			_appGlobalData.socketTask.onMessage((res) => {
				// todo 处理注册事件
				const _eventsStock = _appGlobalData.registerEventsStock
				const _len = _eventsStock.length
				for (let event in _eventsStock) {
					_eventsStock[event].cb && _eventsStock[event].cb(res)
				}
			})
		} catch {
			// 跳转登录页
			uni.navigateTo({
				url: '/pages/login/index'
			});
		}
		
	}
}

/**
 * 注册监听事件
 * @param {String} eventName 事件名称
 * @param {Function} eventFun 处理事件函数（用于回调）
 * */
export function registerEvents (eventName = 'eventName', eventFun = null) {
	const _appGlobalData = getApp().globalData
	const _eventsStock = _appGlobalData.registerEventsStock
	_appGlobalData.registerEventsStock = {
		[eventName]: {
			cb: eventFun
		},
		..._eventsStock
	}
}

/**
 * 销毁已注册的监听事件
 * @param {String} eventName 事件名称
 * */
export function destroyEvents (eventName = 'eventName') {
	const _appGlobalData = getApp().globalData
	const _eventsStock = _appGlobalData.registerEventsStock
	delete _eventsStock[eventName]
	_appGlobalData.registerEventsStock = {
		..._eventsStock
	}
}

/**
 * 关闭WebSocket连接
 * */
export function closeWs () {
	socketTaskAr.map(instance => {
		instance.close()
	})
	socketTaskAr = []
}

/**
 * 发送WebSocket消息（统一发送字符串类型参数，便于兼容）
 * @param {Object | Array | String} msg 待发送的消息
 * */
export function sendWsMsg (msg = '') {
	if (checkWSInstance()) {
		const _webSocketInstance = getApp().globalData.webSocketInstance
		let _msg = ''
		if (Array.isArray(msg)) {
			if (mag.length) {
				_msg = msg.join()
			}
		} else if (typeof msg === 'object') {
			_msg = JSON.stringify(msg)
		} else {
			_msg = msg
		}
		console.log(_msg)
		_webSocketInstance.send({
			data: _msg
		})
	} else {
		loopCheckWSInstance(sendWsMsg, msg)
	}
}
