/**
 * Created by rocky.l on 2017/1/19.
 *
 * 场景导航器
 */

import {Entity, EventEmitter} from 'scilla'
import {INavigatorDelegate, NavigatorAction, StackNavigator} from "./StackNavigator";

const showLog = false;

export const VIEW_WILL_ENTER: string = 'VIEW_WILL_ENTER';
export const VIEW_DID_ENTER: string = 'VIEW_DID_ENTER';
export const VIEW_WILL_LEAVE: string = 'VIEW_WILL_LEAVE';
export const VIEW_DID_LEAVE: string = 'VIEW_DID_LEAVE';

export interface INavigatorViewBase {
	onWillMount(last: string, action: NavigatorAction, parameters: any): Promise<any>;

	onWillUnMount(next: string, action: NavigatorAction, parameters: any): Promise<any>;

	onWillEnter(last: string, action: NavigatorAction, parameters: any): Promise<any>;

	onDidEnter(last: string, action: NavigatorAction, parameters: any): void;

	onWillLeave(next: string, action: NavigatorAction, parameters: any): Promise<any>;

	onDidLeave(next: string, action: NavigatorAction, parameters: any): void;
}

export class VirtualNavigator extends EventEmitter implements INavigatorDelegate {
	stack: StackNavigator;

	protected _currentName: string;
	protected _currentView: INavigatorViewBase;

	protected _classDic: any;
	protected _container: Entity;

	constructor(container) {
		super();

		this._container = container;
		this._classDic = {};

		this.stack = new StackNavigator(this);
	}

	register(alias: string, childName: string, componentDef): void {
		this._classDic[alias] = {
			childName,
			componentDef,
		};
	}

	get currentView(): INavigatorViewBase {
		return this._currentView;
	}

	get currentName(): string {
		return this._currentName;
	}

	protected getViewInstanceByName(name: string): INavigatorViewBase {
		let {childName, componentDef,} = this._classDic[name];
		let scene: Entity = this._container.getChildrenByName(childName)[0];
		let component:any = scene.getComponent(componentDef);
		return component;
	}

	/**
	 * 栈入实现
	 * @param name
	 * @param last
	 * @param action
	 * @param parameters
	 * @returns {Promise<void>}
	 */
	async onEnter(name: string, last: string, action: NavigatorAction, parameters: any) {
		let view: INavigatorViewBase = this.getViewInstanceByName(name);
		this._currentView = view;
		this._currentName = name;
		await view.onWillMount(last, action, parameters);
		if (showLog) console.log(name + ' will enter.');
		this.emit(VIEW_WILL_ENTER, {name, last, action, parameters});
		await view.onWillEnter(last, action, parameters);
		if (showLog) console.log(name + ' did enter.');
		this.emit(VIEW_DID_ENTER, {name, last, action, parameters});
		view.onDidEnter(last, action, parameters);
	}

	/**
	 * 栈出实现
	 * @param name
	 * @param next
	 * @param action
	 * @param parameters
	 * @returns {Promise<void>}
	 */
	async onLeave(name: string, next: string, action: NavigatorAction, parameters: any) {
		let view: INavigatorViewBase = this.getViewInstanceByName(name);
		await view.onWillUnMount(name, action, parameters);
		if (showLog) console.log(name + ' will leave.');
		this.emit(VIEW_WILL_LEAVE, {name, next, action, parameters});
		await view.onWillLeave(next, action, parameters);
		if (showLog) console.log(name + ' did leave.');
		this.emit(VIEW_DID_LEAVE, {name, next, action, parameters});
		view.onDidLeave(next, action, parameters);
	}

	/**
	 * 当收到错误实现
	 * @param error
	 */
	onError(error: Error) {

	}
}
