import {
	getStorage,
	setStorage
} from '@/utils/localStorage';
window.sessionTime = new Date();
var socketTaskList = []; //websocket 待发送任务列表
var socketInter = null;
/**
 * websocket配置项
 * @type {{serverTimeoutObj: null, timeoutObj: null, timeoutnum: null, lockReconnect: boolean, ws: null, params: {houseId: null, openid: null, userid: null}, timeout: number}}
 */
let wsConfig = {
    ws: null,
    lockReconnect: false,    //是否真正建立连接
	interval: null,
    timeoutObj: null,   //心跳心跳倒计时
    serverTimeoutObj: null,   // 服务连接超时时间
    timeoutnum: null,  // 断开重连倒计时
    timeout: 58 * 1000,  // 58秒一次心跳
    // 建立ws连接时，所需参数
    params: {
        openid: null,
        userid: null,
        houseId: null
    }
}
/**
 * 获取随机数,为socket请求拼接后缀
 */
function uuid(len, radix) {
	var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
	var uuid = [],
		i;
	radix = radix || chars.length;
	if (len) {
		for (i = 0; i < len; i++) uuid[i] = chars[0 | Math.random() * radix];
	} else {
		var r;
		uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
		uuid[14] = '4';

		for (i = 0; i < 36; i++) {
			if (!uuid[i]) {
				r = 0 | Math.random() * 16;
				uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];
			}
		}
	}
	return uuid.join('');
}
/**
 * 初始化websocket
 */
function initWebsocket() {
    let str1 = parseInt(Math.random() * 10);
    let str2 = parseInt(Math.random() * 10);
    let str3 = parseInt(Math.random() * 10);
    let str4 = "" + str1 + str2 + str3;
    //初始化weosocket
    let websocketUrl = $config.ws_url;
	let rod = uuid(8, 60);
    const wsuri =
        `${websocketUrl}gs-guide-websocket/` +
        str4 +
        "/" + rod + "/websocket";
    wsConfig.ws = new WebSocket(wsuri);
    // 连接建立时触发
    wsConfig.ws.onopen = websocketonopen;
    // 客户端接收服务端数据时触发
    wsConfig.ws.onmessage = websocketonmessage;
    // 通信发生错误时触发
    wsConfig.ws.onerror = websocketonerror;
    // 连接关闭时触发
    wsConfig.ws.onclose = websocketclose;
    return wsConfig.ws;
}

/**
 * 连接建立时触发
 */
function websocketonopen() {
	let data = initPage();
    console.log('建立ws连接', data)
	//开启心跳
	start();
    //发送链接身份数据
    connectSend(data.openId, data.userId, data.houseId);
}

/**
 * 客户端接收服务端数据时触发
 * @param e
 */
function websocketonmessage(e) {
    // console.log('客户端接收服务端数据时触发', e);
    //收到服务器信息，心跳重置
    reset();
}

/**
 * 通信发生错误时触发
 */
function websocketonerror() {
    console.log("出现错误");
    reconnect();
}

/**
 * 连接关闭时触发
 * @param e
 */
function websocketclose(e) {
    //关闭
    console.log("断开连接", e);
	socketInter && clearInterval(socketInter);//清空心跳发送
	socketInter = null;
    //重连
    reconnect();
}

function websocketsend(Data) {
    // console.log('ws状态', wsConfig.ws)
	if(wsConfig.ws && wsConfig.ws.readyState==1){
		let param = [
			"SEND" +
			"\nproject:" +
			"elab-marketing-system" +
			"\nmethod:" +
			"POST" +
			"\npath:" +
			"/behavior/brandMiniWeb/upload" +
			"\ndestination:" +
			"/ws/remote/invoke" +
			"\n\n" +
			JSON.stringify(Data) +
			"\u0000",
		];
		//数据发送
		wsConfig.ws.send(JSON.stringify(param));
	}else{
		// 如果还没有创建好socket链接或者链接还没打开,则放到待发送列表中
		if(Data){
			socketTaskList.push(Data);
		}
		console.log("***ws-socketTaskList列表count***", socketTaskList.length)
		return
	}
    
}
/**
 * 解析页面路由参数
 * @param name
 * @returns {null}
 */
