/**
 * Created by rockyl on 2019-11-22.
 */

import {injectProp, obj2query} from "./utils";

/**
 * http请求
 * @param url
 * @param method
 * @param params
 * @param type
 * @param headers
 */
export function httpRequest(url: string, method: string = 'get', params?: any, type: 'text' | 'json' | 'jsonp' = 'text', headers?) {
	let openUrl = url.indexOf('blob') === 0 ? url : urlJoin(url, '__ts__=' + Date.now());
	let mParams = {};
	injectProp(mParams, params);
	if (type === "jsonp") {
		return jsonp(openUrl, mParams);
	} else {
		return new Promise((resolve, reject) => {
			let mHeaders = {
				'Content-Type': 'application/x-www-form-urlencoded',
			};
			injectProp(mHeaders, headers);

			let request = {url, method, params: mParams, type, headers: mHeaders};

			const mock = window['mock'];
			let mockRule;
			if (mock) {
				mock(request, (rule) => {
					mockRule = rule;
					if (!mockRule) {
						doRequest(request, resolve, reject);
					}
				}, resolve, reject);
			} else {
				request.url = openUrl;
				doRequest(request, resolve, reject);
			}
		});
	}
}

function doProxyRequest(payload, resolve, reject) {
	let proxyWindow = window['proxy_window'];
	window.addEventListener('message', onMessage, false);

	proxyWindow.postMessage(JSON.stringify({
		action: 'http-request-proxy',
		payload: payload,
	}), '*');

	function onMessage(event) {
		window.removeEventListener('message', onMessage);
		try {
			let data = JSON.parse(event.data);
			console.log('onMessage', event.data);

			switch (data.action) {
				case 'http-request-proxy-resolve':
					resolve(data.payload);
					break;
				case 'http-request-proxy-reject':
					reject(data.payload);
					break;
			}
		} catch (e) {

		}
	}
}

function doXhrRequest({url, method, params, type, headers}, resolve, reject) {
	let xhr;
	if (window["XMLHttpRequest"]) {
		xhr = new XMLHttpRequest();
	} else if (window["ActiveXObject"]) {
		xhr = new window["ActiveXObject"]();
	} else {
		console.log('no xhr');
	}
	if (xhr != null) {
		const isGet = method.toUpperCase() === 'GET';
		const queryStr = obj2query(params);
		let openUrl = url;
		if (openUrl.indexOf('projectx') == 0) {
			openUrl = '/' + openUrl;
		}
		if (isGet) {
			openUrl = urlJoin(openUrl, queryStr);
		}
		xhr.open(method, openUrl, true);
		for (let key in headers) {
			xhr.setRequestHeader(key, headers[key]);
		}
		xhr.responseType = type;
		xhr.onreadystatechange = () => {
			if (xhr.readyState == 4 && xhr.status == 200) {
				resolve(xhr.response)
			}
		};
		xhr.onerror = (reason): void => {
			reject(reason)
		};
		xhr.onloadend = (): void => {
			if (xhr.status == 404) {
				reject(url + ' 404 (Not Found)')
			}
		};
		if (isGet) {
			xhr.send();
		} else {
			xhr.send(queryStr);
		}
	}
}

function doRequest(payload, resolve, reject) {
	if (window['proxy_window'] && payload.url.indexOf('blob') !== 0) {
		doProxyRequest(payload, function (p) {
			resolve(p);
		}, reject);
	} else {
		doXhrRequest(payload, resolve, reject);
	}
}

/**
 * jsonp请求
 * @param url
 * @param params
 */
export function jsonp(url, params) {
	return new Promise<void>((resolve, reject) => {
		const src = urlJoin(url, obj2query(params));
		const scriptEl = document.createElement('script');
		scriptEl.src = src;
		scriptEl.onload = function () {
			resolve();
			document.body.removeChild(scriptEl);
		};
		scriptEl.onerror = function () {
			reject();
			document.body.removeChild(scriptEl);
		};
		/*const callbackFuncName = '__zeroing_jsonp_callback__' + Math.random();
		window[callbackFuncName] = function () {
			callback(result);
		};*/
		document.body.appendChild(scriptEl);
	})
}

export function urlJoin(url, query) {
	if (query) {
		url += url.indexOf('?') < 0 ? '?' : '';
		url += url[url.length - 1] === '?' ? '' : '&';
		return url + query;
	} else {
		return url;
	}
}
