/**
 * Created by rockyl on 2018-11-30.
 *
 * 帧动画组件
 *
 * todo 倒置播放
 */

import Renderer from "./Renderer";
import {FrameAnimation, ScillaEvent} from "scilla";

/**
 * 帧动画渲染组件
 */
export default class FrameAnimationRenderer extends Renderer {
	/**
	 * 帧动画资源
	 */
	public frameAnimation: FrameAnimation;
	/**
	 * 是否自动播放
	 */
	public autoPlay: boolean = false;
	/**
	 * 帧率
	 * 不设置就读取动画文件的帧率
	 */
	public fps: number = NaN;

	public onComplete: ScillaEvent = new ScillaEvent();
	public onLoopComplete: ScillaEvent = new ScillaEvent();

	private _playing;
	private _startTime;
	private _startFrame;
	private _endFrame;

	private _currentFrameIndex;

	private _startFlag;
	private _loop;
	private _loopCounting;
	private _flag;

	/**
	 * @inheritDoc
	 */
	onAwake() {
		super.onAwake();

		if(this.autoPlay){
			this.play(0, -1);
		}
	}

	/**
	 * @inheritDoc
	 */
	onUpdate(t) {
		if (this._playing) {
			const {frameAnimation, _startFrame, _endFrame, fps} = this;

			if (this._startFlag) {
				this._startFlag = false;
				this._startTime = t;
				this._loopCounting ++;
			}

			const mFPS = isNaN(fps) ? frameAnimation.fps : fps;

			const passTime = t - this._startTime;
			const passFrameCount = Math.floor(passTime / (1000 / mFPS));
			const passFrameInRegion = passFrameCount % (_endFrame - _startFrame + 1);
			this._currentFrameIndex = _startFrame + passFrameInRegion;

			if(passFrameInRegion == 0 && passFrameCount > 0){
				this._currentFrameIndex = _endFrame;
				this.onLoopEnd();
			}
		}

		super.onUpdate(t);
	}

	/**
	 * @inheritDoc
	 */
	onSleep() {
		super.onSleep();
	}

	/**
	 * 当一遍播放结束时
	 */
	onLoopEnd(){
		if (this._loop < 0) {
			this._startFlag = true;
			this.onLoopComplete.invoke();
		} else if (this._loopCounting < this._loop) {
			this._startFlag = true;
			this.onLoopComplete.invoke();
		} else {
			this._playing = false;
			this.onComplete.invoke();
		}
	}

	/**
	 * 播放
	 * @param frame
	 * @param loop
	 * @param force
	 */
	play(frame: number | string = 0, loop: number = 0, force = true) {
		this._loop = loop;
		this._loopCounting = 0;
		if (!this.frameAnimation) {
			return;
		}
		let startFrame = 0, endFrame = this.frameAnimation.frameCount - 1;
		if (typeof frame == 'string') {
			const label = this.frameAnimation.getLabel(frame);
			if (label) {
				startFrame = label.frame - 1;
				endFrame = label.end;
			}
		} else {
			startFrame = frame;
		}
		this._startFrame = startFrame;
		this._endFrame = endFrame;

		this._currentFrameIndex = this._startFrame;

		this._startFlag = true;
		this._playing = true;
	}

	/**
	 * 停止
	 */
	stop() {
		this._playing = false;
	}

	/**
	 * @inheritDoc
	 */
	protected draw() {
		super.draw();

		if (!this.frameAnimation) {
			return;
		}

		const {context, frameAnimation, _currentFrameIndex, bounds} = this;

		const {texture, data} = frameAnimation.getFrame(_currentFrameIndex);

		if (texture) {
			const {img, bounds: {x, y, width: textureWidth, height: textureHeight}} = texture;

			bounds.setTo(data.x, data.y, textureWidth, textureHeight);

			context.drawImage(img, x, y, textureWidth, textureHeight, data.x, data.y, textureWidth, textureHeight);
		}
	}
}
