import MEvent from "../Component/MEvent";

export default class MTimer {
	public static init() {
		startTime = Date.now();
		engine.gameStage.addEventListener(engine.Event.ENTER_FRAME, onUpdate, MTimer);
		document.addEventListener("visibilitychange", onVisibilityChange);
	}

	public static destroy() {
		_onFrame.clear();
		engine.gameStage.removeEventListener(engine.Event.ENTER_FRAME, onUpdate, MTimer);
		document.removeEventListener("visibilitychange", onVisibilityChange);
	}

	/**
	 * 帧间隔
	 */
	public static get deltaTime(): number {
		return _deltaTime;
	}

	/**
	 * 帧间隔系数：当前帧间隔与标准帧间隔（60帧）的比值
	 */
	public static get dtFactor() {
		return MTimer.deltaTime / DefaultDeltaTime;
	}

	/**
	 * 注册帧回调函数
	 */

	/*  public static get onFrame(): MEvent<(dt: number) => void> {
			 return _onFrame;
	 } */

	public static onFrame(key: string, callback: (dt: number) => void, thisObj?: any) {
		if (key) {
			if (onFrameCaches[key]) {
				_onFrame.remove(onFrameCaches[key].callback, onFrameCaches[key].thisObj);
				delete onFrameCaches[key];
			}

			onFrameCaches[key] = {
				callback: callback,
				thisObj: thisObj
			};
		}
		_onFrame.add(callback, thisObj);
	}

	public static removeOnFrame(key: string) {
		if (onFrameCaches[key]) {
			_onFrame.remove(onFrameCaches[key].callback, onFrameCaches[key].thisObj);
			delete onFrameCaches[key];
		}
	}

	/**
	 * 设置帧计时器
	 */
	public static setFrameTimer(frame: number, onTimeOut: () => void) {
		let count = 0;
		const callback = () => {
			if (count >= frame) {
				onTimeOut();
				timerTickEvent.remove(callback);
			} else {
				count += MTimer.dtFactor;
			}
		}
		timerTickEvent.add(callback);
	}
}

const onFrameCaches: {
	[key: string]: {
		callback: (dt: number) => void,
		thisObj?: any
	}
} = {};

const _onFrame: MEvent<(dt: number) => void> = new MEvent();
const timerTickEvent: MEvent<() => void> = new MEvent();
const DefaultDeltaTime = 1000 / 60;
let _deltaTime: number = 0;
let startTime = 0;
let lastTime = 0;
let curTime = 0;

function updateDeltaTime() {
	lastTime = curTime;
	curTime = Date.now() - startTime;
	_deltaTime = curTime - lastTime;
}

function onVisibilityChange() {
	if (document.visibilityState == "visible") {
		curTime = Date.now() - startTime;
	}
}

function onUpdate() {
	updateDeltaTime();
	_onFrame.call(MTimer.deltaTime);
	timerTickEvent.call();
}