function getQueryString(name) {
    let reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i');
    let arr = window.location.href.split('?');
    let result = null;
    arr.forEach((item, index) => {
        let res = item.match(reg);
        if (res != null) {
            result = unescape(res[2]);
        }
    })
    return result
}
/**
 * 初始进入页面参数
 */
function initPage(){
	let userInfo = getStorage('userInfo') ? JSON.parse(getStorage('userInfo')) : null;
	let queryObj = getStorage('queryObj') ? JSON.parse(getStorage('queryObj')) : null;
	let urlObj = queryObj || util.getUrlParams(location.href) || {};
	let brandId = urlObj.brandId || urlObj.special_ID || $config.brandId || '';
	let userId = urlObj.leavePhoneCustomerId ? urlObj.leavePhoneCustomerId : (userInfo?userInfo.userId:'');
    return {
        session: urlObj.session || '',
        // 项目id，默认仙女山项目
        houseId: urlObj.xcxHouseId || urlObj.houseId || '',
        userId: userId || '',
        openId: urlObj.openid || (userInfo ? userInfo.openId : ''),
        brandId: brandId || '',
        product: urlObj.xcxHouseId || urlObj.houseId || '',
        fromPlatform: urlObj.fromProduce || '',
        platform: urlObj.platform || '',
        scene: urlObj.scene1 || '',
		layoutName: urlObj.layoutName || '',
    }
}
/**
 * 发送ws连接请求
 */
function connectSend(openid, userid, houseId) {
    console.log('建立ws通信', openid, userid, houseId)
	//发送堆积的待发送消息
    const param = [
        "CONNECT" +
        "\nopenId:" +
        openid +
        "\nplatform:" +
        "1" +
        "\nhouseId:" +
        houseId +
        "\nuserId:" +
        userid +
        "\naccept-version:1.1,1.0\nheart-beat:5000,5000\n\n\u0000",
    ];
    websocketsend(JSON.stringify(param));
	if (socketTaskList && socketTaskList.length > 0) {
		for (var i = 0; i < socketTaskList.length; i++) {
			if(socketTaskList[i]){
				// wsConfig.ws.send(socketTaskList[i]);
				if(!socketTaskList[i].userId){
					socketTaskList[i].userId = userid;
					socketTaskList[i].brandUserId = userid;
				}
				if(!socketTaskList[i].openId){
					socketTaskList[i].openId = openid;
				}
				// console.log("***ws-socketTaskList列表***", socketTaskList[i])
				let param = [
					"SEND" +
					"\nproject:" +
					"elab-marketing-system" +
					"\nmethod:" +
					"POST" +
					"\npath:" +
					"/behavior/brandMiniWeb/upload" +
					"\ndestination:" +
					"/ws/remote/invoke" +
					"\n\n" +
					JSON.stringify(socketTaskList[i]) +
					"\u0000",
				];
				// 发送堆积的待发送消息
				wsConfig.ws.send(JSON.stringify(param));
				socketTaskList[i] = null;
			}
		}
		for (var i = 0; i < socketTaskList.length; i++) {
			if(!socketTaskList[i]){
				socketTaskList.splice(i,1);
			}
		}
	}
}

/**
 * 重新连接ws
 */
function reconnect() {
    console.log('重新连接ws');
    //重新连接
    if (wsConfig.lockReconnect) {
        return;
    }
    wsConfig.lockReconnect = true;
    //没连接上会一直重连，设置延迟避免请求过多
    wsConfig.timeoutnum && clearTimeout(wsConfig.timeoutnum);
    wsConfig.timeoutnum = setTimeout(() => {
        //新连接
        initWebsocket()
        wsConfig.lockReconnect = false
    }, 5000)
	socketInter && clearInterval(socketInter);//清空心跳发送
	socketInter = null;
}

/**
 *  重置ws连接
 */
