import CryptoJS from 'crypto-js';
/**
 * ========================================================================================================================
 * 以RecognizeBankCard为例。
 * 这里只是为了小程序端演示流程,所以将代码写在了小程序端
 * 真正上线不建议将ACCESS_KEY_ID和ACCESS_KEY_SECRET写在小程序端,会有泄漏风险,建议将请求API接口代码写到您的服务端
 * 请求银行卡识别:https://help.aliyun.com/document_detail/151893.html
 * ========================================================================================================================
 */
// 参数说明:
// miniProgramType:小程序类型,比如:微信小程序传参数:wx,支付宝传参数:my,钉钉传参数:dd,注意不要传字符串;
// callback:结果的回调
// type 1: 人物动漫化 2:人物素描化
function callRecognizeBankCard(imageURL, miniProgramType, type, callback) {
	const accessKeyId = "LTAI5tDPiEBZgfqNcWBqaFEc";
	//AccessKeySecret
	const accessKeySecret = "amI84BLFbHz6dhOVbuArrERmeemmnx";
	//这里endpoint为API访问域名,与类目相关,具体类目的API访问域名请参考:https://help.aliyun.com/document_detail/143103.html
	let endpoint = "facebody.cn-shanghai.aliyuncs.com";
	//API Action,能力名称,请参考具体算法文档详情页中的Action参数,这里以银行卡识别为例:https://help.aliyun.com/document_detail/151893.html
	let Action = "GenerateHumanAnimeStyle";
	//API_HTTP_METHOD推荐使用POST
	const API_HTTP_METHOD = "POST";
	//API_VERSION为API版本,与类目相关,具体类目的API版本请参考:https://help.aliyun.com/document_detail/464194.html
	let API_VERSION = "2019-12-30";
	const request_ = {};
	if (type == 2) {
		Action = "GenerateHumanSketchStyle";
		request_["ReturnType"] = "full";
	} else if (type == 3) {
		Action = "SegmentHDBody";
		endpoint = "imageseg.cn-shanghai.aliyuncs.com";
	} else if (type == 4) {
	    Action = "EnhanceImageColor";
		endpoint = "imageenhan.cn-shanghai.aliyuncs.com";
		API_VERSION = "2019-09-30";
		request_["ImageURL"] = imageURL;
		request_["Mode"] = "ln17_256";
		request_["OutputFormat"] = "png";
	} else {
		request_["AlgoType"] = "handdrawn";
	}
	//系统参数
	request_["SignatureMethod"] = "HMAC-SHA1";
	request_["SignatureNonce"] = signNRandom();
	request_["AccessKeyId"] = accessKeyId;
	request_["SignatureVersion"] = "1.0";
	request_["Timestamp"] = getTimestamp();
	request_["Format"] = "JSON";
	request_["RegionId"] = "cn-shanghai";
	request_["Version"] = API_VERSION;
	request_["ImageURL"] = imageURL;
	request_["Action"] = Action;
	callApiRequest(miniProgramType, request_, API_HTTP_METHOD, endpoint, accessKeySecret, callback);
};

//请求数据
function callApiRequest(miniProgramType, request_, API_HTTP_METHOD, endpoint, accessKeySecret, callback) {
	const url = generateUrl(request_, API_HTTP_METHOD, endpoint, accessKeySecret);
	miniProgramType.request({
		url: url,
		method: 'POST',
		header: {
			"ContentType": "application/json"
		},
		success: (result) => {
			//获取结果
			return typeof callback == "function" && callback(result.data)
		},
		fail: (error) => {
			//获取报错信息
			return typeof callback == "function" && callback(error.data)
		}
	})
};

/**
 * ========================================================================================================================
 * 以下代码仅仅为了调用服务端接口计算签名,其逻辑可参考文档:https://help.aliyun.com/document_detail/144904.html
 * 这里只是为了Web前端演示,所以将代码写在了Web前端
 * 真正上线不建议将ACCESS_KEY_ID和ACCESS_KEY_SECRET写在Web前端上,会有泄漏风险,建议将请求API接口代码写到您的服务端
 * ========================================================================================================================
 */
//随机数字
function signNRandom() {
	const Rand = Math.random()
	const mineId = Math.round(Rand * 100000000000000)
	return mineId;
};

//Timestamp
function getTimestamp() {
	let date = new Date();
	let YYYY = pad2(date.getUTCFullYear());
	let MM = pad2(date.getUTCMonth() + 1);
	let DD = pad2(date.getUTCDate());
	let HH = pad2(date.getUTCHours());
	let mm = pad2(date.getUTCMinutes());
	let ss = pad2(date.getUTCSeconds());
	return `${YYYY}-${MM}-${DD}T${HH}:${mm}:${ss}Z`;
};

function pad2(num) {
	if (num < 10) {
		return '0' + num;
	}
	return '' + num;
};

function ksort(params) {
	let keys = Object.keys(params).sort();
	let newParams = {};
	keys.forEach((key) => {
		newParams[key] = params[key];
	});
	return newParams;
};

function createHmac(stringToSign, key) {
	const CrypStringToSign = CryptoJS.HmacSHA1(CryptoJS.enc.Utf8.parse(stringToSign), key);
	const base64 = CryptoJS.enc.Base64.stringify(CrypStringToSign);
	return base64;
};

function encode(str) {
	var result = encodeURIComponent(str);
	return result.replace(/!/g, '%21')
		.replace(/'/g, '%27')
		.replace(/\(/g, '%28')
		.replace(/\)/g, '%29')
		.replace(/\*/g, '%2A');
};

function sha1(stringToSign, key) {
	return createHmac(stringToSign, key);
};

function getSignature(signedParams, method, secret) {
	var stringToSign = `${method}&${encode('/')}&${encode(signedParams)}`;
	const key = secret + "&";
	return sha1(stringToSign, key);
};

//参数拼接
function objToParam(param) {
	if (Object.prototype.toString.call(param) !== '[object Object]') {
		return '';
	}
	let queryParam = '';
	for (let key in param) {
		if (param.hasOwnProperty(key)) {
			let value = param[key];
			queryParam += toQueryPair(key, value);
		}
	}
	return queryParam;
};

function toQueryPair(key, value) {
	if (typeof value == 'undefined') {
		return `&${key}=`;
	}
	return `&${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
};

function generateUrl(request, httpMethod, endpoint, accessKeySecret) {
	//参数中key排序
	const sortParams = ksort(request);
	//拼成参数
	const sortQueryStringTmp = objToParam(sortParams);
	const sortedQueryString = sortQueryStringTmp.substring(1); // 去除第一个多余的&符号
	//构造待签名的字符串
	const Signture = getSignature(sortedQueryString, httpMethod, accessKeySecret)
	//签名最后也要做特殊URL编码
	request["Signature"] = encodeURIComponent(Signture);
	//最终生成出合法请求的URL
	const finalUrl = "https://" + endpoint + "/?Signature=" + encodeURIComponent(Signture) + sortQueryStringTmp;
	return finalUrl;
};

//导出方法
module.exports = {
	callRecognizeBankCard: callRecognizeBankCard,
	signNRandom: signNRandom,
	getTimestamp: getTimestamp,
	generateUrl: generateUrl,
	createHmac: createHmac
}