/*--------------------------------------------------------------

__  __ `__ \  _ \  ___/  __ `/_  __ \  __ \
_  / / / / /  __/ /__ / /_/ /_  / / / /_/ /
/_/ /_/ /_/\___/\___/ \__,_/ /_/ /_/\____/

	Version: 1.1
	
	Purpose: 	Sequencer for linear function calls as a chain reaction.
				Mostly used to support delays, like data transfert or animations.
	
	Usage:		_aS = new ActionStack(this);
				var stack = [];
				stack[stack.length] = {func: this.play, wait: true};
				stack[stack.length] = {func: this.myFunction, param: ["param1","param2", ...]}; 
				stack[stack.length] = {trg: this._aS, func: this._aS.setProp, param: [targetMc, "_alpha", 0], wait: true};
				stack[stack.length] = {trg: this._aS, func: this._aS.doDelay, param: [24, "frame"]};
				_aS.start(stack);
					
	
	Modified On: 2009/08/16
	
	Created by:	Patrick Picher
				patrickpicher.com@gmail.com
							
	Copyright © 2009 Patrick Picher							
	
	=Notes====
	Very DIRTY, needs a good clean up and more helper/wrapper functions
	
	1.2 	- use of startUp instead of start
--------------------------------------------------------------*/

var ActionStack = new Class({
    initialize: function(pTrg){
		this._trg = pTrg;
		this._actionStack = [];
    },
	
	next: function(){
		if(this._actionStack.length > 0){
			var act = this._actionStack.shift();
			
			act.trg = (act.trg) ? act.trg : this._trg;
			act.param = (act.param) ? act.param : [];
			
			if(act.asfunc!=null){
				if( (typeof act.asfunc) != 'string') throw('ActionStack : asfunc must be a string');
				act.func = this[act.asfunc];
				act.trg = this;
			}else if( (typeof act.func) == 'string' ){
				act.func = act.trg[act.func]; //legacy	
			}
			
			
			
			if(act.wait) act.param.push(this);
			
			act.func.apply(act.trg,act.param);
			
			if(!act.wait && this._actionStack.length > 0) this.next(); 
		}
	},	
	
	start: function(aS, callnext){
		if(callnext != null){
			aS[aS.length] = {trg:callnext, func:callnext.next};
		}
		this.setStack(aS);
		this.next();
	},
	
	stop: function(){
		this._actionStack = [];
	},
	
	//-- Private
	//------------------------------------------------------
	setStack: function(ar){
		this._actionStack = [];
		var lg=ar.length
		for(var i=0;i<lg;i++){
			this._actionStack[i] = ar[i];
		}
	},	
	
	//-- Set Shortcuts
	//------------------------------------------------------
	setProp: function(pTrg,pProp,pV){
		pTrg[pProp] = pV;
	},
	setStyles: function(pTrg,pOpt){
		if(pTrg.setStyles == null) throw('ActionStack.setStyles(el, opt) : Trg is not a Mootools Element');
		pTrg.setStyles(pOpt);
	},
		
	
	//-- Animation
	//------------------------------------------------------
	doDelay: function(duration, callnext){
		setTimeout(function(){callnext.next()}, duration);
	},
	
	
	
	doTween: function(el, opt, callnext){
		if(opt==null) throw('doTween(el, opt [, callnext]) : Missing opt');
		if(opt.from==null && opt.to==null) throw('doTween(el, opt [, callnext]) : Missing opt.to or opt.from property');
		if(opt.property==null) throw('doTween(el, opt [, callnext]) : Missing opt.property property');

		opt.type = (opt.type!=null) ? opt.type : 'Tween';
		opt.from = (opt.from!=null) ? opt.from : el.getStyle(opt.property);
		opt.to = (opt.to!=null) ? opt.to : el.getStyle(opt.property);
		
		if(callnext) opt.onComplete = function(){callnext.next();};
		
		var fx = new Fx[opt.type](el,opt);
		
		fx.start(opt.from,opt.to);
		
	}, 
	
	
	//-- Debug
	//------------------------------------------------------
	jsAlert: function(mV){
		alert(mV);	
	},
	
	empty: function(){}
	
});
