/**
 * 全局工具类
 */

/**
 * 进行延时，以达到可以简写代码的目的
 */
export const sleep = (value = 30) => {
	return new Promise((resolve) => {
		setTimeout(() => {
			resolve()
		}, value)
	})
}


// 获取父组件的参数，因为支付宝小程序不支持provide/inject的写法
// this.$parent在非H5中，可以准确获取到父组件，但是在H5中，需要多次this.$parent.$parent.xxx
// 这里默认值等于undefined有它的含义，因为最顶层元素(组件)的$parent就是undefined，意味着不传name
// 值(默认为undefined)，就是查找最顶层的$parent
export const $parent = (name = undefined) => {
	let parent = this.$parent
	// 通过while历遍，这里主要是为了H5需要多层解析的问题
	while (parent) {
		// 父组件
		if (parent.$options && parent.$options.name !== name) {
			// 如果组件的name不相等，继续上一级寻找
			parent = parent.$parent
		} else {
			return parent
		}
	}
	return false
}

// json数据克隆
export const jsonClone = (obj) => {
	// 对常见的“非”值，直接返回原来值
	return JSON.parse(JSON.stringify(obj));
}

// 深度克隆
export const deepClone = (obj) => {
	// 对常见的“非”值，直接返回原来值
	if ([null, undefined, NaN, false].includes(obj)) return obj
	if (typeof obj !== 'object' && typeof obj !== 'function') {
		// 原始类型直接返回
		return obj
	}
	const o = test.array(obj) ? [] : {}
	for (const i in obj) {
		if (obj.hasOwnProperty(i)) {
			o[i] = typeof obj[i] === 'object' ? deepClone(obj[i]) : obj[i]
		}
	}
	return o
}


/**
 * 防抖函数
 */
export const debounce = (fn, context, delay = 500) => {
	let timer
	return function(...args) {
		if (timer) {
			clearTimeout(timer)
		}
		timer = setTimeout(() => {
			fn.apply(context, args)
		}, delay)
	}
}

/**
 * 节流函数
 */
export const throttle = (fn, context, wait = 500) => {
	let flag = true;
	return function(...args) {
		if (flag) {
			flag = false;
			fn.apply(context, args); //立即执行
			setTimeout(() => {
				flag = true
			}, wait)
		}
	}
}


/**
 * 根据属性数组创建一个新对象
 * @param {Object} obj 对象数据
 * @param { Array} keys 需要提取的字段集合    
 */
export const createMap = (obj, keys) => {
	return keys.reduce((result, key) => {
		if (obj.hasOwnProperty(key)) {
			result[key] = obj[key];
		}
		return result;
	}, {});
}



/**
 * @description 格式化时间
 * @param {String|Number} dateTime 需要格式化的时间戳
 * @param {String} fmt 格式化规则 yyyy:mm:dd|yyyy:mm|yyyy年mm月dd日|yyyy年mm月dd日 hh时MM分等 ss 秒,可自定义组合 默认yyyy-mm-dd
 * @returns {string} 返回格式化后的字符串
 */
export function timeFormat(dateTime = null, formatStr = 'yyyy-mm-dd hh:MM:ss') {
	let date
	// 若传入时间为假值，则取当前时间
	if (!dateTime) {
		date = new Date()
	}
	// 若为unix秒时间戳，则转为毫秒时间戳（逻辑有点奇怪，但不敢改，以保证历史兼容）
	else if (/^\d{10}$/.test(dateTime?.toString().trim())) {
		date = new Date(dateTime * 1000)
	}
	// 若用户传入字符串格式时间戳，new Date无法解析，需做兼容
	else if (typeof dateTime === 'string' && /^\d+$/.test(dateTime.trim())) {
		date = new Date(Number(dateTime))
	}
	// 其他都认为符合 RFC 2822 规范
	else {
		// 处理平台性差异，在Safari/Webkit中，new Date仅支持/作为分割符的字符串时间
		date = new Date(
			typeof dateTime === 'string' ?
			dateTime.replace(/-/g, '/') :
			dateTime
		)
	}

	const timeSource = {
		'y': date.getFullYear().toString(), // 年
		'm': (date.getMonth() + 1).toString().padStart(2, '0'), // 月
		'd': date.getDate().toString().padStart(2, '0'), // 日
		'h': date.getHours().toString().padStart(2, '0'), // 时
		'M': date.getMinutes().toString().padStart(2, '0'), // 分
		's': date.getSeconds().toString().padStart(2, '0') // 秒
		// 有其他格式化字符需求可以继续添加，必须转化成字符串
	}

	for (const key in timeSource) {
		const [ret] = new RegExp(`${key}+`).exec(formatStr) || []
		if (ret) {
			// 年可能只需展示两位
			const beginIndex = key === 'y' && ret.length === 2 ? 2 : 0
			formatStr = formatStr.replace(ret, timeSource[key].slice(beginIndex))
		}
	}

	return formatStr
}

// 日期字符串转秒级时间戳
export function dateToUnix(dateText) {
	let times = new Date(dateText);
	return times.getTime() / 1000;
}
/**
 * 获取一天的时间戳
 * @param {String} type 
 */
export function timeFrame(type = 'start') {
	let date = new Date();
	date = date.setDate(date.getDate() - 1);
	let startTime = Date.parse(new Date(date));
	let endTime = Date.parse(timeFormat());
	return type == 'start' ? startTime / 1000 : endTime / 1000
}
/**
 * 获取一天的展示时间
 * @param {String} type 
 */
export function timeFrameText(type = 'start') {
	let date = new Date();
	date = date.setDate(date.getDate() - 1);
	return type == 'start' ? timeFormat(new Date(date), 'yyyy-mm-dd') : timeFormat(new Date(), 'yyyy-mm-dd')
}
