import { ComponentInternalInstance } from 'vue'
interface Data {
	[key: string]: any;
}
/**
 * 预览图片。
 @param {Object} url 必填 当前预览的图片链接。
 @param {Object} list 可以是url数组，也可以是对象，数据比如：["http:url"] or [{url:"https:url",...}]
 @param {Object} rangKey 如果list是对象数组，需要提供url字段。
 */
import { preview } from "./preview.js"
export default preview;
/**
 * 检测是否是数字
 * @param arg 待检测的字符
 * @param defaultNum 0,如果不符合值时设置默认值
 * @returns number类型数值
 */
export function isNumber(arg: string | number | undefined | null, defaultNum = 0): number {
	const p = Number(arg);
	return p || defaultNum;
}
/**
 * 检测是否是字符串
 * @param arg 待检测的字符
 * @param defaultNum 默认"",如果不符合值是设置默认值
 * @returns 字符串
 */
export function isString(arg: string | number | undefined | null, defaultStr = ""): string {
	let p = "";
	if (typeof arg === "string" && arg != null) {
		p = String(arg);
	} else p = defaultStr;
	return p;
}
/**
 * 把一个数字进行分页返回数字数组
 * @param total 总数
 * @param pageSize 分页大小
 * @returns 数字数组
 */
export function paginate(total: number, pageSize: number): number[] {
	const pages = Math.ceil(total / pageSize);
	const pageArr: number[] = [];
	for (let i = 0; i < pages; i++) {
		pageArr.push(i + 1);
	}
	return pageArr;
}


/**
   * 取对象数据值（可深层次取值）
   * @example getValue(data,"a.b.c")
   * @param data 对象数据
   * @param keys 键值
   * @returns 返回值
   * @description 注意不会去改变原来的数据
   */
export function getValue(data: Data, keys: string): any {
	const keyArr = keys.split(".");
	let result = { ...data };

	for (const key of keyArr) {
		result = result[key];
		if (result === undefined || result === null) {
			return result;
		}
	}

	return result;
}

/**
 * 设置对象键值（可深层次设置值）
 * @example setValue(data,"a.b.c","haha")
 * @param data 对象数据
 * @param keys 键值
 * @returns 修改后的对象数据。
 * @description 改变原来的数据
 */
export function setValue(data: Data, keys: string, value: any): void {
	const keyArr = keys.split(".");
	let obj = data;
	for (let i = 0; i < keyArr.length - 1; i++) {
		const key = keyArr[i];
		if (!(key in obj)) {
			obj[key] = {};
		}
		obj = obj[key];
	}
	obj[keyArr[keyArr.length - 1]] = value;
}
/**
 * 计算并返回一个对象中最大的层级数
 * @param data 待检测对象数据
 * @returns 最大层级数
 */
export function getMaxDepth(data: Data): number {
	let maxDepth = 0;

	function traverse(obj: any, depth: number): void {
		if (typeof obj !== "object" || obj === null) {
			maxDepth = Math.max(maxDepth, depth);
			return;
		}
		for (const key in obj) {
			// deno-lint-ignore no-prototype-builtins
			if (obj.hasOwnProperty(key)) {
				traverse(obj[key], depth + 1);
			}
		}
	}

	traverse(data, 0);

	return maxDepth;
}

/**
 * 深度合并对象
 * @param FirstOBJ 需要合并的对象
 * @param SecondOBJ 被合并的对象
 * @returns 返回合并后的对象 
 */
export function deepObjectMerge(FirstOBJ : Data, SecondOBJ : Data) : Data { // 深度合并对象
	for (var key in SecondOBJ) {
		FirstOBJ[key] = FirstOBJ[key] && FirstOBJ[key]?.toString() === "[object Object]" ?
			deepObjectMerge(FirstOBJ[key], SecondOBJ[key]) : FirstOBJ[key] = SecondOBJ[key];
	}
	return FirstOBJ;
}

/**
* 数据分组
* @param {Array} oArr - 原数组列表
* @param {Number} length - 单个数组长度
* @return {Array}  arr - 分组后的新数组
*/
export function splitData<T>(arr: Array<T> = [], size = 1): Array<T[]> {
	const result = [];
	for (let i = 0; i < arr.length; i += size) {
		result.push(arr.slice(i, i + size));
	}
	return result as T[][];
}


/**
 * 深度克隆
 * @param {T} data 待大克隆复制的数据
 * @return {T} any
 */
