/**
 * Created by hwj on 2018/11/22.
 * 网络组件
 */

import {utils, engine} from "scilla";

/**
 * 调用接口
 * @param uri
 * @param params
 * @param method
 * @param responseType
 * @param ignoreSuccessField
 */
export function callApi(uri: string, params: any = null, method: string = 'post', responseType = 'json', ignoreSuccessField = false): Promise<any> {
	let ts = Date.now() + Math.floor(Math.random() * 9999999);

	let url = uri.startsWith('//') ? uri : `${engine.customConfig.webServiceUrl}${uri}?_=${ts}`;

	params = params || {};

	let options: any = {
		method,
	};

	if (!DEBUG) {
		options.credentials = 'include';
	}

	let temp = typeof params === 'string' ? params : utils.objectStringify(params);
	switch (method.toUpperCase()) {
		case 'GET':
			if(temp && temp.length > 0){
				url += (url.indexOf('?') < 0 ? '?' : '') + '&' + temp;
			}
			break;
		case 'POST':
			options.body = temp;
			options.headers = {
				'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
			};
			break;
	}

	const fetchMethod = responseType == 'jsonp' ? window['fetchJsonp'] : fetch;

	return fetchMethod(url, options)
		.then((response) => {
			if (response.type === 'opaque') {
				return null;
			}
			return response.text();
		})
		.then((response) => {
			//console.log('fetch ==>', url, response);
			if (response) {
				let data;
				switch (responseType) {
					case 'json':
						try {
							data = JSON.parse(response);
						} catch (e) {
							console.log('decode json failed: ' + url);
							return Promise.reject({});
						}

						if (ignoreSuccessField || data.success) {
							return {
								data: data.hasOwnProperty('data') ? data.data : data,
								origin: data,
							};
						} else {
							return Promise.reject(data.code);
						}
					case 'html':
						let html = null;//DOMParser.parseFromString(response, 'text/html');
						return html;
					case 'txt':
						return response;
				}
			}

			return Promise.reject();
		})
}

/**
 * 轮训请求
 * @param successFunc
 * @param maxTimes
 * @param delay
 * @param uri
 * @param params
 * @param abortFunc
 * @param method
 * @param responseType
 */
export async function polling(successFunc, uri, params, maxTimes = 10, delay = 500, abortFunc?: Function, method = 'POST', responseType = 'json'): Promise<any> {
	let lastData;

	/*let p = Promise.resolve();

	for (let i = 0; i < maxTimes; i++) {
		if(abortFunc){
			p.then(
				()=>{
				if(abortFunc()){
					return Promise.reject('abort');
					//throw new Error('abort');
				}
			}, (e)=>{
					return Promise.reject(e);
				}
			)
		}
		p = p.then(func);
		p = p.then(() => {
			return utils.waitPromise(delay)
		})
	}

	return p.then(
		() => {
			return Promise.reject(null);
		},
		(e) => {
			if (e === 'success') {
				return Promise.resolve(lastData);
			}

			return Promise.reject(e);
		}
	);*/

	let needBreak;
	for (let i = 0; i < maxTimes; i++) {
		await func().catch(e=>{
			if (e === 'success') {
				needBreak = true;
			}else{
				throw e;
			}
		});
		if(needBreak){
			break;
		}
		if(abortFunc()){
			throw new Error('abort')
		}
		await utils.waitPromise(delay);
	}

	if(!needBreak){
		throw new Error('timeout')
	}

	return lastData;

	function func() {
		return callApi(uri, params, method, responseType).then(
			(data) => {
				if (successFunc(data)) {
					lastData = data;
					return Promise.reject('success');
				}
			}
		)
	}
}

/**
 * 获取token并发送
 * @param uri
 * @param params
 * @param method
 * @param responseType
 */
export async function getToken(uri: string, params: any, method: string = 'POST', responseType: string = 'json') {
	if (window['getDuibaToken']) {
		window['getDuibaToken'](async (tokenObj: any) => {
			params.token = tokenObj.token;
			await this.send(uri, params, method, responseType);
		}, () => {
		});
	} else {
		await this.send(uri, params, method, responseType);
	}
}

// /**
//  * 通讯底层错误
//  */
// protected onError(key,msgObj): void {
//     const msg = `${key}:${msgObj}`
//     this.dispatchEvent('Error', msg );
// }

/**
 * 生成签名
 * @param {number} ticketId
 * @param {number} score
 * @param {any} gameData
 * @param {string} submitToken 提交
 * @returns {string} 签名
 */
export function createSgin(ticketId: number, score: number, gameData: any, submitToken: string): string {
	return window['duiba_md5'](ticketId + '' + score + '' + gameData + '' + submitToken);
}

