/** backgroundAnimation 
 * 
 *  version 1.0
 *  
 * 
 * This is a plugin for jQuery
 * Tested on version 1.4
 * 
 * The plugin extends the jQuery framework with another animation feature.
 * To use this plugin correctly, you need an image, that contains all
 * aniamtion images in it, because it animates by changing the background-position (Y-Axis) css property
 * 
 *  
 * Usage:
 * 
 * Preparing the element which contains the animation (e.g. a div-tag):
 * 				$("#anidiv").css({height:"90px",width:"130px",display:"inline-block"});
 * and must linked with the animation object:
 * 				
 * 				$("#anidiv").bga_object();
 * 
 * now we can control the animation whit these functions:
 * 				
 * 				$("#anidiv").bga_start(options);	
 * 
 * *****************************************************************************************
 * options are:
 * 		image:"img/ani.png", //the animation-image
 *		offset:100,//the height of each animation-frame
 *		repeat:0, //loops
 *		startframe:0,//animation startframe
 *		endframe:10, //animation endframe
 * 		timeout:50, // waiting time between each frame in ms
 *		delay_first:1000, //time after the animation starts
 *		delay:0, //time each loop pauses before continue
 *		reverse:false //if true: the animation goes from start to end, then reverse
 * 				
 * 				$("#anidiv").bga_object([options]);  //links an element with a animation object if not already set; this must 
 * 				$("#anidiv").bga_stop();			 //stops the animation
 * 				$("#anidiv").bga_start(options);	 //starts the animation
 * 				$("#anidiv").bga_setFrame(x,o);	     //sets the animation to frame x, the height of each frame is o		
 *				$("#anidiv").bga_getFrame();		 //returns the current frame, .bga_stop() will not reset getCurrentFrame()
 *				$("#anidiv").bga_continue(options);	 //same as .bga_play(options), but startframe will set to getCurrentFrame(), startframe default is 0
 *				$("#anidiv").bga_unlink();			 //unlinks the animation-object from element
 *				$("#anidiv").bga_getObject();		 //returns the animation-object
 *				$("#anidiv").bga_onFrame(x,f);		 //executes the callback f on x
 *				$("#anidiv").bga_clearFrameFunctions //deletes all onFrame entries
 *
 * *****************************************************************************************
 * 
 * IMPORTANT NOTES:
 * 
 * Pay attention with repeat, reverse and continue
 * 
 * you shoult set start/endframe in start/stop functions especially if you use continue and reverse.
 * 
 * @author Philipp Hock
 */


$.fn.bga_stop = function(){
	var elem=$(this);
	if(elem.data("animationObject")!=null){
		var ani = elem.data("animationObject");
		ani.stop();	
	}
	return elem;
};

$.fn.bga_setFrame = function(frame,offset){
	var elem=$(this);
	
	var obj=elem.bga_getObject();
	if(obj!=null){
		
		var off=offset;
		if(off==undefined){
			off=obj.getOffset();
		}
		obj.setFrame(frame,offset);	
	}
	
	return elem;

};

$.fn.bga_getFrame = function(){
	var elem=$(this);
	if(elem.data("animationObject")!=null){
		var ani = elem.data("animationObject");
		return ani.getCurrentFrame();	
	}
	
};

$.fn.bga_continue = function(opt){
	var elem=$(this);
	var frame=elem.bga_getFrame();
	elem.bga_setFrame(frame);
	elem.bga_start(opt,true);
};

$.fn.bga_object = function(options){
	this.each(function(){
		var elem=$(this);
		if(elem.data("animationObject")==null){
			var ani = new animationObject(elem,options);
			elem.data("animationObject",ani);
		}
	});
			
	//return $(this).data("animationObject");
	return $(this);
	
};
$.fn.bga_onFrame=function(x,do_){
	this.each(function(){
		var obj=$(this).bga_getObject();
		obj.onFrame(x,do_);	
	});	
};
$.fn.bga_clearFrameFunctions=function(){
	this.each(function(){
		var obj=$(this).bga_getObject();
		obj.frameFunctionArray.length = 0;
	});
};