export function deepClone<T>(data: T): T {
	// 对常见的“非”值，直接返回原来值
	if (data === null || typeof data !== "object") {
		return data;
	}
	if (Array.isArray(data)) {
		const clone: any[] = [];
		for (const item of data) {
			clone.push(deepClone(item));
		}
		return clone as any;
	}
	if (data instanceof Date) {
		return new Date(data.getTime()) as unknown as T;
	}
	if (data instanceof RegExp) {
		const flags = data.flags;
		return new RegExp(data.source, flags) as unknown as T;
	}
	if (typeof data === "function") {
		return data as unknown as T;
	}
	const clone = {} as T;
	for (const key in data) {
		if (Object.prototype.hasOwnProperty.call(data, key)) {
			clone[key] = deepClone(data[key]);
		}
	}
	return clone;
}


/**
* 剩余时间格式化
* @param {Number} t - 剩余多少秒
* @return {Object}  format - 格式后的天时分秒对象
*/
export function timeMuch(t: number) {
	let format: any = {
		d: '00',
		h: '00',
		m: '00',
		s: '00'
	};
	if (t > 0) {
		let d = Math.floor(t / 86400);
		let h = Math.floor((t / 3600) % 24);
		let m = Math.floor((t / 60) % 60);
		let s = Math.floor(t % 60);
		format.d = d < 10 ? '0' + d : d;
		format.h = h < 10 ? '0' + h : h;
		format.m = m < 10 ? '0' + m : m;
		format.s = s < 10 ? '0' + s : s;
	}
	return format;
}
//获取时间距离当前时间
export function getDateToNewData(timestamp: number | string | Date = new Date().getTime()) {
	if (typeof timestamp == 'string') {
		timestamp = new Date(timestamp).getTime();
	}

	// 补全为13位
	var arrTimestamp: Array<string> = (timestamp + '').split('');
	for (var start = 0; start < 13; start++) {
		if (!arrTimestamp[start]) {
			arrTimestamp[start] = '0';
		}
	}
	timestamp = Number(arrTimestamp.join('')) * 1;

	var minute = 1000 * 60;
	var hour = minute * 60;
	var day = hour * 24;
	var halfamonth = day * 15;
	var month = day * 30;
	var now = new Date().getTime();
	var diffValue = now - timestamp;

	// 如果本地时间反而小于变量时间
	if (diffValue < 0) {
		return '不久前';
	}
	// 计算差异时间的量级
	var monthC = diffValue / month;
	var weekC = diffValue / (7 * day);
	var dayC = diffValue / day;
	var hourC = diffValue / hour;
	var minC = diffValue / minute;

	// 数值补0方法
	var zero = function (value: number) {
		if (value < 10) {
			return '0' + value;
		}
		return value;
	};

	// 使用
	if (monthC > 12) {
		// 超过1年，直接显示年月日
		return (function () {
			var date = new Date(timestamp);
			return date.getFullYear() + '年' + zero(date.getMonth() + 1) + '月' + zero(date.getDate()) + '日';
		})();
	} else if (monthC >= 1) {
		return parseInt(monthC + '') + "月前";
	} else if (weekC >= 1) {
		return parseInt(weekC + '') + "周前";
	} else if (dayC >= 1) {
		return parseInt(dayC + '') + "天前";
	} else if (hourC >= 1) {
		return parseInt(hourC + '') + "小时前";
	} else if (minC >= 1) {
		return parseInt(minC + '') + "分钟前";
	}
	return '刚刚';
}

/**
* 打电话
* @param {String<Number>} phoneNumber - 数字字符串
* @return {Promise}
*/
export function callPhone(phoneNumber = '') {
	let num = phoneNumber.toString()
	return new Promise((rs, rj) => {
		uni.makePhoneCall({
			phoneNumber: num,
			success: () => rs(true),
			fail: (err) => rj(err)
		});
	})
}

/**
 * 调起客户端相机扫码。
 * @param {Boolean} onlyFromCamera true 是否只允许相机扫码识别
 * @param {Array<string>} scanType ['barCode', 'qrCode', 'datamatrix','datamatrix']
 * @returns Promise 成功返回相关数据结构
 */
export function scanCode(onlyFromCamera = true, scanType = ['barCode', 'qrCode', 'datamatrix', 'datamatrix']): Promise<string | UniApp.ScanCodeSuccessRes> {
	return new Promise((rs, rj) => {
		// #ifdef H5
		rj('不支持H5');
		// #endif
		// #ifndef H5
		uni.scanCode({
			onlyFromCamera: onlyFromCamera,
			scanType: scanType,
			success: (res) => rs(res),
			fail: (error) => rj(error)
		});
		// #endif
	})
}

