/**
 * Created by rockyl on 2018-11-30.
 */

import {Sheet} from "./Sheet";

const animationMap = {};
const animDataMap = {};
const textureMap = {};

/**
 * 获取一个帧动画资源
 * @param name
 */
export function getFrameAnimation(name): FrameAnimation {
	let animation: FrameAnimation = animationMap[name];
	if (!animation) {
		animation = animationMap[name] = new FrameAnimationImpl(name);
		animation.fillMcData(name);
	}

	return animation;
}

/**
 * 放置帧动画图片和数据
 * @param img
 * @param data
 */
export function putFrameAnim(img, data) {
	const {mc, res} = data;

	let sheet: Sheet = new Sheet(img, res);

	for (let key in mc) {
		const animData = animDataMap[key] = mc[key];
		animData.sheet = sheet;
	}
}

/**
 * 帧动画资源
 */
export interface FrameAnimation {
	/**
	 * 填充帧数据
	 * @param name
	 */
	fillMcData(name);

	/**
	 * 获取帧率
	 */
	readonly fps: number;
	/**
	 * 获取所有帧标签
	 */
	readonly labels: any[];

	/**
	 * 获取帧数
	 */
	readonly frameCount: number;

	/**
	 * 根据名字获取帧标签
	 * @param name
	 */
	getLabel(name): any;

	/**
	 * 获取帧
	 * @param frameIndex
	 */
	getFrame(frameIndex): any;

	/**
	 * 销毁自身
	 */
	destroy()
}

/**
 * 帧动画资源实现
 */
export class FrameAnimationImpl implements FrameAnimation {
	private readonly _name: string;
	private _animData;

	constructor(name) {
		this._name = name;
	}

	get name(): string {
		return this._name;
	}

	fillMcData(name) {
		const animData = animDataMap[name];
		if (animData) {
			this._animData = animData;
		} else {
			console.warn(`anim data [${name}] is not exist`)
		}
	}

	get fps(): number {
		return this._animData.frameRate;
	}

	get labels(): any[] {
		return this._animData.labels;
	}

	get frameCount(): number {
		return this._animData.frames.length;
	}

	getLabel(name): any {
		let result;
		for (let label of this._animData.labels) {
			if (label.name == name) {
				result = label;
				break;
			}
		}

		return result;
	}

	getFrame(frameIndex): any {
		const {_animData,} = this;

		let texture, frameData;
		if (_animData) {
			const {frames} = _animData;
			frameData = frames[frameIndex];
			if (frameData) {
				const res = frameData.res;
				texture = textureMap[res];
				if (!texture) {
					texture = textureMap[res] = _animData.sheet.getTexture(res);
				}
			}
		}
		return {
			texture,
			data: frameData,
		};
	}

	destroy() {
		this._animData = null;
	}
}
