var smokySlider = new Class({
	Implements: [Options],
	options: {
		maskSelector: 'div.mask',
		itemsSelector: 'div.item',
		navigationSelector: 'div.nav',
		nextButtonSelector: 'a.next',
		previousButtonSelector: 'a.previous',
		playButtonSelector: 'a.status',
		thumbSelector: 'img.thumb',
		itemTitleSelector: 'h2 a',
		thumbPreviewSelector: 'div.thumb-preview',
		selectedPageArrowSelector: 'div.selected-page-arrow',
		mode: 'horizontal',
		autoPlay: true,
		sliderTimer: 4000,
		addZeroPrefixToNumbers: true,
		tweenOptions: {
			'link': 'cancel',
			'duration': 1000,
			'transition': 'expo:in:out'
		},
		playButtonText: 'PLAY',
		pauseButtonText: 'PAUSE'
	},
	
	initialize: function(element, options) {
		this.setOptions(options);
		this.builtElement(element);
	},
	
	isAnimating: false,
	
	navigationPages: [],
	
	isPaused: false,
	
	interval: null,
	
	builtElement: function(el){
		this.element = document.id(el);
		if(!this.element) return;
		this.mask = this.element.getElement(this.options.maskSelector);
		this.items = this.element.getElements(this.options.itemsSelector);
		this.navContainer = this.element.getElement(this.options.navigationSelector);
		this.nextButton = this.element.getElement(this.options.nextButtonSelector);
		this.previousButton = this.element.getElement(this.options.previousButtonSelector);
		this.playButton = this.element.getElement(this.options.playButtonSelector);
		this.thumbPreview = this.element.getElement(this.options.thumbPreviewSelector);
		this.selectedPageArrow = this.element.getElement(this.options.selectedPageArrowSelector);		
		if(!this.items.length) return;
		this.setMoveOptions();
		this.createMovable();
		this.setTween();
		this.createNavigation();
		this.builtControls();
		this.play();
	},
	
	setMoveOptions: function(){
		this.dimension = this.options.mode == 'horizontal' ? 'width' : 'height';
		this.direction = this.options.mode == 'horizontal' ? 'left' : 'top';
		this.moveOffset = this.mask.getStyle(this.dimension).toInt();
	},
	
	createMovable: function(){
		this.movable = new Element('div',{
			'styles': {
				'position': 'relative'	
			}
		}).inject(this.mask,'top');
		if(this.options.mode == 'horizontal'){
			this.movable.setStyle('width', this.moveOffset*this.items.length);	
		}
		this.movable.adopt(this.items);
	},
	
	setTween: function(){
		this.tween = new Fx.Tween(this.movable,this.options.tweenOptions);
		this.tween.addEvents({
			start: function(){
				clearInterval(this.interval);
			}.bind(this),
			complete: function(){
				this.isAnimating = false;
				this.loop();
			}.bind(this)
		}).start(this.direction, 0);
	},
	
	setSelectedPage: function(el){
		if(this.selectedPage){
			this.selectedPage.removeClass('selected');
		}
		this.selectedPage = el;
		this.selectedPage.addClass('selected');
	},
	
	moveToNext: function(){
		var el = this.selectedPage.getNext();
		var ev = {};
		if(this.isAnimating) return;
		if(!el) el = this.navigationPages[0];
		ev.target = el;
		this.moveToPos(ev);
	},
	
	moveToPrevious: function(){
		var el = this.selectedPage.getPrevious('a.page');
		var ev = {};
		if(this.isAnimating) return;
		if(!el) el = this.navigationPages[this.items.length-1];
		ev.target = el;
		this.moveToPos(ev);
	},
	
	moveToPos: function(e){
		var clicked = e.target;
		if(this.isAnimating || this.selectedPage == clicked) return;
		this.setSelectedPage(clicked);
		this.currentIndex = clicked.get('pos');
		var dim = clicked.getSize();
		if(this.selectedPageArrow){
			this.selectedPageArrow.setStyle('left', clicked.offsetLeft + dim.x/2 - this.selectedPageArrow.getStyle('width').toInt()/2);
		}
		if(this.thumbPreview && this.hoverPageEvent){
			this.pageMouseEnter(this.hoverPageEvent);
		}
		this.tween.start(this.direction, -this.currentIndex*this.moveOffset);
	},
	
	changeStatus: function(){
		this.isPaused = !this.isPaused;
		if(this.isPaused){
			clearInterval(this.interval);
			if(this.playButton){
				this.playButton.addClass('paused');
				this.playButton.set('text', this.options.playButtonText);
			}
		}
		else{
			this.moveToNext();
			if(this.playButton){
				this.playButton.removeClass('paused');
				this.playButton.set('text', this.options.pauseButtonText);
			}
		}
	},
	
	pageMouseEnter: function(ev){	
		var el = ev.target;
		var dim = el.getSize();
		var thumbURL;
		if(el == this.selectedPage){
			this.thumbPreview.setStyle('visibility', 'hidden');
			return;
		}
		this.hoverPageEvent = ev;
		thumbURL = this.items[el.get('pos')].getElement(this.options.thumbSelector).get('src');
		this.thumbPreview.getElement('div.img').setStyle('background-image', 'url('+thumbURL+')');
		this.thumbPreview.setStyles({
			'visibility': 'visible',
			'left': el.offsetLeft + dim.x/2 - this.thumbPreview.getStyle('width').toInt()/2
		});
	},
	
	pageMouseLeave: function(ev){
		this.hoverPageEvent = null;
		this.thumbPreview.setStyle('visibility', 'hidden');					
	},
	
	createPage: function(index, title){
		var numbersPrefix = this.options.addZeroPrefixToNumbers ? '0' : '';
		var el = new Element('a', {
			'html': numbersPrefix+(index + 1),
			'href': 'javascript:void(0)',
			'class': 'page smokyToolTip',
			'title': title,
			'pos': index
		});
		if(this.thumbPreview){
			el.addEvents({
				'mouseenter': this.pageMouseEnter.bind(this),
				'mouseleave': this.pageMouseLeave.bind(this)
			});	
		}
		return el;
	},
	
	setItemStyles: function(item, index){
		if(this.dimension == 'width'){
			item.setStyle('float', 'left');
		}
		else if(this.dimension == 'opacity'){
			item.setStyles({
				'position': 'absolute',
				'top': 0,
				'left': 0,
				'z-index': index == 0 ? 11 : 10,
				'opacity': index == 0 ? 1 : 0
			});
		}
	},
	
	createNavigation : function(){
		var page;
		if(!this.navContainer) return;
		this.items.each(function(item, index){
			this.setItemStyles(item, index);
			page = this.createPage(index, item.getElement(this.options.itemTitleSelector).get('html'));
			page.addEvent('click', this.moveToPos.bind(this));
			page.addEvent('click', function(ev){ev.preventDefault();});
			page.inject(this.navContainer, 'bottom');
			this.navigationPages[index] = page;
		}, this);
		this.setSelectedPage(this.navigationPages[0]);
	},
	
	builtControls: function(){
		if(this.nextButton){
			this.nextButton.addEvent('click', function(ev){
				ev.preventDefault();
				this.moveToNext();
			}.bind(this));
		}
		if(this.previousButton){
			this.previousButton.addEvent('click', function(ev){
				ev.preventDefault();
				this.moveToPrevious();
			}.bind(this));
		}
		if(this.playButton){
			this.playButton.addEvent('click', function(ev){
				ev.preventDefault();
				this.changeStatus();												  
			}.bind(this));
		}
	},

	loop: function(){
		if(!this.isPaused){
			this.interval = this.moveToNext.delay(this.options.sliderTimer,this);
		}
	},
	
	play: function(){
		if(this.options.autoPlay){
			this.loop();
		}
		else{
			this.changeStatus();
		}	
	},

	toElement: function(){
		return this.element;
	}
});


