// Object to animate AnimationObjects, AnimationGroups and AnimationChains

var WebElements;

if(!WebElements) WebElements = {};

WebElements.Animator = function(animation_chain, fps, callback) {
	
	this.animation_chain = animation_chain;
	this.animation_chain_index = 0;
	
	this.fps = null;
	this.setFps(fps);
	
	this.callback = null;
	this.setCallback(callback);
	
	this.start_time = null;
	this.current_time = null;
	this.running = false;
	this.timeout = null;
	this.interval = null;
}

WebElements.Animator.prototype.setOptions = function(options) {
	
	if(options) 
	{
		for(var optionname in options)
		{
			this[optionname] = options[optionname];
		}
		
		return true;
	}
	
	return false;
}

WebElements.Animator.prototype.setFps = function(fps) {
	
	this.fps = (fps != null && fps > 0) ? fps : 60;
	
	this.interval = Math.round(1000 / this.fps);
}

WebElements.Animator.prototype.setCallback = function(callback) {
	
	if(callback != null && typeof callback == "function")
	{
		this.callback = callback;
		
		return true;
	}
	
	return false;
}

WebElements.Animator.prototype.addCallback = function(callback) {
	
	if(callback != null && typeof callback == "function")
	{
		var oldcallback = this.callback;
		
		if(this.callback != null && typeof this.callback == "function")
		{
			this.callback = function() { oldcallback(); callback(); };
		}
		else 
		{
			this.callback = callback;
		}
		
		return true;
	}
	
	return false;
}

WebElements.Animator.prototype.getAnimationChain = function() {
	
	return this.animation_chain;
}

WebElements.Animator.prototype.updateTime = function() {
	
	this.current_time = (new Date).getTime();
}

WebElements.Animator.prototype.resetTime = function() {
	
	this.start_time = (new Date).getTime();
}

WebElements.Animator.prototype.start = function() {
	
	if(!this.running) 
	{
		this.running = true;
		
		this.resetTime();
		
		this.animateChain();
		
		return true;
	}
	
	return false;
}

WebElements.Animator.prototype.stop = function() {
	
	if(this.running) 
	{
		clearTimeout(this.timeout);
		
		this.running = false;
		
		this.animation_chain_index = 0;
		
		if(this.callback != null) this.callback();
		
		return true;
	}
	
	return false;
}

WebElements.Animator.prototype.animateChain = function() {

	if(this.animation_chain_index < this.animation_chain.getAnimationCount())
	{
		if(this.animation_chain_index > 0)
			this.animation_chain.deactivateAnimationGroup(this.animation_chain_index - 1);
		
		this.animation_chain.activateAnimationGroup(this.animation_chain_index);
		
		this.resetTime();
		
		this.animateGroup(this.animation_chain.getAnimationGroup(this.animation_chain_index));
		
		this.animation_chain_index++;
	}
	else
	{
		if(this.animation_chain_index > 0)
			this.animation_chain.deactivateAnimationGroup(this.animation_chain_index - 1);
			
		if(this.animation_chain.callback != null) this.animation_chain.callback();
		
		this.stop();
	}
}

WebElements.Animator.prototype.animateGroup = function(animation_group) {
	
	this.updateTime();
	
	var self = this;
	var ready = true;
	
	for(var i = 0; i < animation_group.getAnimationCount(); i++)
	{
		if(animation_group.getAnimationObject(i).getProgress() < 1)
		{
			ready = false;
			
			this.animateStep(animation_group.getAnimationObject(i));
		}
	}
	
	if(ready)
	{
		if(animation_group.callback != null) animation_group.callback();
		
		this.animateChain();
		
		return true;
	}
	
	var next_frame = this.interval - ((new Date).getTime() - this.current_time);
	
	this.timeout = setTimeout(function() { self.animateGroup(animation_group); }, (next_frame < 0) ? 0 : next_frame);
}

WebElements.Animator.prototype.animateStep = function(animation_object) {
	
	animation_object.updateProgress(this.current_time - this.start_time);
	
	this.map(animation_object.element, animation_object.property, animation_object.getValue());
}

WebElements.Animator.prototype.map = function(element, property, value) {
	
	element.style[property] = value;
	
	if(property == "opacity")
	{
		// for MSIE
		element.style["filter"] = "alpha(opacity=" + (value * 100) + ")";
		
		// for older Mozilla browsers
		element.style["-moz-opacity"] = value;
		
		// for Konqueror browsers
		element.style["-khtml-opacity"] = value;
		
		if(value == 1) element.style["filter"] = "";
	}
}
