Ext.namespace('Ext.ux');
Ext.ux.Carousel = Ext.extend(Ext.util.Observable, {
	constructor: function(settings){
		//Apply Settings
		Ext.apply(this, settings);
		
		//Register events
		this.addEvents(
			'init'
			,'change'
		);
		
		//Call super
		Ext.ux.Carousel.superclass.constructor.apply(this, arguments);
		
		//Init this component
		this.init();
	}
	
	//Private
	,items: []
	,animating: false
	,interval: null
	,currentIndex: 0
	,outerContainer: null
	
	//Public
	,width: 500
	,height: 500
	,container: null
	,overlay: null
	,nextButton: null
	,previousButton: null
	,selector: ''
	,wait: 5
	,animationDuration: 1 
	,easing: 'bounceOut'
	,autoStart: true
	
	
	,init: function(){
		this.initElements();
		this.initButtons();
		this.initItems();
		
		if(this.autoStart){
			this.start();
		}
		
		//Fire init event
		this.fireEvent('init');
	}
	,initElements: function(){
		this.container = Ext.get(this.container);
		this.overlay = Ext.get(this.overlay);
		this.nextButton = Ext.get(this.nextButton);
		this.previousButton = Ext.get(this.previousButton);
		
		//Create the outer container
		this.outerContainer = Ext.get(Ext.DomHelper.insertBefore(this.container,{
			tag: 'div'
			,style: {
				position: 'relative'
				,width: this.width + 'px'
				,height: this.height + 'px'
				,overflow: 'hidden'
			}
		}));
		
		//Move the container inside the outer container
		this.outerContainer.appendChild(this.container);
		
		//show the container
		if(this.container != null){
			this.container.set({
				style: {
					position: 'relative'
				}
			})
			this.container.show();
		}
	}
	,initItems: function(){
		this.getItems();
	}
	
	,initButtons: function(){
		
		//Add handler for next button
		if(this.nextButton != null){
			this.nextButton.on('click', this.next, this);
		}
		
		//Add handler for previous button
		if(this.previousButton != null){
			this.previousButton.on('click', this.previous, this);
		}
		
		//Pause movement when user hovers over container
		if(this.overlay == null){
			this.overlay = this.container;
		}
		this.overlay.on('mouseover', function(event, el){
			this.stop();
			
			//See if the current index has a url
			if(Ext.get(this.items[this.currentIndex]).select('a').elements[0] != null){
				this.overlay.dom.style.cursor = 'pointer';
			}
			else{
				this.overlay.dom.style.cursor = 'default';
			}
			
		}, this);
		this.overlay.on('mouseout', function(){
			this.start();
		}, this);
		this.overlay.on('click', function(event, el){
			var link = Ext.get(this.items[this.currentIndex]).select('a').elements[0];
			if(link != null){
				window.open(link.href, '_newtab');
			}
		}, this);
	}
	
	,getItems: function(){
		//Get the items
		this.items = this.container.select(this.selector).elements;
		
		//Hide, style and position all elements
		this.items.each(function(el){
			var item = Ext.get(el);
			
			//Style element
			item.set({
				style: {
					position:'absolute'
					,top:0
					,left:0
					,width: this.width + 'px'
					,height: this.height + 'px'
					,overflow:'hidden'
				}
			});
			
			//Hide the element
			item.hide();
		});
		
		//Align and show the first
		if(this.items.length){
			Ext.get(this.items[0]).setLeft(0 + 'px');
			Ext.get(this.items[0]).show();
		}
	}
	
	,alignItems: function(lastIndex, currentIndex, next){
		if(next == null){
			next = true;
		}
		var currentItem = Ext.get(this.items[lastIndex]);
		var nextItem = Ext.get(this.items[currentIndex]);
		var left = this.width;
		if(!next){
			left = -this.width;
		}
		
		//Position the next item
		nextItem.setLeft(left + 'px');
		nextItem.show();
	}
	
	,next: function(){
		if(!this.animating){
			//get the old index
			var lastIndex = this.currentIndex;
			
			//Increment the current item
			this.currentIndex++;
			
			//Check the doundaries
			if(this.currentIndex > this.items.length-1){
				this.currentIndex = 0;
			}
			
			//align the items
			this.alignItems(lastIndex, this.currentIndex, true);
			
			//animate the container
			this.container.animate(
			    {left: { to: -this.width, unit: 'px'} },
			    this.animationDuration,
			    this.animationComplete.createDelegate(this),
			    this.easing,
			    'motion'
			);
			
			//is animating
			this.animating = true;
			
			//restart interval
			this.reset();
			
			//Fire event
			this.fireEvent('change');
		}
	}
	,previous: function(){
		if(!this.animating){
			
			//get the old index
			var lastIndex = this.currentIndex;
			
			//Decrement the currentIndex
			this.currentIndex--;
			
			//Check boundaries
			if(this.currentIndex < 0){
				this.currentIndex = this.items.length-1;
			}
			
			//Align the items
			this.alignItems(lastIndex, this.currentIndex, false);
			
			//Animate the container
			this.container.animate(
			    {left: { to: this.width, unit: 'px'} },
			    this.animationDuration,
			    this.animationComplete.createDelegate(this),
			    this.easing,
			    'motion'
			);
			
			//Is animating
			this.animating = true;
			
			//restart interval
			this.reset();
			
			//Fire event
			this.fireEvent('change');
		}
	}
	,animationComplete: function(){
		//hide all but the current
		for(var i=0; i < this.items.length; i++){
			if(i != this.currentIndex){
				Ext.get(this.items[i]).hide();
			}
		}
		
		//Set offsets back to zero
		var currentItem = Ext.get(this.items[this.currentIndex]);
		currentItem.setLeft(0);
		this.container.setLeft(0);
		
		this.animating = false;
	}
	,start: function(){
		var t = this;
		this.interval = setInterval(function(){
			this.next();
		}.createDelegate(this), (this.wait*1000));
	}
	,stop: function(){
		clearInterval(this.interval);
	}
	,reset: function(){
		this.stop();
		this.start();
	}
	
});