/**
 * 设置剪切板内容。
 * @param {String} data 
 * @returns Promise true/false
 */
export function setClipboardData(data: string): Promise<string | boolean> {
	return new Promise((rs, rj) => {
		// #ifndef H5
		uni.setClipboardData({
			data: data,
			success: () => rs(true),
			fail: (error) => rj(error)
		});
		// #endif
		// #ifdef H5
		if (navigator.clipboard && window.isSecureContext) {
			navigator.clipboard.writeText(data).then(() => rs(true)).catch((error => rs(error)))
		} else {
			const textArea = document.createElement('textarea')
			textArea.style.opacity = "0"
			textArea.style.position = "fixed"
			textArea.style.top = "0px"
			textArea.value = data
			document.body.appendChild(textArea)
			textArea.focus()
			textArea.select()
			document.execCommand('copy') ? rs(true) : rj("错误")
			textArea.remove()
		}
		// #endif
	})
}
/**
 * 获取剪切板内容
 * @returns Promise 剪切板内容
 */
export function getClipboardData(): Promise<boolean | string> {

	return new Promise((rs, rj) => {
		// #ifndef H5
		uni.getClipboardData({
			success: (res) => rs(res.data),
			fail: (error) => rj(error)
		});
		// #endif
		// #ifdef H5
		console.error('H5无法获取剪切板内容')
		rj('H5无法获取剪切板内容')
		// #endif
	})

}

/**
 * 设置cookie数据
 * @param {String} key 键值
 * @param {String} data 值
 * @returns Boolean
 */
export function setCookie(key: string, data: any) {
	try {
		uni.setStorageSync(key, data);
		return true;
	} catch (e) {
		return false;
	}
}
/**
 * 删除一个本地cookie
 * @param {String} key 键值
 * @returns Boolean
 */
export function delCookie(key: string) {
	try {
		uni.removeStorageSync(key);
		return true;
	} catch (e) {
		return false;
	}
}

/**
 * 获取一个cookie数据
 * 如果存入的是对象，返回的也是对象。如果是string返回的也是字符串。
 * @param {String} key 键
 * @returns json/string
 */
export function getCookie(key: string) {
	try {
		const value = uni.getStorageSync(key);
		try {
			let val = JSON.parse(value)
			return val;
		} catch (e) {
			return value;
		}
	} catch (e) {
		return undefined;
	}
}


/**
 * 向地址连接追加参数。
 * @param {string} uri 网址
 * @param {string} key 字段
 * @param {string} value 字段值
 * @returns 
 */
export function httpUrlAddKey(uri: string, key: string, value: string) {
	if (!value) {
		return uri;
	}
	var re = new RegExp("([?&])" + key + "=.*?(&|$)", "i");
	var separator = uri.indexOf("?") !== -1 ? "&" : "?";
	if (uri.match(re)) {
		return uri.replace(re, "$1" + key + "=" + value + "$2");
	} else {
		return uri + separator + key + "=" + value;
	}
}
/**
 * 取url参数
 * @param {string} uri 网址
 * @param {string} key 字段
 * @returns string
 */
export function getQueryString(url: string, key: string): string {
	var query_string = url.substring(url.indexOf("?"));
	if (!query_string) return "";
	var re = /[?&]?([^=]+)=([^&]*)/g;
	var tokens: any;
	while (tokens = re.exec(query_string)) {
		if (decodeURIComponent(tokens[1]) === key) {
			return decodeURIComponent(tokens[2]);
			break;
		}
	}
	return "";
}

/**
 * 
 * @param rdix 随机因子
 * @param length 取的长度
 * @param isAddStr 是否限制随机结果中的长度,不允许输出长度
 * @returns String
 */
export function getUid(rdix = 1, length = 12, isAddStr = false) {
	return Math.floor(Math.random() * rdix * Math.floor(Math.random() * Date.now())).toString(isAddStr ? 16 : 10).substring(0, length);
}