$.fn.bga_getObject = function(){
	var elem=$(this);
	return elem.data("animationObject");
};
$.fn.bga_unlink = function(){
	elem.removeData("animationObject");
};
$.fn.bga_start = function(options,continued){
	var elem=$(this);
	if(elem.data("animationObject")!=null){
		var ani = elem.data("animationObject");
		ani.start(options,continued);
	}
	return elem;	
};

function animationObject(el,opt){
	var _self= this;
	this.elem=el;
	this.options=opt;
	this.frameFunctionArray=new Array(0);
	this.defaults = {  
        image:"img/ani.png", 
		offset:100,
		repeat:0,
		endframe:10,
		startframe:0,
		timeout:50,
		delay_first:1000,
		delay:0,
		reverse:false
				
    };
	//_self.options =  $.extend(this.defaults,_self.options);
	
	this.options =  $.extend(this.defaults,this.options);
	this.getOffset = function(){
		return this.options.offset;
	};

	
	this.timer=null;

			//timeline functions
			this.inprogress=false;
			
			this.stop = function(){
				if(_self.timer!=null){
					clearTimeout(_self.timer);	
				}
				
				this.stopthat=true;
				this.inprogress=false;
			};

			this.getCurrentFrame=function(){
				return this.step_;
			};
			
			this.elem.css({backgroundImage:"url("+this.options.image+")",backgroundRepeat:"no-repeat" } );
			this.step_=this.options.startframe;
			this.vz=1;
			this.repeat_run=false;
			
			this.max=this.options.endframe;
			if(this.options.startframe>this.options.endframe){
				this.max=this.options.startframe;
			}
			
			this.start=function(options,continued){
				
				if(options!=null){
					_self.options =  options;
					_self.options =  $.extend(this.defaults,_self.options);	
				}
				
				
				_self.stopthat=false;				
				var delf=this.options.delay_first;			
				if(typeof continued=='undefined'){
					_self.step_=_self.options.startframe;
					_self.loopsleft = _self.options.repeat;
					this.repeat_run=false;
				}else{
					delf=0;
				}
				if(typeof _self.loopsleft=='undefined'||_self.loopsleft==0){
					_self.loopsleft = _self.options.repeat;
					
				}
				if(this.step_==this.options.endframe){
					this.step_=0;
				}
				
				this.max=this.options.endframe;
				if(this.options.startframe>this.options.endframe){
					this.max=this.options.startframe;
				}
				if(_self.getCurrentFrame()>this.options.endframe){
					this.vz=-1;	
				}else{
					this.vz=1;
				}
				timer=setTimeout(this.animate,delf);
				
			};

			
			this.animate = function(){
				

				

				if(_self.stopthat){
					return;
				}
				var callback = _self.frameFunctionArray[_self.step_];
				_self.step_+=_self.vz;	
				
				if(typeof callback!='undefined'){
						callback(_self.elem);
						
				}
				_self.setFrame(_self.step_,_self.options.offset);		
				
				//end of aninmation
				if(_self.step_==_self.options.endframe){
					
					if(_self.options.reverse){
						_self.repeatRUN();
						if(_self.repeat_run){
							_self.timer=setTimeout(_self.animate,_self.options.timeout);	
							return;
						}
						
					}
					//_self.step_=_self.options.startframe;
					if(_self.loopsleft>0){
						
						_self.loopsleft--;	
					}
				
					if(_self.loopsleft!=0){
						_self.step_=_self.options.startframe;
						setTimeout(_self.animate,_self.options.delay);
					}
					return;	
				}else{
					_self.timer=setTimeout(_self.animate,_self.options.timeout);
				}

		};
		
		this.repeatRUN = function(){
				var ne=_self.options.startframe;
				_self.options.startframe=_self.options.endframe;
				_self.options.endframe=ne;
				_self.vz*=-1;
				_self.repeat_run=!_self.repeat_run;
		};
		
		this.setFrame=function(frame,offset){
			
			var npos=offset*frame;
			_self.step_=frame;
			_self.elem.css({backgroundPosition:"0px -"+npos+"px"});	
		};
		
		this.onFrame=function(x,f){
			this.frameFunctionArray[x]=f;
		};
	
	

}

