import { destroyLayers, layers } from "./modules/layers";
import { SceneController } from "./modules/layers/ctrls";
import { ModalCtroller } from "./modules/ModalControl";
import { RES } from "./modules/RES";
import { ResJson } from "./ResJson";
import { GameScene } from "./scenes/GameScene/GameScene";
import { NewGuyScene } from "./scenes/NewGuyScene/NewGuyScene";
import { Tools } from "./tools/Tools";
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;

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

export {
	G_Events
} from './scenes/GameScene/GameEvents'

export const loadAllGroups = async function() {
	RES.loadConfig(ResJson)
	await RES.loadAllGroup()
}

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

	constructor(
		canvas: HTMLCanvasElement,
		config: {
			isFirstGame: boolean
			skinName: string,
			gameDiff: {
				score: number
				speed: number
			}[]
		},
		desWidth = 750,
		desHeight = 1624,
		divWidth?: number,
		divHeight?: number,
		renderType = RENDERER_TYPE.WEBGL,
		stageCenter = true,
		fixedHeight = false,
		resolution?: any,
	) {
		let sysInfo;
		config && (Tools.PageData = config)
		// 淘宝小程序环境就用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();

    if (document) {
      this.initWebEvent()
    }
	}

	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);
	}

  async onAddToStage() {
		// const realSceneLayer = new FYGE.Container()
		// this.stage.addChild(realSceneLayer)
    layers.init(this.stage)
		// realSceneLayer.y = layers.stageOffsetY

		SceneController.init(layers.sceneLayer)

    RES.loadConfig(ResJson)
		await RES.loadGroup('common')

		SceneController.changeScene(Tools.PageData.isFirstGame ? NewGuyScene : GameScene)
  }

  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;//先不暂停了
		// 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();

		// 晴空下
		ModalCtroller.clearModalMap()

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

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