var smokyFader = new Class({
	
    Extends: smokySlider,
	
	Implements: [Options],
	
    initialize: function(element, options){
        this.parent(element, options);
    },
	
	setMoveOptions: function(){
		this.dimension = 'opacity';
	},
	
	createMovable: function(){
		// We don't need to create a movable
	},
	
	setTween: function(){
		// Same applies here	
	},
	
	setSelectedPage: function(el){
		var pos;
		if(this.selectedPage){
			this.selectedPage.removeClass('selected');
			pos = this.selectedPage.get('pos');
			this.items[pos].setStyle('z-index', 10);
			this.lastActive = this.items[pos];
		}
		this.selectedPage = el;
		this.selectedPage.addClass('selected');
	},
	
	moveToPos: function(e){
		var clicked = e.target;
		if(this.isAnimating || this.selectedPage == clicked) return;
		this.setSelectedPage(clicked);
		this.currentIndex = clicked.get('pos');
		this.items[this.currentIndex].setStyle('z-index', 11);
		var dim = clicked.getSize();
		if(this.selectedPageArrow){
			this.selectedPageArrow.setStyle('left', clicked.offsetLeft + dim.x/2 - this.selectedPageArrow.getStyle('width').toInt()/2);
		}
		if(this.thumbPreview && this.hoverPageEvent){
			this.pageMouseEnter(this.hoverPageEvent);
		}
		

		
		this.tween = new Fx.Tween(this.items[this.currentIndex],this.options.tweenOptions);
		this.tween.addEvents({
			start: function(){
				this.isAnimating = true;
				clearInterval(this.interval);
			}.bind(this),
			complete: function(){
				if(this.lastActive){
					this.lastActive.setStyle('opacity', 0);
				}
				this.isAnimating = false;
				this.loop();
			}.bind(this)
		}).start('opacity', 1);
		
	}
	
});
