import { layers, destroyLayers } from "../module/views/layers";
import { RES } from "../module/RES";
import { changeScene, destroyAllCtrls, showToast } from "../module/ctrls";
import { G_EVENT } from "./common/G_EVENT";
import { IndexScene } from "./scenes/IndexScene";


import { ResJson } from "./ResJson";
import { SkinJson } from "./SkinJson";
import { destroyTbNetData } from "./tools/TaoBaoNet";
import { Tools } from "./tools/Tools";
import { destroyWebNetData } from "./tools/WebNet";
import Tween = FYGE.Tween;
import EventDispatcher = FYGE.EventDispatcher;
import Stage = FYGE.Stage;
import RENDERER_TYPE = FYGE.RENDERER_TYPE;
import Event = FYGE.Event;
import getEnv = FYGE.getEnv;

import Texture = FYGE.Texture;

/**
 * 全局事件，为了和小程序交互
 * 有可能多处页面用到，所以单开
 */
export const GDispatcher = new EventDispatcher();

export class Game {
	//主舞台
	stage: Stage;
	private requestID;
	private _pause: boolean;
	private canvas: HTMLCanvasElement;

	constructor(
		canvas: HTMLCanvasElement,
		desWidth = 750,
		desHeight = 1624,
		divWidth?,
		divHeight?,
		renderType = RENDERER_TYPE.WEBGL,
		stageCenter = true,
		fixedHeight = false,
		resolution?,
	) {
		let sysInfo;
		// 淘宝小程序环境就用canvas初始化
		if (!window) {  // 自行处理吧，这么判断也不保险，万一淘宝小程序加进了window
			FYGE.initedByCanvas(canvas);    // 里面会设置env为tb，这个很重要
			// @ts-ignore 存在my就初始化
			sysInfo = my.getSystemInfoSync();
		}

		divWidth = divWidth || sysInfo?.windowWidth || document.body.clientWidth;
		divHeight = divHeight || sysInfo?.windowHeight || document.body.clientHeight;
		resolution = resolution || sysInfo?.pixelRatio || window.devicePixelRatio || 1;

		// 建舞台
		const stage = this.stage = new Stage(
			canvas,
			desWidth,       // 设计宽度，按设计搞给的就行
			desHeight,      // 设计高度
			divWidth,       // 显示宽度，全屏就是屏幕宽度
			divHeight,      // 显示高度，全屏就是屏幕高度
			renderType,     // 渲染模式canvas
			stageCenter,    // 视窗居中裁切
			fixedHeight,    // 不定高，定宽适配
			resolution,     // 分辨率
		);

		this.canvas = canvas; // 赋值下，为了下面的destroy的cancelAnimationFrame

		// stage初始化
		stage.addEventListener(Event.INIT_STAGE, this.onAddToStage, this);

		//循环
		this.loop();
	}

	private loop = () => {
		if (!this._pause) {
			Tween.flush();
			this.stage.flush();
		}

		// @ts-ignore
		getEnv() == "tb" ? this.requestID = this.canvas.requestAnimationFrame(this.loop) :
			this.requestID = window.requestAnimationFrame(this.loop);
	}


	private async onAddToStage() {
		//初始化层级
		layers.init(this.stage);
		console.log("初始化层级完成");

		//初始化资源配置
		RES.loadConfig(ResJson);
		console.log("初始化资源配置完成");

		//皮肤配置加载
		RES.loadSkinConfig(SkinJson);
		console.log("初始化皮肤配置完成");

		//加载通用资源
		await RES.loadGroup("common");
		console.log("通用资源加载完成");

    //加载通用资源
		await RES.loadGroup("bird");
		console.log("bird资源加载完成");

		// h5环境时，隐藏加载中
		if (getEnv() == "web" && document.getElementById("__loading__")) {
			document.getElementById("__loading__").style.display = "none";
		}

		await Promise.all([
			Texture.fromUrl("https://yun.duiba.com.cn/aurora/assets/923bcdee2d54f39797fb1cc5a79ab84da1bbe972.jpg"),
			Texture.fromUrl("https://yun.duiba.com.cn/aurora/assets/92856abbb6293e863708fa2c0ea3556cf9b2afaa.jpg"),
			Texture.fromUrl("https://yun.duiba.com.cn/aurora/assets/d660b9e12c66ad2c42fca23c57bf33db5009fedf.jpg"),
			Texture.fromUrl("https://yun.duiba.com.cn/aurora/assets/a6903842083d8015e2e81d2dc652370574be6774.jpg"),
		]);

		// MusicBtn.changeMusicStatus(true);   /// TODO 进游戏打开音乐先
		changeScene(IndexScene, { from: "main" });
	}

	initWebEvent(){
		const mouseEvent = this.stage.onMouseEvent.bind(this.stage);
		this.canvas.addEventListener("touchstart", mouseEvent, false);
		this.canvas.addEventListener('touchmove', mouseEvent, false);
		this.canvas.addEventListener('touchend', mouseEvent, false);
	}

	run() {
		this._pause = false;
		// @ts-ignore Tween计时清零
		Tween._lastTime = null;
		// 触发onShow
		GDispatcher.dispatchEvent({ type: G_EVENT.ON_SHOW });
	}

	/**
	 * 在小程序隐藏时调用onHide
	 */
	pause() {
		// this._pause = true;//先不暂停了
		// 触发onHide
		GDispatcher.dispatchEvent({ type: G_EVENT.ON_HIDE });
	}


	/**
	 * 添加全局事件，用于小程序的交互调用
	 * 一直很犹豫要不要放在main的实例里，还是和Main同级导出，还有上面的pause，run，下面的事件等
	 * @param name
	 * @param fun
	 * @param thisObj
	 * @param once
	 */
	addGlobalEvent(name: string, fun: Function, thisObj?: any, once: boolean = false) {
		if (once) {
			GDispatcher.once(name, fun, thisObj)
		} else {
			GDispatcher.addEventListener(name, fun, thisObj)
		}
	}

	/**
	 * 派发全局事件，用于小程序的交互调用
	 * @param name 可以是事件名，也可以是事件
	 * @param data
	 */
	dispatchGlobalEvent(name: string | any, data?: any) {
		GDispatcher.dispatchEvent(name, data)
	}

	/**
	 * 移除全局事件，用于小程序交互调用
	 * @param name
	 * @param fun
	 * @param thisObj
	 */
	removeGlobalEvent(name: string, fun: Function, thisObj?: any) {
		GDispatcher.removeEventListener(name, fun, thisObj)
	}

	//在小程序页面卸载时调用onUnload，多次销毁后会有问题，再检查
	destroy() {
		// Tween都移除，注意吧，可能原先的也被移除,对于多page时注意，会把其他页面的也去掉
		Tween.removeAllTweens();
		// 停掉计时器

		// @ts-ignore 为了兼容多page的canvas
		FYGE.getEnv() == "tb" ? this.canvas.cancelAnimationFrame(this.requestID) :
			window.cancelAnimationFrame(this.requestID);

		// 层级销毁
		destroyLayers();

		// 销毁控制器
		destroyAllCtrls();

		// 舞台销毁
		this.stage.destroy();

		// 全局事件置空
		GDispatcher.removeAllEventListener();

		// 淘宝环境网络数据记录清
		destroyTbNetData();

		// 网络数据记录清空
		destroyWebNetData();
	}
}
