///<reference path="all.ts"/>
module jg {
	/**
	 * 複数のフレームによってアニメーションを行うSprite。
	 * なおこのクラスでは1枚の画像を複数のフレームに区切って扱う形のみサポートしているため、複数の画像で一つのアニメーションを後世することは出来ない。
	 */
	export class FrameSprite extends Sprite {
		/** 画像一列で何枚の画像が入っているか */
		sep: number;
		/** フレーム */
		frame: number[];
		/** 現在のフレーム番号 */
		fno: number;
		/** アニメーション中かどうか */
		animation: boolean;
		/** アニメーション時間 */
		wait: number;
		/** 繰り返しアニメーションを行うかどうか */
		loop: boolean;
		/** アニメーション完了時に発生するイベント。ループ中は発生しない */
		frameEnded: Trigger;

		/**
		 * コンストラクタ
		 * @param image 画像。1枚の画像にアニメーションパターンがすべて格納されている必要がある
		 * @param srcWidth フレームの横幅
		 * @param srcHeight フレームの縦幅
		 * @param wait アニメーション時間をミリ秒で指定。省略時は200ミリ秒
		 */
		constructor(image:any, srcWidth:number, srcHeight:number, wait?:number) {
			super(image, srcWidth, srcHeight);
			this.sep = Math.floor(this.image.width / this.width);
			var frameCnt = Math.ceil(image.width * image.height) / (srcWidth * srcHeight);
			this.frame = [];
			for (var i=0; i<frameCnt; i++)
				this.frame.push(i);
			this.fno = 0;
			this.animation = false;
			this.wait = wait === undefined ? 200 : wait;
			this.loop = true;
		}	

		/**
		 * フレームを変更し、変更フラグを立てる
		 */
		changeFrame() {
			this.srcX = (this.frame[this.fno] % this.sep) * this.srcWidth;
			this.srcY = Math.floor(this.frame[this.fno] / this.sep) * this.srcHeight;
			this.updated();
		}

		/**
		 * アニメーションを開始する。すでにアニメーション中である場合、noClearの設定含めて無視される
		 * @param noClear 指定した場合、fnoを0にリセットする
		 */
		animate(noClear?:boolean) {
			if (this.animation)
				return true;
			if (! noClear)
				this.fno = 0;
			this.animation = true;
			this.startTimer(this.wait);
		}

		/**
		 * アニメーションを停止する
		 */
		inanimate() {
			if (!this.animation)
				return;
			this.stopTimer(this.wait);
			this.animation = false;
		}

		/**
		 * アニメーション処理を行うコールバック
		 */
		interval() {
			this.fno++;
			if (this.fno >= this.frame.length) {
				if (this.loop) {
					this.fno = 0;
				} else {
					if (this.frameEnded) {
						this.inanimate();
						this.frameEnded.fire();
						return;
					}
				}
			}
			this.changeFrame();
		}
	}
}