import md5 from 'js-md5';
import {
	fileUrl
} from '@/config.js';
/**
 * 格式化日期格式 (用于兼容ios Date对象)
 */
export const formatDate = (time) => {
	// 将xxxx-xx-xx的时间格式，转换为 xxxx/xx/xx的格式 
	return time.replace(/\-/g, "/");
}

/**
 * 对象转URL参数
 * @param {object} obj
 * @return {string}
 */
export const urlEncode = (obj = {}) => {
	const result = []
	for (const key in obj) {
		const item = obj[key]
		if (!item) {
			continue
		}
		if (isArray(item)) {
			item.forEach(val => {
				result.push(key + '=' + val)
			})
		} else {
			result.push(key + '=' + item)
		}
	}
	return result.join('&')
}

/**
 * URL参数转对象
 * @param {string} queryStr
 * @return {object}
 */
export const urlDecode = (queryStr = '') => {
	var newObj = new Object()
	if (queryStr) {
		var strs = queryStr.split("&")
		for (var i = 0; i < strs.length; i++) {
			newObj[strs[i].split("=")[0]] = (strs[i].split("=")[1]) || ''
		}
	}
	return newObj
}

/**
 * 遍历对象
 */
export const objForEach = (obj, callback) => {
	Object.keys(obj).forEach((key) => {
		callback(obj[key], key)
	})
}

/**
 * 是否在数组内
 */
export const inArray = (search, array) => {
	for (var i in array) {
		if (array[i] == search) return true
	}
	return false
}

/**
 * 对Date的扩展，将 Date 转化为指定格式的String
 * 月(Y)、月(m)、日(d)、小时(H)、分(M)、秒(S) 可以用 1-2 个占位符，
 * 例子：
 * dateFormat('YYYY-mm-dd HH:MM:SS', new Date()) ==> 2020-01-01 08:00:00
 */
export const dateFormat = (fmt, date) => {
	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() // 秒
		// 有其他格式化字符需求可以继续添加，必须转化成字符串
	};
	let ret
	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
}

/**
 * 判断是否为空对象
 * @param {*} object 源对象
 */
export const isEmptyObject = (object) => {
	return Object.keys(object).length === 0
}

/**
 * 判断是否为对象
 * @param {*} object
 */
export const isObject = (object) => {
	return Object.prototype.toString.call(object) === '[object Object]'
}

/**
 * 判断是否为数组
 * @param {*} array
 */
export const isArray = (array) => {
	return Object.prototype.toString.call(array) === '[object Array]'
}

/**
 * 判断是否为空
 * @param {*} object 源对象
 */
export const isEmpty = (value) => {
	if (isArray(value)) {
		return value.length === 0
	}
	if (isObject(value)) {
		return isEmptyObject(value)
	}
	return !value
}

/**
 * 对象深拷贝
 * @param {*} obj 源对象
 */
export const cloneObj = (obj) => {
	let newObj = isArray(obj) ? [] : {};
	if (typeof obj !== 'object') {
		return;
	}
	for (let i in obj) {
		newObj[i] = typeof obj[i] === 'object' ? cloneObj(obj[i]) : obj[i];
	}
	return newObj
}

// 节流函数
// 思路： 第一次先设定一个变量true，
// 第二次执行这个函数时，会判断变量是否true，
// 是则返回。当第一次的定时器执行完函数最后会设定变量为flase。
// 那么下次判断变量时则为flase，函数会依次运行。
export function throttle(fn, delay = 100) {
	// 首先设定一个变量，在没有执行我们的定时器时为null
	var timer = null
	return function() {
		// 当我们发现这个定时器存在时，则表示定时器已经在运行中，需要返回
		if (timer) return
		timer = setTimeout(() => {
			fn.apply(this, arguments)
			timer = null
		}, delay)
	}
}