function reset() {
    console.log('重启心跳')
    //重置心跳
    clearTimeout(wsConfig.timeoutObj);
    // //清除时间
    clearTimeout(wsConfig.serverTimeoutObj);
    //重启心跳
    // wsSendHeartBeat();
	//开启心跳
	start();
}
// socket 心跳发送
function wsSendHeartBeat() {
	let ws = wsConfig.ws;
	let data = ["\n"];//心跳的数据格式
	if(!socketInter){
		console.warn('***ws-开启WebSocket心跳***');
		//5秒钟发送一次心跳
		socketInter = setInterval(()=>{
			// console.warn("***ws-SendHeartBeat-尝试心跳发送:");
			//这里发送一个心跳，后端收到后，返回一个心跳消息，
			// console.warn('***ws-心跳***');
			if (ws.readyState == 1) {
			    //如果连接正常
			    ws.send(JSON.stringify(data)); //这里可以自己跟后端约定
			} else {
			    //否则重连
			    reconnect();
			}
		},5000)
	}
}
/**
 * 开启ws连接
 */
function start() {
    let ws = wsConfig.ws;
    // console.log("开启心跳", wsConfig,ws.readyState);
	let data = ["\n"];//心跳的数据格式
	ws.send(JSON.stringify(data));
    wsConfig.timeoutObj && clearTimeout(wsConfig.timeoutObj);
    wsConfig.serverTimeoutObj && clearTimeout(wsConfig.serverTimeoutObj);
    wsConfig.timeoutObj = setTimeout(function() {
		//这里发送一个心跳，后端收到后，返回一个心跳消息，
		if (websock.readyState == 1) {
			//如果连接正常
			ws.send(JSON.stringify(data)); //这里可以自己跟后端约定
		} else {
			//否则重连
			self.reconnect();
		}
        wsConfig.serverTimeoutObj = setTimeout(function() {
			console.warn("***超时主动关闭***")
            //超时关闭
            ws.close();
        }, wsConfig.timeout);
    }, wsConfig.timeout);
	// wsSendHeartBeat();//开始心跳
}
var util = {
	dateFormat(date, fmt) {
		let ret
		const opt = {
			'y+': date.getFullYear().toString(), // 年
			'M+': (date.getMonth() + 1).toString(), // 月
			'd+': date.getDate().toString(), // 日
			'H+': date.getHours().toString(), // 时
			'm+': date.getMinutes().toString(), // 分
			's+': date.getSeconds().toString(), // 秒
			// 有其他格式化字符需求可以继续添加，必须转化成字符串
		}
		for (let k in opt) {
			ret = new RegExp('(' + k + ')').exec(fmt)
			if (ret) {
				fmt = fmt.replace(
					ret[1],
					ret[1].length == 1 ? opt[k] : opt[k].padStart(ret[1].length, '0')
				)
			}
		}
		return fmt
	},
	formatDate: function(date, fmt) {
		if (/(y+)/.test(fmt)) {
			fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length))
		}
		let o = {
			'M+': date.getMonth() + 1,
			'd+': date.getDate(),
			'h+': date.getHours(),
			'm+': date.getMinutes(),
			's+': date.getSeconds()
		}
		for (let k in o) {
			if (new RegExp(`(${k})`).test(fmt)) {
				let str = o[k] + ''
				fmt = fmt.replace(RegExp.$1, RegExp.$1.length === 1 ? str : this.padLeftZero(str))
			}
		}
		return fmt
	},
	padLeftZero: function(str) {
		return ('00' + str).substr(str.length)
	},
	formatDatetime(val, format) {
		const year = val.getFullYear();
		const month = val.getMonth() + 1;
		const day = val.getDate();
		const hour = val.getHours();
		const minute = val.getMinutes();
		const second = val.getSeconds();
		return year + '-' + (month > 9 ? month : '0' + month) + '-' + day + ' ' + hour + ':' + (minute > 9 ?
			minute : '0' + minute) + ':' + (second > 9 ? second : '0' + second);

	},
	formatDayTime(val) {
		const year = val.getFullYear();
		const month = val.getMonth() + 1;
		const day = val.getDate();
		const hour = val.getHours();
		const minute = val.getMinutes();
		const second = val.getSeconds();
		return year + '-' + (month > 9 ? month : '0' + month) + '-' + day + ' ' + hour + ':' + (minute > 9 ?
			minute : '0' + minute);
	},
	formatTodayTime(val) {
		const year = val.getFullYear();
		const month = val.getMonth() + 1;
		const day = val.getDate();
		const hour = val.getHours();
		const minute = val.getMinutes();

		if (month == new Date().getMonth() + 1 && day + 1 == new Date().getDate()) {
			return '昨天' + hour + ':' + (minute > 9 ? minute : '0' + minute);
		} else if (month == new Date().getMonth() + 1 && day == new Date().getDate()) {

			return hour + ':' + (minute > 9 ? minute : '0' + minute);
		} else {
			return year + '-' + (month > 9 ? month : '0' + month) + '-' + day + ' ' + hour + ':' + (minute > 9 ?
				minute : '0' + minute);
		}
	},

	/**
	 * 计算天数
	 * @param date1
	 * @param date2
	 * @returns {number}
	 * @constructor
	 */
	getNumberOfDays(date1, date2) { //获得天数
		if (!date1 || !date2) {
			return 0;
		}
		//date1：开始日期，date2结束日期
		var a1 = Date.parse(new Date(date1));
		var a2 = Date.parse(new Date(date2));
		var day = parseInt((a2 - a1) / (1000 * 60 * 60 * 24)) + 1; //核心：时间戳相减，然后除以天数
		return day
	},

	getUrlParams(url) {
		url = url == null ? window.location.href : url;
		var search = url.substring(url.lastIndexOf("?") + 1);
		var obj = {};
		var reg = /([^?&=]+)=([^?&=]*)/g;
		// [^?&=]+表示：除了？、&、=之外的一到多个字符
		// [^?&=]*表示：除了？、&、=之外的0到多个字符（任意多个）
		search.replace(reg, function(rs, $1, $2) {
			var name = decodeURIComponent($1);
			var val = decodeURIComponent($2);
			val = String(val);
			obj[name] = val;
			return rs;
		});
		return obj;
	},
	formatTime(date) {
		var year = date.getFullYear()
		var month = date.getMonth() + 1
		var day = date.getDate()
		var hour = date.getHours()
		var minute = date.getMinutes()
		var second = date.getSeconds()
		return [year, month, day].map(this.formatNumber).join('-') + ' ' + [hour, minute, second].map(this
			.formatNumber).join(
			':')
	},
	formatNumber(n) {
		n = n.toString()
		return n[1] ? n : '0' + n
	},
	trackRequest(para, app = null) {
		if ((para.type && para.type.includes('Error'))) {
			//所有报错埋点以及曝光埋点不再发送至服务器
			return
		}
		try {
			
			if(typeof (para.clkParams) == 'object'){
			    let obj = {
			        locusBehaviorName: para.locusBehaviorName ? para.locusBehaviorName : ''
			    }
			    para.clkParams = Object.assign(obj,para.clkParams)
			}
			
			let pvCurPageParams = "";//字符串string对象
			if(para.pvCurPageParams){//调用的时候传递进来的-先转为对象
				pvCurPageParams = typeof para.pvCurPageParams === 'object' ? para.pvCurPageParams : JSON.parse(para.pvCurPageParams)
			}else{
				pvCurPageParams = {};
			}
			let queryObj = getStorage('queryObj') ? JSON.parse(getStorage('queryObj')) : null;
			let urlObj = queryObj || util.getUrlParams(location.href) || {};
			let userInfo = getStorage('userInfo') ? JSON.parse(getStorage('userInfo')) : null;
			let userId = urlObj.leavePhoneCustomerId ? urlObj.leavePhoneCustomerId : (userInfo?userInfo.userId:'');
			let brandId = urlObj.special_ID || $config.brandId || ''
			//在页面参数里面手动添加path参数
			pvCurPageParams.brandId = brandId;
			pvCurPageParams.locusBehaviorName = para.locusBehaviorName  || '';
			pvCurPageParams.locusValue = para.locusValue  || '';
			pvCurPageParams.locusName = para.locusName  || '';
            let _fromParam = {};
            _fromParam["scene"] = urlObj.scene1 || '';
			let data = {
				session: '',
				userAgent: navigator.userAgent.substring(0, 255) || '',
				browserName: navigator.appName || '',
				browserVersion: navigator.appVersion.substring(0, 255) || '',
                fromParam: JSON.stringify(_fromParam), //转发者秘钥
				platform: 'h5', //iframeUrl代表是顾问分享的外链
				fromPlatform: urlObj.fromPlatform || urlObj.fromProduce || 'h5',
				ip: window.ip || '',
				cookieId: from_cookie || getStorage("cookie_id") || '',
				openId: urlObj.openid || (userInfo ? userInfo.openId : ''),
				userId: userId,
				brandUserId: userId,
				createTime: this.formatTime(new Date()),
				uploadTime: this.formatTime(new Date()),
				product: 'h5', //iframeUrl代表是顾问分享的外链
				project: para.project || urlObj.xcxHouseId || urlObj.houseId || '',
				brandId: brandId,
				expand: JSON.stringify(urlObj), //扩展字段
				imTalkId: para.imTalkId || '', //IM对话编号
				imTalkType: para.imTalkType || '', //IM对话类型
				eventName: para.eventName || '', //事件名称
				clkDesPage: para.clkDesPage || '', //点击前往的页面名称
				clkId: para.clkId || '', //点击ID
				clkName: para.clkName || '',
				pvId: para.pvId || '', //PV埋点ID
				clkParams: typeof para.clkParams === 'object' ? JSON.stringify(para.clkParams) : (para.clkParams || ''), //点击参数
				pvCurPageName: para.pvCurPageName || '', //当前页面名称
				pvCurPageParams: typeof pvCurPageParams === 'object' ? JSON.stringify(pvCurPageParams) : (pvCurPageParams ||''), //当前页面参数
				pvLastPageName: para.pvLastPageName || '', //上一页页面名称
				pvLastPageParams: para.pvLastPageParams || '', //上一页页面参数
				pvPageLoadTime: para.pvPageLoadTime || '', //加载时间
				type: para.type || '', //埋点类型
				reserve1: urlObj.channel || '', //来源平台，抖音百度微信
			}
            if(para.behaviorName){
                data.behaviorName = para.behaviorName;
            }
			let timeNow = new Date().getTime();
			let session = getStorage('sessionNumber') ? Number(getStorage('sessionNumber')) : timeNow;
			if (timeNow - sessionTime > 180000 && !urlObj.session) {
				// session++;
				session = timeNow;
				setStorage('sessionNumber', session)
			}
			data.session = urlObj.session || data.userId + "_" + session || '';
			sessionTime = timeNow;
			// return data;
			// app.globalData.session_id = data.session
			// app.globalData.sessionTime = timeNow;
			// requestConfig('upload', data, true);
			// let param = ["SEND" +
			// 	"\nproject:" + "elab-marketing-system" + 
			// 	"\nmethod:" + 'POST' +
			// 	"\npath:" + '/behavior/brandMiniWeb/upload' +
			// 	"\ndestination:" + '/ws/remote/invoke' +
			// 	"\n\n" + JSON.stringify(data) +
			// 	"\u0000"
			// ];
			// app.wsSendOrder(param,data);//socket 消息发送
			console.warn("***mook***", (data.pvId || data.clkId || data.eventId), data)
			// let param = [
			//     "SEND" +
			//     "\nproject:" +
			//     "elab-marketing-system" +
			//     "\nmethod:" +
			//     "POST" +
			//     "\npath:" +
			//     "/behavior/brandMiniWeb/upload" +
			//     "\ndestination:" +
			//     "/ws/remote/invoke" +
			//     "\n\n" +
			//     JSON.stringify(data) +
			//     "\u0000",
			// ];
			// console.log("上报埋点数据", param);
			// websocketsend(JSON.stringify(param));
			websocketsend(data);
		} catch (e) {
			console.warn("***util.js-onError***", e);
		}
	},
	getSession() { //获取session
		let timeNow = new Date().getTime();
		let session = uni.getStorageSync('sessionNumber') || timeNow; //session具体的值
		uni.setStorage({
			key: "sessionNumber",
			data: session
		})
		return session;
	},
	initWebsocket:initWebsocket,
};
window.from_session = util.getUrlParams(location.href).session || '';
window.from_cookie = util.getUrlParams(location.href).cookie || '';
export default util;
// module.exports = util;