/**
 * Created by rockyl on 2018/11/23.
 */

import {Entity, traverse, traversePostorder} from "./Entity";
import {injectProp} from "../tools/utils";
import {setupContext as setupInteractContext} from "./context/InteractContext";
import {clear, ScaleMode, setupContext as setupRenderContext} from "./context/RenderContext";
import './requestAnimationFrame';

/**
 * 默认配置
 */

let options: any = {
	fps: 60,
	designWidth: 750,
	designHeight: 1334,
	scaleMode: ScaleMode.FIXED_WIDTH,
};

let root: Entity;

let _flush = 0, _currentFlush = 0;
let tsStart, tsLast;
let lastFPS = 0;

/**
 * 装配引擎
 * @param _options
 */
export function setup(_options?) {
	injectProp(options, _options);

	const {canvas, designWidth, designHeight, scaleMode, modifyCanvasSize} = options;

	let canvasElement = typeof canvas == 'object' ? canvas : document.getElementById(canvas);

	setupInteractContext({
		canvas: canvasElement,
		touchHandler: {
			onTouchBegin,
			onTouchMove,
			onTouchEnd,
		}
	});
	setupRenderContext({
		canvas: canvasElement,
		designWidth,
		designHeight,
		scaleMode,
		modifyCanvasSize,
	});

	root = new Entity('root');
	root._restrict();
}

/**
 * 开始引擎
 */
export function start() {
	root.enabled = true;

	tsStart = Date.now();
	startTick();
}

/**
 * 暂停引擎
 */
export function pause() {
	root.enabled = false;

	stopTick();
}

/**
 * 获取根Entity
 */
export function getRoot(): Entity {
	return root;
}

/**
 * 获取当前帧率
 */
export function getFPS() {
	return lastFPS;
}

/**
 * 开始时钟
 */
function startTick() {
	_flush = 60 / options.fps - 1 >> 0;
	if (_flush < 0) {
		_flush = 0;
	}

	requestAnimationFrame(flush);
}

/**
 * 停止时钟
 */
function stopTick() {

}

let tsLast2;

/**
 * 时钟触发
 */
function flush(tsNow): void {
	if (_flush == 0) {
		onFrameTick(tsNow);
	} else {
		if (_currentFlush == 0) {
			onFrameTick(tsNow);
			_currentFlush = _flush;
		} else {
			_currentFlush--;
		}
	}

	requestAnimationFrame(flush);
}

function onFrameTick(tsNow) {
	clear();
	const tsNow2 = Date.now();
	lastFPS = Math.floor(1000 / (tsNow - tsLast));
	tsLast = tsNow;
	tsLast2 = tsNow2;
	const ts = tsNow - tsStart;
	traverse(root, function (child) {
		if (!child.isFree && child.enabled) {
			child.onUpdate(ts);
		} else {
			return true;
		}
	}, -1, true, function (current) {
		current.afterUpdate();
	});
	//const tsPass = Date.now() - tsNow;
}

/**
 * 代理出来的onTouchBegin方法
 * @param event
 */
function onTouchBegin(event) {
	traversePostorder(root, function (child) {
		return child.onInteract(0, event);
	})
}

/**
 * 代理出来的onTouchMove方法
 * @param event
 */
function onTouchMove(event) {
	traversePostorder(root, function (child) {
		return child.onInteract(1, event);
	})
}

/**
 * 代理出来的onTouchEnd方法
 * @param event
 */
function onTouchEnd(event) {
	traversePostorder(root, function (child) {
		return child.onInteract(2, event);
	})
}