/**
 * Created by rockyl on 2018-12-04.
 */

import {engine, utils, cleanEntity} from "scilla";
import Scene from './Scene'

export {default as Scene} from './Scene'

export default class ScillaLauncher{
	private currentScene: Scene;
	private resUUIDs: string[];

	/**
	 * 启动引擎
	 * @param containerElement
	 * @param options
	 * @param onProgress
	 */
	async launch(containerElement, options:any = {}, onProgress: Function) {
		const resPath = options.resPath || '';
		const manifest = await engine.assetsManager.loadJson(resPath + 'manifest.json');

		engine.assetsManager.setResPath(resPath + 'assets/');

		let engineConfig:any = {};
		utils.injectProp(engineConfig, manifest.engineConfig);
		utils.injectProp(engineConfig, options.engineConfig);

		let customConfig:any = {};
		utils.injectProp(customConfig, manifest.customConfig);
		utils.injectProp(customConfig, options.customConfig);

		let dataCenterConfig:any = {};
		utils.injectProp(dataCenterConfig, manifest.dataCenterConfig);
		utils.injectProp(dataCenterConfig, options.dataCenterConfig);

		let canvas = document.createElement('canvas');
		containerElement.appendChild(canvas);

		engineConfig.canvas = canvas;
		engine.setup(engineConfig, customConfig, dataCenterConfig);

		let entryScene = options.scene || customConfig.scene.entryScene;

		await this.launchScene(entryScene, options.resReplaceConfigs, onProgress)
	}

	/**
	 * 启动场景
	 * @param sceneNameOrPath
	 * @param resReplaceConfigs
	 * @param progress
	 */
	async launchScene(sceneNameOrPath, resReplaceConfigs?, progress?) {
		const sceneConfig = engine.customConfig.scene;
		let sceneFile = sceneConfig.scenes[sceneNameOrPath];

		if(!sceneFile){
			sceneFile = sceneNameOrPath;
		}
		const scene = await this.loadScene(sceneFile, 'scene_' + sceneFile);

		this.resUUIDs = engine.assetsManager.getAllResUuids();

		const replaceConfig = resReplaceConfigs && resReplaceConfigs[sceneFile];
		await scene.loadResGroup('preload', replaceConfig, progress);

		if(this.currentScene){
			this.unmountScene(this.currentScene);
		}

		this.currentScene = scene;
		this.mountScene(scene);

		scene.loadResGroup('delay', null, progress);
	}

	/**
	 * 装载场景
	 * @param scene
	 */
	private mountScene(scene){
		engine.pause();
		scene.setup(engine.root);
		engine.start();
	}

	/**
	 * 卸载场景
	 * @param scene
	 */
	private unmountScene(scene){
		engine.pause();
		cleanEntity(scene.root);
		engine.assetsManager.destroyRes(this.resUUIDs);
	}

	/**
	 * 加载场景资源
	 * @param url url
	 * @param uuid 唯一名
	 * @param cache 是否缓存
	 * @param config
	 * @return Promise<any> 资源
	 */
	private async loadScene(url, uuid?, cache = false, config?) {
		const sceneConfig = await engine.assetsManager.loadJson5(url);

		const scene = new Scene(engine);
		scene.initByConfig(sceneConfig);
		return scene;
	}
}

