var Carousel = new Class({

	Implements: [Options,Events],
	
	Binds: [
		'slideChange',
		'slideComplete',
		'transitionComplete',
		'next',
		'previous'
	],

	options: {
		cycle: true,
		animate: true,
		loop: 5000,
		duration: 1000,
		transition: 'cubic:in:out',
		hideNavigation: true
	},

	container: null,
	scroller: null,
	items: null,
	pages: [],
	current: 0,
	nextButton: null,
	previousButton: null,
	fx: null,
	timer: null,
	slider: null,

	initialize: function(element, options){
		var self = this;
		this.setOptions(options);
		options = this.options;

		this.container = $(element);
		this.scroller = this.container.getElement('ul');
		this.items = this.scroller.getChildren('li');
		var width = 0;
		this.items.each(function(item){
			width += item.getWidth() + item.getStyle('margin-left').toInt() + item.getStyle('margin-right').toInt();
		});
		this.scroller.setStyle('width', width);

		this.fx = new Fx.Tween(this.scroller, {
			property: 'margin-left',
			link: 'cancel',
			duration: this.options.duration,
			transition: this.options.transition,
			onComplete: this.transitionComplete
		});

		this.nextButton = this.container.getElement('.next');
		this.nextButton.set('tween', { link: 'cancel'});
		this.nextButton.addEvent('click', this.next);
		
		this.previousButton = this.container.getElement('.previous');
		this.previousButton.set('tween', { link: 'cancel'});
		this.previousButton.addEvent('click', this.previous);
		
		this.getPages();
		/*
		if(slider && knob){
			this.slider = new SlideBarExt(slider, knob, {
				steps: (this.pages.length-1),
				onChange: this.slideChange,
				onComplete: this.slideComplete
			});
		}
		*/
		if(this.pages.length > 1){
			this.hideNavigation();
			this.showNavigation();
			if(this.options.animate)
				this.play();
		}
	},

	getPages: function(){
		var self = this;
		var pageWidth = this.container.getWidth();
		var count = 0, total = 0;
		this.pages = [];
		this.pages.push(0);
		this.items.each(function(item){
			if(count >= pageWidth){
				total += count;
				self.pages.push(total);
				count = 0;
			}
			count += item.getWidth().toInt();
		});
	},
	
	slideChange: function(step){
		this.hideNavigation();
		this.stop();
		this.current = step;
		var scroll = this.pages[this.current];
		if($defined(scroll))
			this.fx.start(-(scroll));
	},
	
	slideComplete: function(){
		this.transitionComplete();
	},
	
	transitionComplete: function(){
		if(this.slider && this.slider.isDragging)
			return;
		this.showNavigation();
		if(this.options.animate)
			this.play();
	},

	next: function(event){
		if(event)
			event.preventDefault();
			
		if(this.options.hideNavigation)
			this.hideNavigation();
			
		this.stop();
		
		if(this.pages.length == 0) return;
		this.current++;
		if(this.current > this.pages.length-1)
			this.current = this.options.cycle ? 0 : this.pages.length-1;
			
		var scroll = this.pages[this.current];
		if($defined(scroll))
			this.fx.start(-(scroll));
		
		if(this.slider)
			this.slider.slideTo(this.current);
	},

	previous: function(event){
		if(event)
			event.preventDefault();
			
		if(this.options.hideNavigation)
			this.hideNavigation();
			
		this.stop();
		
		if(this.pages.length == 0) return;
		this.current--;
		if(this.current < 0)
			this.current = this.options.cycle ? this.pages.length-1 : 0;
			
		var scroll = this.pages[this.current];
		if($defined(scroll))
			this.fx.start(-(scroll));
		
		if(this.slider)
			this.slider.slideTo(this.current);
	},
	
	hideNavigation: function(){
		this.nextButton.fade('hide');
		this.previousButton.fade('hide');
	},
	
	showNavigation: function(){
		this.nextButton.fade('in');
		this.previousButton.fade('in');
	},
	
	play: function(){
		$clear(this.timer);
		this.timer = this.next.periodical(this.options.loop, this);
	},
	
	stop: function(){
		$clear(this.timer);
	}
});

var SlideBarExt = new Class({
	
	Extends: Slider,
	
	options: {
		duration: 1000,
		transition: 'cubic:in:out'
	},
	
	fx: null,
	
	initialize: function(slider, knob, options){
		this.parent(slider, knob, options);
		
		this.fx = new Fx.Tween(this.knob, {
			property: 'left',
			link: 'cancel',
			duration: this.options.duration,
			transition: this.options.transition,
			onComplete: this.end.bind(this)
		});
	},
	
	slideTo: function(step){
		if (!((this.range > 0) ^ (step < this.min))) step = this.min;
		if (!((this.range > 0) ^ (step > this.max))) step = this.max;
		this.step = Math.round(step);
		this.checkStep();
		this.fx.start(this.toPosition(this.step));
		return this;
	}
});