// 防抖函数
// 首次运行时把定时器赋值给一个变量， 第二次执行时，
// 如果间隔没超过定时器设定的时间则会清除掉定时器，
// 重新设定定时器， 依次反复， 当我们停止下来时，
// 没有执行清除定时器， 超过一定时间后触发回调函数。
// 参考文档：https://segmentfault.com/q/1010000021145192
export function debounce(fn, delay = 100) {
	let timer
	return function() {
		const that = this
		const _args = arguments // 存一下传入的参数
		if (timer) {
			clearTimeout(timer)
		}
		timer = setTimeout(function() {
			fn.apply(that, _args)
		}, delay)
	}
}

/**
 * 数组交集
 * @param {Array} 数组1
 * @param {Array} 数组2
 * @return {Array}
 */
export const arrayIntersect = (array1, array2) => {
	return array1.filter(val => array2.indexOf(val) > -1)
}

/**
 * 获取当前客户端的rpx比值
 * @return {Number}
 */
export const rpx = () => {
	const {
		windowWidth
	} = uni.getSystemInfoSync()
	// #ifdef H5
	// 与pages.json文件中的 rpxCalcMaxDeviceWidth参数对应, 请勿修改
	const rpxCalcMaxDeviceWidth = 750
	// 与pages.json文件中的 rpxCalcBaseDeviceWidth参数对应, 请勿修改
	const rpxCalcBaseDeviceWidth = 560
	const calcWindowWidth = windowWidth > rpxCalcMaxDeviceWidth ? rpxCalcBaseDeviceWidth : windowWidth
	return calcWindowWidth / 750
	// #endif
	// #ifndef H5
	return windowWidth / 750
	// #endif
}

/**
 * 获取当前客户端的rpx比值
 * @return {Number}
 */
export const rpx2px = (num) => {
	return num * rpx()
}

// 生成订单编号
export function createOrderNo() {
	const data = new Date();
	return `${data.getFullYear()}${data.getMonth()}${data.getDate()}${data.getHours()}${data.getMilliseconds()}${uni.$u.random(800, 12000)}`;
}


// 封装签名
export function getSign(form, appSecret) {
	if (form == null) {
		return false;
	}
	let sign = '';
	form.timestamp = new Date().getTime();
	// form.version = 'v3';
	const arr = objKeySort(form);
	Object.keys(arr).forEach((k) => {
		if (form[k] != null && form[k] != '') {
			sign = sign.concat(form[k]).concat('-');
		}
	});
	sign = sign.concat(appSecret);
	console.log("md5加密前的字符串: ", sign);
	return md5(sign);
}

// 参数按照字母顺序排序
export const objKeySort = (obj) => {
	//排序的函数
	const newkey = Object.keys(obj).sort();
	//先用Object内置类的keys方法获取要排序对象的属性名，再利用Array原型上的sort方法对获取的属性名进行排序，newkey是一个数组
	const newObj = {}; //创建一个新的对象，用于存放排好序的键值对
	for (let i = 0; i < newkey.length; i++) {
		//遍历newkey数组
		newObj[newkey[i]] = obj[newkey[i]]; //向新创建的对象中按照排好的顺序依次增加键值对
	}
	return newObj; //返回排好序的新对象
};

export const getWeek = (text) => {
	const week = [
		'星期日',
		'星期一',
		'星期二',
		'星期三',
		'星期四',
		'星期五',
		'星期六'
	];
	return week[text];
};

/**
 * 获取输入内容的长度
 * @param value
 * @return 内容的长度
 */
