export abstract class middleLayerBase extends cc.Component {

	abstract reWriteAir(): void;
	abstract showMask(): void;
	abstract hideMask(): void;
	abstract hideWaitingLetters(): void;
	abstract showWaitingLetters(): void;

	callNetworkApiPost(uri, data, callBack) {
		this.getBaseUrl((baseUrl) => {
			const xhr = new XMLHttpRequest();
			const url = `${baseUrl}${uri}`;
			xhr.open("POST", url, true);
			xhr.setRequestHeader('content-type', 'application/json');
			xhr.onreadystatechange = () => {
				if (xhr.readyState == 4) {
					callBack(JSON.parse(xhr.responseText));
				}
			}
			xhr.send(JSON.stringify(data));
		});
	}

	callNetworkApiGet(uri, data, callBack) {
		this.getBaseUrl((baseUrl) => {
			let queryStr = '?';
			const params = [];
			for (const key in data) {
				if (Object.hasOwnProperty.call(data, key)) {
					params.push(`${key}=${data[key]}`);
				}
			}
			queryStr += params.join("&");
			const xhr = new XMLHttpRequest();
			xhr.onreadystatechange = () => {
				if (xhr.readyState == 4 && (xhr.status >= 200 && xhr.status < 400)) {
					callBack(xhr.responseText);
				}
			};
			const url = `${baseUrl}${uri}${queryStr}`;
			console.log('url = ' + url);
			xhr.open('GET', url, true);
			xhr.send();
		});
	}

	async getBaseUrl(callback) {
		const engineInfo = await this.getEngineInfo();
		const { isDev } = JSON.parse(engineInfo);
		if (isDev == 1) {
			callback('http://staging-openapi.iteachabc.com');
		} else {
			callback('http://openapi.iteachabc.com');
		}
	}

	getEngineInfo() {
		if ((<any>window).air.engineInfo) {
			return (<any>window).air.engineInfo;
		} else {
			return new Promise((resolve, reject) => {
				(<any>window).courseware.getEngineInfo(() => {
					resolve((<any>window).air.engineInfo);
				});
			});
		}
	}
	asyncCallNetworkApiGet(apiName, data) {
		return new Promise((resolve, reject) => {
			this.callNetworkApiGet(apiName, data, (res => {
				resolve(res);
			}));
		});
	}
	asyncCallNetworkApiPost(uri, data) {
		return new Promise((resolve, reject) => {
			this.callNetworkApiPost(uri, data, (res) => {
				resolve(res);
			});
		});
	}

	loadOnlineBundle(bundleName) {
		this.callNetworkApiGet(`/api/template/v1/${bundleName}`, {}, (datastr) => {
			const data = JSON.parse(datastr);
			let configData = null;
			if (cc.sys.os == cc.sys.OS_IOS) {
				configData = data.data.conf.ios;
			} else if (cc.sys.os == cc.sys.OS_ANDROID) {
				configData = data.data.conf.android;
			} else {
				configData = data.data.conf.web_desktop;
			}
			const sceneName = configData.sceneName;
			const version = configData.version;
			const bondleUrl = configData.bondleUrl;
			this.loadBundle(sceneName, version, bondleUrl);
		});
	}
	currentBundleInfo = null;

	reloadBundle() {
		const { sceneName, version, bondleUrl } = this.currentBundleInfo;

		this.loadBundle(sceneName, version, bondleUrl);
	}

	loadBundle(sceneName, version, bondleUrl) {
		this.currentBundleInfo = { sceneName, version, bondleUrl };
		this.showMask();
		this.showWaitingLetters();
		cc.assetManager.loadBundle(bondleUrl, { version: version }, async (err, bundle) => {
			bundle.loadScene(sceneName, null, null, (err, scene) => {
				const btnRestart = cc.find('middleLayer/BtnRestart');
				btnRestart.active = false;
				cc.audioEngine.stopAll();
				cc.director.runScene(scene, null, () => {
					console.log('sceneName = ' + sceneName);
					const canvas = cc.find('Canvas');
					const middleLayer = cc.find('middleLayer');
					cc.find('middleLayer/ExitBtn').active = true;
					this.hideWaitingLetters();
					this.hideMask();
					canvas.getComponent(cc.Widget).updateAlignment();
					middleLayer.scale = canvas.width / middleLayer.width;
					// this.showLog('middleLayer.scale = ' + middleLayer.scale);
				});
			});
		});
	}

	courses = null;
	courseIndex = 0;
	courseItem = null;
	loadOnlineCourseWare(courseId, linkFlag = false) {
		this.showWaitingLetters();

		let api = `/api/courseware/v1/${courseId}/list`;
		if (linkFlag === true) {
			api = `/api/courseware/v1/${courseId}/eq/level/list`;
		}
		this.callNetworkApiGet(api, {}, (datastr) => {
			const data = JSON.parse(datastr);
			if (data.rows && data.rows.length > 0) {
				this.courses = data.rows;
				this.courseIndex = data.index || 0;
				this.courseItem = data.rows[this.courseIndex];
			}
			if (this.courses && this.courses.length > 1 && this.courseIndex <= this.courses.length - 1) {
				cc.find('middleLayer/BtnRight').active = true;
			}
			if (this.courseIndex > 0) {
				cc.find('middleLayer/BtnLeft').active = false;
			}
			this.reWriteAir();
			this.loadPageBundle();
		});
	}

	loadPageBundle() {
		let sceneName, version, bondleUrl = "";
		if (cc.sys.os == cc.sys.OS_IOS) {
			sceneName = this.courseItem.conf.ios.sceneName;
			version = this.courseItem.conf.ios.version;
			bondleUrl = this.courseItem.conf.ios.bondleUrl;
		} else if (cc.sys.os == cc.sys.OS_ANDROID) {
			sceneName = this.courseItem.conf.android.sceneName;
			version = this.courseItem.conf.android.version;
			bondleUrl = this.courseItem.conf.android.bondleUrl;
		} else {
			sceneName = this.courseItem.conf.web_desktop.sceneName;
			version = this.courseItem.conf.web_desktop.version;
			bondleUrl = this.courseItem.conf.web_desktop.bondleUrl;
		}

		this.loadBundle(sceneName, version, bondleUrl);
	}
	goPrePage() {
		this.goTarIndexPage(this.courseIndex - 1);
	}
	goNextPage() {
		this.goTarIndexPage(this.courseIndex + 1);
	}
	goTarIndexPage(index) {
		if (!this.courses || index == this.courseIndex || index < 0 || index > this.courses.length - 1) {
			return;
		}

		(<any>window).courseware.freeAllOcMethod();

		this.courseIndex = index;
		this.courseItem = this.courses[this.courseIndex];
		this.loadPageBundle();
	}

	showTips(str) {
		const tipsNode = new cc.Node();
		tipsNode.parent = cc.find('Canvas');
		tipsNode.zIndex = 100;

		const bg = cc.instantiate(cc.find('middleLayer/bg'));
		bg.parent = tipsNode;
		bg.active = true;
		bg.color = cc.color(100, 100, 100);

		const labelNode = new cc.Node();
		labelNode.parent = tipsNode;
		const label = labelNode.addComponent(cc.Label);
		label.string = str;

		bg.width = 200;
		bg.height = labelNode.height + 20;

		cc.tween(tipsNode)
			.set({ opacity: 255 })
			.delay(1)
			.to(1, { opacity: 0 })
			.removeSelf()
			.start();
	}

	log(str) {
		cc.log(str);
	}

}