/*
防抖
防抖原理：在一定时间内，只有最后一次操作，再过wait毫秒后才执行函数
	@param {Function} func 要执行的回调函数
	@param {Number} wait 延迟的时间
	@param{Boolean} immediate 是否要立即执行
*/
var timeout: any = getUid(1)
export function debounce(func: Function, wait = 500, immediate = false) {
	// 清除定时器
	if (timeout !== null) clearTimeout(timeout);
	// 立即执行，此类情况一般用不到
	if (immediate) {
		timeout = setTimeout(() => {
			timeout = null;
		}, wait);
		typeof func === "function" && func();
	} else {
		// 设置定时器，当最后一次操作后，timeout不会再被清除，所以在延时wait毫秒后执行func回调方法
		timeout = getUid(1);
		timeout = setTimeout(() => {
			typeof func === "function" && func();
		}, wait);
	}
}

/**
 * 节流
	节流原理：在一定时间内，只能触发一次
 * @param {Function} func 要执行的回调函数 
 * @param {Number} wait 延时的时间
 * @param {Boolean} immediate 是否立即执行
 * @return null
 */
var timesr: any = NaN, throttleFlag: boolean;
export function throttle(func: Function, wait = 500, immediate = true) {
	if (immediate) {
		if (!throttleFlag) {
			throttleFlag = true;
			// 如果是立即执行，则在wait毫秒内开始时执行
			typeof func === 'function' && func();
			timesr = setTimeout(() => {
				throttleFlag = false;
			}, wait);
		}
	} else {
		if (!throttleFlag) {
			throttleFlag = true
			// 如果是非立即执行，则在wait毫秒内的结束处执行
			timesr = setTimeout(() => {
				throttleFlag = false
				typeof func === 'function' && func();
			}, wait);
		}

	}
};