export const getInputSize = (value) => {
	if (!value) {
		return 0
	}
	const charCount = value.split('').reduce((prev, curr) => {
		// 英文字母和数字等算一个字符；这个暂时还不完善；
		if (/[a-z]|[0-9]|[,;.!@#-+/\\$%^*()<>?:"'{}~]/i.test(curr)) {
			return prev + 1
		}
		// 其他的算是2个字符
		return prev + 2
	}, 0)

	// 向上取整，防止出现半个字的情况
	const count = Math.ceil(charCount / 2)
	// 省略超出部分，显示’… 详情>>’
	if (count < 25) {
		return value
	}
	return value

	// return Math.ceil(charCount / 2)
}

/* 获取缩列图地址 */
export const thumbnail = (url) => {
	if (url.indexOf('/thumbnail/') < 0) {
		return url.replace(fileUrl, fileUrl + '/thumbnail');
	}
	return url;
}

/* 获取预览图地址 */
export const thumb = (url) => {
	if (url.indexOf('/thumb/') < 0) {
		return url.replace(fileUrl, fileUrl + '/thumb');
	}
	return url;
}

/* 获取原图地址 */
export const original = (url) => {
	if (url.indexOf('/thumbnail/') > -1) {
		return url.replace('/thumbnail/', '/');
	}
	return url;
};

/**
 * 下载图片到相册
 * @param {string} imageUrl 图片地址
 * @param {function} successCallback 成功回调
 * @param {function} failCallback 失败回调
 */
export const downloadImage = (imageUrl, successCallback, failCallback) => {
	if (!imageUrl) {
		uni.showToast({
			title: '图片地址无效',
			icon: 'none'
		});
		return;
	}

	uni.showLoading({
		title: '下载中...',
		mask: true
	});

	// 下载图片
	uni.downloadFile({
		url: imageUrl,
		success: (res) => {
			if (res.statusCode === 200) {
				// 保存到相册
				uni.saveImageToPhotosAlbum({
					filePath: res.tempFilePath,
					success: () => {
						uni.hideLoading();
						uni.showToast({
							title: '保存成功',
							icon: 'success'
						});
						successCallback && successCallback();
					},
					fail: (err) => {
						uni.hideLoading();
						console.log('保存图片失败:', err);
						if (err.errMsg.includes('auth deny')) {
							uni.showModal({
								title: '提示',
								content: '请允许访问相册后重试\n(右上角菜单 - 设置 - 相册)',
								showCancel: false
							});
						} else {
							uni.showToast({
								title: '保存失败',
								icon: 'none'
							});
						}
						failCallback && failCallback(err);
					}
				});
			} else {
				uni.hideLoading();
				uni.showToast({
					title: '下载失败',
					icon: 'none'
				});
				failCallback && failCallback();
			}
		},
		fail: (err) => {
			uni.hideLoading();
			console.log('下载图片失败:', err);
			uni.showToast({
				title: '下载失败',
				icon: 'none'
			});
			failCallback && failCallback(err);
		}
	});
};

/**
 * 下载视频到相册
 * @param {string} videoUrl 视频地址
 * @param {function} successCallback 成功回调
 * @param {function} failCallback 失败回调
 */
export const downloadVideo = (videoUrl, successCallback, failCallback) => {
	if (!videoUrl) {
		uni.showToast({
			title: '视频地址无效',
			icon: 'none'
		});
		return;
	}

	uni.showLoading({
		title: '下载中...',
		mask: true
	});

	// 下载视频
	uni.downloadFile({
		url: videoUrl,
		success: (res) => {
			if (res.statusCode === 200) {
				// 保存到相册
				uni.saveVideoToPhotosAlbum({
					filePath: res.tempFilePath,
					success: () => {
						uni.hideLoading();
						uni.showToast({
							title: '保存成功',
							icon: 'success'
						});
						successCallback && successCallback();
					},
					fail: (err) => {
						uni.hideLoading();
						console.log('保存视频失败:', err);
						if (err.errMsg.includes('auth deny')) {
							uni.showModal({
								title: '提示',
								content: '请允许访问相册后重试\n(右上角菜单 - 设置 - 相册)',
								showCancel: false
							});
						} else {
							uni.showToast({
								title: '保存失败',
								icon: 'none'
							});
						}
						failCallback && failCallback(err);
					}
				});
			} else {
				uni.hideLoading();
				uni.showToast({
					title: '下载失败',
					icon: 'none'
				});
				failCallback && failCallback();
			}
		},
		fail: (err) => {
			uni.hideLoading();
			console.log('下载视频失败:', err);
			uni.showToast({
				title: '下载失败',
				icon: 'none'
			});
			failCallback && failCallback(err);
		}
	});
};