var Ticker = new Class({

    options: {
		container			: null,
		fxoptions			: {duration:500},
		size				: [0,0],
		scrollType			: "vertical"
	},
	
	initialize: function(options){
		this.setOptions(options)
	
		this.scrollFx		= null; 
		this.scrollDiv 		= null;
		this.container 		= $(this.options.container) || null;
		this.scrollType		= (this.options.scrollType.toLowerCase() == "vertical") ? "vertical" : "horizontal";
		this.size 			= this.options.size;
		this.reverse		= (this.options.reverse == true);
		this.interval		= parseInt(this.options.interval) || 2000;
		this.fxOptions		= this.options.fxoptions;
		this.items			= [];
		this.index 			= 0;
		this.numItems 		= 0;
		this.maskWidth 		= 0;
		this.maskHeight		= 0;
		this.timer			= 0;
				
		if (this.container != null){
			this.maskWidth 			= this.size[0] || "auto";
			this.maskHeight			= this.size[1] || "auto";
			this.items				= this.container.getChildren();
			this.numItems 			= this.items.length;
			
			// create subContainer div
			this.scrollDiv = new Element("div",{"id":"app_scrolldiv","style":"width:"+this.maskWidth+"px,height:"+this.maskHeight+"px"}),

			// moving all children of container into scrollDiv
			this.scrollDiv.adopt(this.container.getChildren());

			// injecting scrolDiv into DOM
			this.container.adopt(this.scrollDiv);
			
			// create scroll Effect
			this.scrollFx 			= new Fx.Tween(this.scrollDiv,this.fxOptions);
			this.scrollFx.running	= false;
			
			// set divs properties
			this.container.setStyle("width",this.maskWidth)
			this.container.setStyle("height",this.maskHeight)
			this.container.setStyle("overflow","hidden");
			//this.scrollDiv.setStyle("overflow","hidden");	// hack for IE 7 don't delete
//			this.scrollDiv.setStyle("height","auto"); 		// hack for IE 7 don't delete


/******* EVENTS ASSIGNMENT **********/
			this.scrollFx.addEvent("complete",this.onAnimationComplete.bind(this));
			this.scrollDiv.addEvent("mouseover",this.pause.bind(this));
			this.scrollDiv.addEvent("mouseout",this.resume.bind(this));
			
/******* /EVENTS ASSIGNMENT **********/
		
			
			// setting float of elements
			if (this.scrollType == "horizontal") {
				var w = 0;
				this.scrollDiv.getChildren().each(function(item,index){
													item.setStyle("float","left");
													w+= item.getSize().x;
													// catch also margins and paddings
													wmar = item.getStyle("margin-left").toInt() + item.getStyle("margin-right").toInt();
													wpad = item.getStyle("padding-left").toInt() + item.getStyle("padding-right").toInt();													
												},this);

				/* ------------------------- PATCH --------------------------
				 	THIS IS A PATCH AND COULDN'T FIND A BETTER WAY TO SOLVE THE PROBLEM THAT 
				 	SOMETIMES LAST ELEMENT IS NOT FLOATING LEFT. THIS IS BECAUSE THE GETSIZE() METHOD IS NOT GIVING PROPER SIZE WHEN "WIDTH" PROPERTY IS NOT SET, AND EVEN 
					SUMMING PADDINGS AND MARGINS VALUES, IT HAPPENS! SO I HAVE TO DOUBLE THE SIZE AND I'M SURE TO AVOID THIS!					
				*/
				w*= 2;
				// ----------------------- END OF PATCH ---------------------
				
				this.scrollDiv.setStyle("width",w);
			}

			// ---> START APPLICATION
			//var hasScrollH = (this.scrollType == "horizontal" && this.scrollDiv.getSize().x > this.container.getSize().x) 	? true : false;
			//var hasScrollV = (this.scrollType == "vertical" && this.scrollDiv.getSize().y > this.container.getSize().y) 	? true : false;
			
			if (this.numItems > 3 /*&& (hasScrollH || hasScrollV) */){
				if (this.reverse) this.timer = this.prev.bind(this).delay(this.interval);
				else this.timer = this.next.bind(this).delay(this.interval);
			} 

		}

	},
	
	switchItems: function(direction){
		
		if (direction == 1) {
			this.scrollDiv.getFirst().inject(this.scrollDiv.getLast(),"after");
			this.scrollFx.set((this.scrollType == "horizontal") ? "margin-left": "margin-top",0);
		}
		else {
			this.scrollDiv.getLast().inject(this.scrollDiv.getFirst(),"before");
			offset = (this.scrollType == "horizontal") ? -(this.scrollDiv.getChildren()[1].offsetLeft - this.scrollDiv.getFirst().offsetLeft) : -(this.scrollDiv.getChildren()[1].offsetTop - this.scrollDiv.getFirst().offsetTop);
			this.scrollFx.set((this.scrollType == "horizontal") ? "margin-left": "margin-top",offset);
		}
	},
	prev: function(){
		this.move(-1);
	},
		
	next: function(){
		this.move(1);
	},

	move: function(direction){
		if(this.scrollFx != null && !this.scrollFx.running){
			$clear(this.timer);
			if (direction == -1) {
				var index = (this.index-1 < 0) ? this.numItems-1 : this.index-1;
				
				if (
						(this.scrollType == "vertical" && this.items[index].offsetTop > this.items[this.index].offsetTop) ||
						(this.scrollType == "horizontal" && this.items[index].offsetLeft > this.items[this.index].offsetLeft)
					) this.switchItems(-1);
				offset = 0;
				this.index = index;
			}
			else {
				if (
						(this.scrollType == "vertical" && this.scrollDiv.getFirst().getPosition(this.container).y < 0) ||
						(this.scrollType == "horizontal" && this.scrollDiv.getFirst().getPosition(this.container).x < 0)
					) this.switchItems(1);
				this.index = (this.index+1 >= this.numItems-1) ? 0 : this.index+1;
				offset = (this.scrollType == "horizontal") ? -(this.scrollDiv.getChildren()[1].offsetLeft - this.scrollDiv.getChildren()[0].offsetLeft): -(this.scrollDiv.getChildren()[1].offsetTop - this.scrollDiv.getChildren()[0].offsetTop);
			}

			this.scrollFx.running = true;
			this.scrollFx.start((this.scrollType == "horizontal") ? "margin-left": "margin-top",offset);
		}		
	},

	
/******* EVENTS DECLARATION **********/
onAnimationComplete : function(){
	this.scrollFx.running = false;
	if (this.reverse) this.timer = this.prev.bind(this).delay(this.interval);
	else this.timer = this.next.bind(this).delay(this.interval);
},
pause:function(){
	$clear(this.timer);
	this.scrollFx.pause();
},
resume:function(){
	if(this.scrollFx.running) this.scrollFx.resume();
	else this.onAnimationComplete();
}
/******* /EVENTS DECLARATION **********/
});
Ticker.implement(new Options, new Events);