/**等同：queryDom */
export function quereyDom(t: ComponentInternalInstance, node: string): Promise<UniApp.NodeInfo | UniApp.NodeInfo[]> {

	return new Promise((res, rej) => {
		// #ifdef APP-NVUE
		const dom: any = uni.requireNativePlugin('dom')
		setTimeout(function () {
			node = node.replace(/^[#\.]/g, '')
			dom.getComponentRect(t.refs[node], function (el: any) {
				res(el?.size);
			})
		}, 60)
		// #endif
		// #ifndef APP-NVUE
		const query = uni.createSelectorQuery().in(t);
		query.select(node).boundingClientRect(el => {
			res(el);
		}).exec();
		// #endif
	})
}
/**
 * 查询文档节点信息
 * @param t Vue上下文对象
 * @param node 提供带#的id比如：'#id',在nvue中应该是元素上写明ref='id'
 * @returns vue页面返回查询的节点信息，nvue返回weex的节点信息。
 */
export const queryDom = quereyDom

/**
 * 是否是手机号码
 * @param phone 号码
 * @returns Boolean
 */
export function isPhone(phone: string | number) {
	let val = String(phone);
	let reg = /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/
	return !!val.match(reg);
}

/**
 * 是否含有中文
 * @param s 字符串
 * @returns Boolean
 */
export function isChina(s: string) {
	var patrn = /[\u4E00-\u9FA5]|[\uFE30-\uFFA0]/gi;
	return !!patrn.exec(s);
}

/**
 * 是否为空
 * @description 判断是否是null,对象是否为空，数组是否为空。是否为 undefaind，是否为 “”空字符串。
 * @param s 任意
 */
export function isEmpty(s: any) {
	if (typeof s === 'string') {
		s = s.trim();
	}
	if (s == "") return true
	if (s == null) return true;
	if (typeof s === 'undefined') return true;
	if (Array.isArray(s)) {
		if (s.length == 0) return true;
	}
	if (typeof s === 'object') {
		if (Object.keys(s).length == 0) return true;
	}
	return false;
}
/**
 * 是否邮箱
 * @param s 字符串
 * @returns Boolean
 */
export function isEmail(s: string) {
	let reg = /^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/;
	return !!s.match(reg);
}
/**
 * 是否身份证号
 * @param val 字符号或者数字
 * @returns Boolean
 * @author https://cloud.tencent.com/developer/article/1114323
 */
export function isIdCard(val: string | number) {
	val = String(val)
	var p = /^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/;
	var factor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
	var parity = [1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2];
	var code = val.substring(17);
	if (p.test(val)) {
		var sum: number = 0;
		for (var i = 0; i < 17; i++) {
			let id: number | string | any = val[i]
			sum += id * factor[i];
		}
		if (parity[sum % 11] == code.toUpperCase()) {
			return true;
		}
	}
	return false;
}
/**
 * 是否车牌
 * @description 蓝牌5位，绿牌6位。
 * @param s 字符串
 * @returns Boolean
 */
export function isIdCar(s: string) {
	let reg = /^[京|沪|津|渝|鲁|冀|晋|蒙|辽|吉|黑|苏|浙|皖|闽|赣|豫|湘|鄂|粤|桂|琼|川|贵|云|藏|陕|甘|青|宁|新|港|澳|台|新|使]{1}[A-Z]{1}[A-Z_0-9]{5,6}$/
	return !!s.match(reg);
}

/**
 * 纯数字密码验证
 * @param s 字符串或者数字
 * @param len 最小长度，默认6
 * @param maxLen 最大长度，默认20
 * @returns Boolean
 */
export function isPasswordOfNumber(s: number | string, len = 6, maxLen = 20) {
	s = String(s);
	let reg = new RegExp(`^[0-9]{${len},${maxLen}}$`)
	return !!s.match(reg)
}

/**
 * 密码验证
 * @param s 字符串或者数字
 * @param len 最小长度，默认6
 * @param maxLen 最大长度，默认20
 * @param model 0数字和英文，1数字，英文必须包含，不允许有特殊字符，2数字和字母必须包含，可以有特殊字符。
 * @returns Boolean
 */
export function isPasswordOfOther(s: string | number, len = 6, maxLen = 20, model = 0) {
	s = String(s);
	//密码至少包含 数字和英文，长度6-20
	let reg = /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,20}$/
	//密码包含 数字,英文,字符中的两种以上，长度6-20
	if (model === 1) {
		reg = /^(?![0-9]+$)(?![a-z]+$)(?![A-Z]+$)(?!([^(0-9a-zA-Z)])+$).{6,20}$/
	}

	//至少包含数字跟字母，可以有字符
	if (model === 2) {
		reg = /(?=.*([a-zA-Z].*))(?=.*[0-9].*)[a-zA-Z0-9-*/+.~!@#$%^&*()]{6,20}$/
	}

	return !!s.match(reg)
}

/**
 * 是否是一个有效的日期
 * @param s 字符串，数字，日期对象
 * @returns Boolean
 */
export function isDate(s: string | number | Date) {
	if (s == null || typeof s === 'undefined' || !s) return false;
	if (typeof s === 'string') {
		//兼容ios,mac
		s = s.replace('-', '/');
	}
	let d = new Date(s);
	if (d.toString() == 'Invalid Date') return false;
	return true;
}
/**
 * 显示信息
 * @param word 标题
 * @param mask 不允许穿透
 * @param icon 图标
 */
export function toast(word: string, mask: boolean = true, icon: any = 'none') {
	// #ifndef MP-ALIPAY
	uni.showToast({
		mask: mask,
		title: word,
		icon: icon
	})
	// #endif
	// #ifdef MP-ALIPAY
	uni.showToast({
		title: word,
		icon: icon
	})
	// #endif
}
/**
 * 获取屏幕窗口安全高度和宽度
 * 注意是针对种屏幕的统一计算，统一高度，不再让uni获取有效高度而烦恼。
 * 请一定要在onMounted或者onLoad中调用，否则不准确在h5端。
 * @return {height,width,top,isCustomHeader,statusBarHeight,sysinfo}
 */
export function getWindow(): { width: number, height: number, top: number, bottom: number, statusBarHeight: number, isCustomHeader: Boolean, sysinfo: UniApp.GetSystemInfoResult } {
	// let getsysinfoSync = getCookie("tmui_sysinfo")
	// if(getsysinfoSync){
	// 	return getsysinfoSync
	// }
	const sysinfo = uni.getSystemInfoSync();
	let top = 0;
	let height = sysinfo.windowHeight;
	let nowPage = getCurrentPages().pop()
	let isCustomHeader = false;
	let pages = uni.$tm?.pages ?? []
	let bottom = sysinfo.safeAreaInsets?.bottom ?? 0;
	if (uni.$tm?.globalNavStyle == 'custom') {
		isCustomHeader = true;
	} else {
		for (let i = 0; i < uni.$tm.pages.length; i++) {
			if (nowPage?.route == uni.$tm.pages[i].path && uni.$tm.pages[i].custom == 'custom') {
				isCustomHeader = true;
				break;
			}
		}
	}

	// #ifdef H5
	// 兼容说明：h5端第一次获取的高度和第二次获取的高度是有差异 的。
	if (isCustomHeader) {
		height = sysinfo.windowHeight + sysinfo.windowTop

	} else {
		top = 44
		if (sysinfo.windowTop > 0) {
			height = sysinfo.windowHeight;
		} else {
			height = sysinfo.windowHeight + sysinfo.windowTop
		}
	}

	// #endif

	let results = { bottom: bottom, height: height, width: sysinfo.windowWidth, top: top, isCustomHeader: isCustomHeader, statusBarHeight: sysinfo.statusBarHeight || 0, sysinfo: sysinfo };

	return results;
}
type openUrlType = "navigate" | "redirect" | "reLaunch" | "switchTab" | "navigateBack"
/**
 * 
 * @param url string 打开的页面路径
 * @param type openUrlType "navigate"|"redirect"|"reLaunch"|"switchTab"|"navigateBack"
 */
export function routerTo(url: string, type: openUrlType = 'navigate') {
	type openUrlTypeFun = "navigateTo" | "redirectTo" | "reLaunch" | "switchTab" | "navigateBack"
	let funType = {
		navigate: "navigateTo",
		redirect: "redirectTo",
		switchTab: "switchTab",
		reLaunch: "reLaunch",
		navigateBack: "navigateBack",
	}
	let fun = funType[type];
	if (fun == 'navigateBack') {
		uni.navigateBack({
			fail(error) {
				console.error(error)
			}
		})
	} else if (fun == 'reLaunch') {
		uni.reLaunch({
			url: url,
			fail(error) {
				console.error(error)
			}
		})
	} else if (fun == 'switchTab') {
		uni.switchTab({
			url: url,
			fail(error) {
				console.error(error)
			}
		})
	} else if (fun == 'redirectTo') {
		uni.redirectTo({
			url: url,
			fail(error) {
				console.error(error)
			}
		})
	} else if (fun == 'navigateTo') {
		uni.navigateTo({
			url: url,
			fail(error) {
				console.error(error)
			}
		})
	}

}

/**
 * 将rpx转换为px
 * @param v 待转换的数字
 * @param screenWidth 屏幕的宽度，如果不提供默认自动获取
 * @return number
 */
export function torpx(v: number, screenWidth: number = 0) {
	if (typeof screenWidth === 'undefined' || !screenWidth) {
		screenWidth = uni.getSystemInfoSync().screenWidth;
	}
	let pixelRatio = 750 / screenWidth;
	return Math.ceil(v * pixelRatio)
}
/**
 * 将rpx转换为px
 * @param v 待转换的数字
 * @return number
 */
export function topx(v: number) {
	return Math.ceil(uni.upx2px(Number(v)))
}
var lastTime = 0;
/**
 * 在下一次前执行回调函数
 * @param callback 回调函数
 * @returns 一个id值，取消时cancelAnimationFrame(id)来取消
 */
export function requestAnimationFrame(callback: Function): number {
	const currentTime = new Date().getTime();
	const timeToCall = Math.max(0, 16 - (currentTime - lastTime));
	const id = <any>setTimeout(() => {
		callback(currentTime + timeToCall);
	}, timeToCall);
	lastTime = currentTime + timeToCall;
	return id;
}
/**
 * 取消回调执行
 * @param id requestAnimationFrame产生的id
 */
export function cancelAnimationFrame(id: number): void {
	clearTimeout(id)
}
/**
 * 给定一个值，来填充边距所需要的数组值
 * @param val any
 * @returns [左，上，右，下]
 */
export function valToMarginAr(val:any):number[]{

	let ar:number[] = [];
	if(typeof val==='string'&&val){
		ar = [Number(val)]
	}else if(typeof val=== 'number'&&isNaN(Number(val))){
		ar = [val]
	}else if(typeof val ==='undefined'||typeof val === null || val==="" || val === undefined){
		val = [0]
	}else if(Array.isArray(val)){
		ar = val.map(el=>Number(el))
	};
	
	if(ar.length==1){
		ar = new Array(4).fill(ar[0])
	}else if(ar.length==2){
		ar = [...ar,...ar]
		
	}else if(ar.length==3){
		ar = [...ar,0]
	}

	return ar;
}
/**
 * 给定一个值，来填充边距所需要的数组值
 * @param val any
 * @returns [左，上，右，下]
 */
export function valToRoundStrClass(val:number|number[]){
	let dstr = ""
	if(typeof val == 'number') return 'round-'+val
	if (val.length == 1) return 'round-'+val
	if (val.length == 2) return `round-tl-${val[0]} round-tr-${val[1]}`
	if (val.length == 3) return `round-tl-${val[0]} round-tr-${val[1]} round-br-${val[2]} `
	if (val.length == 4) return `round-tl-${val[0]} round-tr-${val[1]} round-br-${val[2]}  round-bl-${val[2]}`

	return dstr
	
}