(function(window){

function DOMTween(){
	this.initialize.apply(this,arguments);
}
var p = DOMTween.prototype;
	p.property = null;
	p.intervalId = 0;
	p.intervalCompleteId = 0;
	p.style = null;
	p.taskStack = null;
	p.task = {};
	/*constractor
	***********************************************************/
	p.initialize = function(element){
		this.property = {
			target:element,
			x:0,
			y:0,
			alpha:0,
			visible:true,
			interval:10
		}
		this.style = element.style;
		this.taskStack = [];
	}

	/*public functions
	***********************************************************/
	p.to = function(){ this.taskStack.push({func:this.task.to,arg:arguments}); return this; }
	p.set = function(){ this.taskStack.push({func:this.task.set,arg:arguments}); return this; }
	p.wait = function(){ this.taskStack.push({func:this.task.wait,arg:arguments}); return this; }
	p.func = function(){ this.taskStack.push({func:this.task.func,arg:arguments}); return this; }
	p.play = function(){
		this.next();
		return this;
	}
	p.stop = function(){
		this.resetInterval();
		this.taskStack = [];
		return this;
	}
	
	/*private functions
	***********************************************************/
	p.next = function(){
		this.resetInterval();
		if(this.taskStack.length > 0)
		{
			var task = this.taskStack.shift();
			task.func.apply(this,task.arg);
		}
	}
	p.resetInterval = function(){
		clearTimeout(this.intervalId);
		clearTimeout(this.intervalCompleteId);
	}
	p.update = function(props,times,easing)
	{
		var
		currentTime = new Date().getTime() - times[0],
		time = times[1] - times[0],
		that = this,
		key,prop;
		for(key in props)
		{
			prop = props[key];
			this[key](easing.call(this,currentTime,prop[0],prop[1]-prop[0],time));
		}
		if(currentTime < time) this.intervalId = setTimeout(function(){that.update.call(that,props,times,easing)},this.interval());
	}
	p.task.to = function(obj,time,easing){
		var
		key,props = {},
		that = this,
		currentTime = new Date().getTime(),
		times = [currentTime,currentTime + time*1000],
		easing = (typeof easing !== "undefined") ? easing : function(t, b, c, d ) { return c*t/d + b; };
		if(typeof time === "undefined") return this;
		for(key in obj) {
			if(key.indexOf("$") != -1) {
				var key2 = key.replace("$","");
				props[key2] = [this[key2](),obj[key] + this[key2]()];
			}
			else props[key] = [this[key](),obj[key]];
		}
		this.update(props,times,easing);
		this.intervalCompleteId = setTimeout(function(){
			clearTimeout(that.intervalId);
			for(key in props) that[key](props[key][1]);
			that.next();
		},time*1000);
	}
	p.task.set = function(obj){
		var key;
		for(key in obj) {
			if(key.indexOf("$") != -1) {
				var key2 = key.replace("$","");
				this[key2](obj[key] + this[key2]());
			}
			else this[key](obj[key]);
		}
		this.next();
	}
	p.task.wait = function(time)
	{
		var that = this;
		this.intervalCompleteId = setTimeout(function(){
			that.next();
		},time*1000);
	}
	p.task.func = function(func,scope,args)
	{
		if(typeof args !== 'undefined') func.apply(scope,args);
		else func.call(scope);
		this.next();
	}

	/*properties
	***********************************************************/
	p.x = function(value){
		if(typeof value !== "undefined"){
			this.property.x = value;
			this.style.left = value + "px";
			return this;
		}
		else return this.property.x;
	}
	p.y = function(value){
		if(typeof value !== "undefined"){
			this.property.y = value;
			this.property.target.style.top = value + "px";
			return this;
		}
		else return this.property.y;
	}
	p.alpha = function(value){
		if(typeof value !== "undefined"){
			this.property.alpha = value;
			this.style.opacity = value;
			this.style.MsFilter = "alpha(opacity=" + value*100 + ")";
			this.style.filter = "alpha(opacity=" + value*100 + ")";
			this.style.KhtmlOpacity = value;
			this.style.MozOpacity = value;
			return this;
		}
		else return this.property.alpha;
	}
	p.interval = function(value){
		if(typeof value !== "undefined"){
			this.property.interval = value;
			return this;
		}
		else return this.property.interval;
	}
	p.visible = function(value) {
		if (typeof value === "undefined") {
			return this.property.visible;
		} else {
			this.property.visible = value;
			if (value) this.style.display = "block";
			else this.style.display = "none";
			return this;
		}
	}
	
window.DOMTween = DOMTween;

}(window))
