/**
* MikuMikuDance VMD形式の再生制御
*
* @author b2ox
*/
package org.b2ox.pv3d.MikuMikuDance
{
	import org.b2ox.betweenas3.FuncTween;
	import org.libspark.betweenas3.BetweenAS3;
	import org.libspark.betweenas3.tweens.ITween;

	/**
	 * 再生制御
	 */
	public class VMDControllerMix implements IVMDController
	{
		private var _ctr1:IVMDController;
		private var _ctr2:IVMDController;
		private var _tween:ITween;
		private var _counterTween:ITween;
		private var _updaterTween:FuncTween;

		/**
		 * IVMDControllerを2つ取り、ctr1, ctr2の順に適用を行うコントローラを返す
		 * 長さが違う場合は長い方を超えない回数だけ短い方を繰り返す
		 * @param	ctr1 
		 * @param	ctr2
		 */
		public function VMDControllerMix(ctr1:IVMDController, ctr2:IVMDController):void
		{
			this._ctr1 = ctr1;
			this._ctr2 = ctr2;
			var n:int;
			if ( ctr1.counterTween == null ) throw new Error("引数ctrl1が不正です。");
			if ( ctr2.counterTween == null ) throw new Error("引数ctrl2が不正です。");
			var d1:Number = ctr1.counterTween.duration;
			var d2:Number = ctr2.counterTween.duration;
			var tw1:ITween, tw2:ITween;
			if ( d1 < d2 )
			{
				n = Math.floor(d2 / d1);
				tw1 = (n == 1) ? ctr1.counterTween.clone() : BetweenAS3.repeat(ctr1.counterTween, n);
				tw2 = ctr2.counterTween.clone();
			} else {
				n = Math.floor(d1 / d2);
				tw1 = ctr1.counterTween.clone();
				tw2 = (n == 1) ? ctr2.counterTween.clone() : BetweenAS3.repeat(ctr2.counterTween, n);
			}
			_counterTween = BetweenAS3.parallel(tw1, tw2);

			_updaterTween = FuncTween.create(function (time:Number):void { applyCurrent(); }, _counterTween);

			var _reseterTween:FuncTween = FuncTween.create(function (time:Number):void { resetParams(); }, _counterTween);
			var _applyerTween:FuncTween = FuncTween.create(function (time:Number):void { applyPose(); }, _counterTween);

			_tween = BetweenAS3.parallel(_reseterTween, _counterTween, _updaterTween, _applyerTween);
		}

		//-------------------------------------------------
		// 再生用のAPI

		public function get tween():ITween { return _tween; }
		public function get counterTween():ITween { return _counterTween; }
		public function get updaterTween():ITween { return _updaterTween; }

		public function get looping():Boolean { return ! _tween.stopOnComplete; }
		public function set looping(loop:Boolean):void { _tween.stopOnComplete = ! loop; }

		public function play():void { _tween.play(); }
		public function stop():void { _tween.stop(); }
		public function togglePause():void { _tween.togglePause(); }
		public function gotoAndPlay(pos:Number):void { _tween.gotoAndPlay(pos); }
		public function gotoAndStop(pos:Number):void { _tween.gotoAndStop(pos); }

		public function get playing():Boolean { return _tween.isPlaying; }

		public function update():void
		{
			resetParams();
			applyCurrent();
			applyPose();
		}

		public function resetParams():void { _ctr1.resetParams(); }
		public function applyPose():void { _ctr1.applyPose(); }

		/**
		 * 現在フレームのパラメータを適用する
		 */
		public function applyCurrent():void { _ctr1.applyCurrent(); _ctr2.applyCurrent(); }
	}
}
