/**
 * 游戏主要管理器
 */
class GameMgr {
	private static _instance: GameMgr;

	static get instance(): GameMgr {
		if (!this._instance) {
			this._instance = new GameMgr();
		}
		return this._instance;
	}

	private constructor() {
		Lang.instance.register();
		EosMgr.instance.register();
	}

	private _main: Main;
	get main(): Main {
		return this._main;
	}
	setMain(main: Main) {
		this._main = main;
	}

	private _uiCtrl: UIController;
	get uiController(): UIController { return this._uiCtrl; }

	private loadingView: LoadingUI;
	private index: Index;
	public createdGame: boolean = false;
	async runGame() {
		// 将ui控制器添加到舞台中
		this._uiCtrl = UIController.instance;
		this._main.stage.addChild(this._uiCtrl);

		await this.preload();
		await this.loadResource();
	}

	/**
	 * 预加载部分资源
	 */
	private async preload() {
		await RES.loadConfig(`default.res.json?${VersionController.currentVersion}`, 'resource/');
		await RES.loadGroup('load');
		// 皮肤方案
		await this.loadTheme();

		this.loadingView = UIController.instance.createView<LoadingUI>(LoadingUI);
		this._main.stage.addChild(this.loadingView);

		await RES.loadGroup("preload", 1, this.loadingView);
	}

	/**
	 * 加载资源
	 */
	private async loadResource() {
		RES.addEventListener(RES.ResourceEvent.GROUP_LOAD_ERROR, this.onResourceLoadError, this);
		RES.addEventListener(RES.ResourceEvent.ITEM_LOAD_ERROR, this.onItemLoadError, this);

		DEBUG && console.log('loadResource');
		// 加载其他资源组
		if (GAME_ISMOBILE) {
			await RES.loadGroup("skin_h5");
		} else {
			await RES.loadGroup("skin_pc");
		}
		this.createGameScene();
	}

	private async loadAudio() {
		await RES.setMaxLoadingThread(1);
		await RES.loadGroup("audio");
		await RES.setMaxLoadingThread(3);
		AudiosMgr.instance.loaded();
	}

	private loadTheme() {
		DEBUG && console.log('loadTheme start');
		return new Promise((resolve, reject) => {
			// load skin theme configuration file, you can manually modify the file. And replace the default skin.
			//加载皮肤主题配置文件,可以手动修改这个文件。替换默认皮肤。
			let theme = new eui.Theme(`resource/default.thm.json?${VersionController.currentVersion}`, this._main.stage);
			theme.addEventListener(eui.UIEvent.COMPLETE, () => {
				resolve();
			}, this);
		})
	}
	private onItemLoadError(event: RES.ResourceEvent): void {
		console.warn("Url:" + event.resItem.url + " has failed to load");
	}

	/**
     * 资源组加载出错
     *  The resource group loading failed
     */
	private onResourceLoadError(event: RES.ResourceEvent): void {
		//TODO
		console.warn("Group:" + event.groupName + " has failed to load");
		//忽略加载失败的项目
		//Ignore the loading failed projects
		this.loadResource();
		RES.removeEventListener(RES.ResourceEvent.GROUP_LOAD_ERROR, this.onResourceLoadError, this);
		RES.removeEventListener(RES.ResourceEvent.ITEM_LOAD_ERROR, this.onItemLoadError, this);
	}
    /**
     * 创建游戏场景
     * Create a game scene
     */
	private createGameScene() {
		RES.removeEventListener(RES.ResourceEvent.GROUP_LOAD_ERROR, this.onResourceLoadError, this);
		RES.removeEventListener(RES.ResourceEvent.ITEM_LOAD_ERROR, this.onItemLoadError, this);

		this.createdGame = true;
		console.log("进入游戏场景");
		// 移除loading界面
		if (this.loadingView) {
			UIController.instance.closeView(this.loadingView);
			this.loadingView = undefined;
		}

		SocketMgr.instance.openSocket();

		Api.getGameInfo()

		this.index = Index.instance;

		setTimeout(() => {
			this.loadAudio();
		}, 300);

		EOS_VUE.$gameLoaded();
	}

	/**
	 * 添加事件监听
	 */
	addEventListener(type: string, listener: Function, thisObject: any, useCapture?: boolean, priority?: number): any {
		return this._main.addEventListener(type, listener, thisObject, useCapture, priority);
	}

	/**
	 * 移除事件监听
	 */
	removeEventListener(type: string, listener: Function, thisObject: any, useCapture?: boolean): void {
		this._main.removeEventListener(type, listener, thisObject, useCapture);
	}

	/**
	 * 分派事件
	 */
	dispatchEvent(event: egret.Event): boolean {
		return this._main.dispatchEvent(event);
	}

	/**
	 * 派发一个指定参数的事件。
	 * @param type {string} 事件类型
	 * @param bubbles {boolean} 确定 Event 对象是否参与事件流的冒泡阶段。默认值为 false。
	 * @param data {any} 事件data
	 * @param cancelable {boolean} 确定是否可以取消 Event 对象。默认值为 false。
	 */
	dispatchEventWith(type: string, bubbles?: boolean, data?: any, cancelable?: boolean): boolean {
		return this._main.dispatchEventWith(type, bubbles, data, cancelable);
	}
}