/**
 * cookie检测和转换
 * @author 转山
 * @date   2020-06-22
 * @param {String} cookie cookie字符串
 *
 * @returns {Object}
 *      isValid {String}
 *          all：    正确cookie字符串，所有都能解析
 *          part：   部分cookie字符串可解析
 *          not：    不是正常格式的cookie字符串
 *      value   {Object}    解析好的cookie对象
 *      source  {String}    传入的cookie，原封不动带回
 */
export const isValidOnCookie = function (cookie) {
	let output = {
		isValid: 'all',
		value: {},
		source: cookie
	};
	// 是否是string字符串
	if (typeof cookie === 'string') {
		// 判断是否有=号
		if (/=/.test(cookie)) {
			let parseObj = {};
			// 截取分号
			let tempArr = cookie.split(/\s*;\s*/);
			tempArr.forEach(x => {
				// 判断是否运行时检查到非法数据
				if (output.isValid === 'not') return;
				// 判断k-v，是否有多个=号
				if (x.match(/=/g) === null || x.match(/=/g).length === 1) {
					// 分割键值
					let key_value = /^(.+)=(.+)$/.exec(x);
					if (key_value) {
						parseObj[key_value[1]] = key_value[2];
					} else {
						output.isValid = 'part';
					}
				} else {
					output.isValid = 'not';
				}
			});
			output.value = parseObj;
		} else {
			// 无法转换成对象
			output.isValid = 'not';
		}
	} else {
		output.isValid = 'not';
	}


	return output;
};

/**
 * 将对象转成cookie字符串
 * @author 转山
 * @date   2020-06-22
 * @param {Object} cookieObj 对象
 *
 * @returns {String}    cookie字符串
 */
export const cookieToString = function (cookieObj) {
	let output = '';
	for (let key in cookieObj) {
		output += `${key}=${cookieObj[key]};`;
	}
	return output.replace(/;$/, '');
};


/**
 * 校验数据格式类型
 * @author 转山
 * @date   2020-09-16
 */
export const is = (() => {
	let is = {
		types: ["Array", "Boolean", "Date", "Number", "Object", "RegExp", "String", "Window", "HTMLDocument", "function", "FormData"]
	};
	is.types.forEach(x => {
		is[x] = function (obj) {
			let temp;
			if (x === "function") {
				temp = typeof obj === x;
			} else {
				temp = Object.prototype.toString.call(obj) === "[object " + x + "]";
			}
			return temp;
		};
	});

	is.getType = function (obj) {
		let output = null;
		if (typeof obj === 'function') {
			output = 'function';
		} else {
			const re = new RegExp(is.types.join('|'));
			let temp = re.exec(Object.prototype.toString.call(obj));
			if (temp && temp[0]) {
				output = temp[0];
			}
		}
		return output;
	};
	return is;
})();

/**
 * 校验数据格式类型
 * @author 转山
 * @date   2020-09-16
 */
export const checkParam = function (param = [], paramType = [], other = {
	name: ''
}) {
	if (paramType.length === 0) return false;

	if (param.length < paramType.length) {
		console.error(`[bl warn]: Parameter missing: number check failed for parameter in "${other.name}". Expected ${paramType.length}, got ${param.length} with value missing.`);
		return false;
	} else {
		let isContinue = true;
		let output = true;
		let start = 0;
		while (isContinue) {
			if (paramType[start].key) {
				if (is.Array(paramType[start].type)) {
					let temp = false;
					paramType[start].type.forEach(x => {
						temp = temp || is[x](param[start]);
					});

					if (!temp) {
						console.warn(`[bl warn]: Invalid parameter: type check failed for parameter "${paramType[start].key}" in "${other.name}". Expected ${paramType[start].type.join(' | ')}, got ${is.getType(param[start])} with value false.`);
					}
				} else {
					if (!is[paramType[start].type](param[start])) {
						console.warn(`[bl warn]: Invalid parameter: type check failed for parameter "${paramType[start].key}" in "${other.name}". Expected ${paramType[start].type}, got ${is.getType(param[start])} with value false.`);
						isContinue = output = false;
					}
				}

			}

			if (paramType.length - 1 === start) isContinue = false;
			start++;
		}
		return output;
	}
};

/**
 * 校验数据格式类型
 * @author 转山
 * @date   2020-09-16
 */
export const checkParamPromise = function (param = [], paramType = [], other = {
	name: ''
}) {
	return new Promise(function (resolve, reject) {
        if (paramType.length === 0) reject({
			errorMessage: '校验规则不足.'
		});

        if (param.length < paramType.length) {
            let _msg  = `${other.name}:fail Parameter missing: number check failed for parameter in "${other.name}". Expected ${paramType.length}, got ${param.length} with value missing.`
            reject({
				errorMessage: _msg
			});
        } else {
            let isContinue = true;
            let output = true;
            let start = 0;
            let _msg = ''
            while (isContinue) {
                if (paramType[start].key) {
                	// 类型校验
                    if (is.Array(paramType[start].type)) {
                        let temp = false;
                        paramType[start].type.forEach(x => {
                            temp = temp || is[x](param[start]);
                        });

                        if (!temp) {
							_msg = `${other.name}:fail Invalid parameter: type check failed for parameter "${paramType[start].key}" in "${other.name}". Expected ${paramType[start].type.join(' | ')}, got ${is.getType(param[start])} with value false.`;
                        }
                    } else {
                        if (!is[paramType[start].type](param[start])) {
							_msg = `${other.name}:fail Invalid parameter: type check failed for parameter "${paramType[start].key}" in "${other.name}". Expected ${paramType[start].type}, got ${is.getType(param[start])} with value false.`;
                            isContinue = output = false;
                        }

						if (paramType[start].type === 'String' && paramType[start].require === true) {
							if (param[start] === '') {
								_msg = `${other.name}:fail Invalid parameter: ${paramType[start].key} can not be empty string.`;
								isContinue = output = false;
							}
						}
                    }
                }

                if (paramType.length - 1 === start || !output) isContinue = false;
                start++;
            }
            if (output) {
                resolve()
            } else {
                reject({
					errorMessage: _msg
				})
            }
        }
    });
};


export function compareVersion(v1, v2) {
	v1 = v1.split('.');
	v2 = v2.split('.');
	const len = Math.max(v1.length, v2.length);

	while (v1.length < len) {
		v1.push('0');
	}
	while (v2.length < len) {
		v2.push('0');
	}

	for (let i = 0; i < len; i++) {
		const num1 = parseInt(v1[i]);
		const num2 = parseInt(v2[i]);

		if (num1 > num2) {
			return 1;
		} else if (num1 < num2) {
			return -1;
		}
	}

	return 0;
}
