var EternalSlider = new Class({
	
	Implements: [Options, Events],
	
	options: {
		elementsSelector: 'div.item',
		nextButtonSelector: 'a.nextButton',
		previousButtonSelector: 'a.previousButton',
		timerLineSelector: 'div.timerLine',
		mode: 'horizontal',
		paused: false,
		duration: 1000,
		period: 5000,
		itemMoveButtonClass: 'moveButton',
		offsetLeft: 400,
		sliderInfo: 'div.sliderInfo',
		sliderInfoDigits: 3,
		log: true,
		itemOnShow: function(elem, slider){
			slider.isMoving = false;
		},
		itemOnHide: function(elem, slider){
			slider.moveSlider();
		}
	},
	
	initialize: function(container, options){
		this.setOptions(options);
		this.setParts(container);
		this.initVariables();			
		this.cloneElements();
		this.createMovable();
		this.setTimer();
			
		this.moveTween = new Fx.Tween(this.movable,{
			link : 'cancel',
			duration: this.options.duration,
			transition: 'quad:in:out',
			onComplete: function(){
				this.elements[this.curIdx].addClass('active');
			}.bind(this)
		}).set(this.moveProperty, this.startPosition);

			
		this.setPrevNextButtons();
	
		this.moveTween.fireEvent('complete');
		this.options.itemOnShow(this.elements[this.curIdx], this);
		this.setSliderInfoText();
		this.resume();
		
		this.container.addEvents({
			'click': function(event){
				event = new Event(event);
				var t = $(event.target);
				if(t.get('class') == this.options.itemMoveButtonClass && t.idx != this.curIdx){
					var s = t.getParent().idx;
					this.showNext(s);
				}
			}.bind(this),
			'mouseover': function(ev){
				var t = $(ev.target);
				if(t.get('class') == this.options.itemMoveButtonClass){
					this.pause();
				}
			}.bind(this),
			'mouseout': function(ev){
				var t = $(ev.target);
				if(t.get('class') == this.options.itemMoveButtonClass){
					this.resume();
				}
			}.bind(this)
		});
		
	},
	
	setParts: function(cont){
		this.container = document.id(cont);
		if(!this.container){
			this.sliderLog('container not found');	
		}
		this.elements = this.container.getElements(this.options.elementsSelector);
		this.sliderInfo = this.container.getElement(this.options.sliderInfo);
		this.nextButton = $(this.options.nextButtonSelector);
		this.previousButton = $(this.options.previousButtonSelector);
	},
	
	initVariables: function(){
		this.curIdx = this.realElementsLength = this.elements.length;
		this.isMoving = false;
		this.elementComputedSize = this.elements[0].getComputedSize({styles: ['border','padding','margin']})[this.options.mode == 'horizontal' ? 'totalWidth' : 'totalHeight'];
		this.startPosition = -(this.realElementsLength*this.elementComputedSize - this.options.offsetLeft);
		
		this.moveProperty = this.options.mode == 'horizontal' ? 'left' : 'top';	
	},
	
	cloneElements: function(){
		var tmp = new Array();
		var clone1, clone2;
		this.elements.each(function(element, index){
			clone1 = element.clone();
			clone2 = element.clone();
			element.idx = index;
			element.realIdx = index;
			clone1.idx = this.realElementsLength + index;
			clone1.realIdx = index;
			clone2.idx = 2*this.realElementsLength + index;
			clone2.realIdx = index;
			tmp[index] = this.elements[index];
			tmp[clone1.idx] = clone1;
			tmp[clone2.idx] = clone2;
		}.bind(this));
		this.elements = tmp;
	},
	
	createMovable: function(){
		this.movable = new Element('div', {
			'styles': {position: 'relative'},
			'class': 'movable'
		})
		.adopt(this.elements)
		.inject(this.container, 'top')
		.setStyle(this.options.mode == 'horizontal' ? 'width' : 'height', this.elements.length * this.elementComputedSize);
	},
	
	setPrevNextButtons: function(){
		if(this.previousButton){
			this.previousButton.addEvents({
				'click' : this.showPrevious.bind(this)
			});
		}
		if(this.nextButton){
			this.nextButton.addEvents({
				'click' : function(){
					this.pause();
					this.showNext();
					this.resume();
				}.bind(this)
			});
		}
	},
	
	showNext: function(idx, fromPaging){
		this.holdIt = this.curIdx;
		if(fromPaging){
			idx = idx + (Math.ceil(this.curIdx/(this.realElementsLength-1)) - 1)*this.realElementsLength;
		}
		if(!this.isMoving){
			this.isMoving = true;
			this.curIdx = idx >= 0 ? idx : this.curIdx + 1;
			this.elements[this.holdIt].removeClass('active');
			this.options.itemOnHide(this.elements[this.holdIt], this);
		}
	},
	
	showPrevious: function(){
		if(!this.isMoving){
			this.pause();
			this.showNext(this.curIdx-1);
			this.resume();
		}
	},
	
	setTimer: function(){
		this.isPaused = this.options.paused;
		this.timeLine = this.container.getElement(this.options.timerLineSelector);
		if(!this.timeLine){
			this.timeLine = new Element('div');
		}
		this.timmerTween = new Fx.Tween(this.timeLine, {
			link: 'cancel',
			duration: this.options.period,
			unit: '%',
			transition: 'expo:in',
			onComplete: function(){
				this.showNext();
				this.timmerTween.start('width',0,'100');
			}.bind(this)
		});	
	},
	
	pause: function(){
		this.timmerTween.pause();
		this.timmerTween.set('width', 0);		
	},
	
	resume: function(){
		if(!this.isPaused){
			this.timmerTween.start('width',0,100);
		}
	},
	
	setSliderInfoText: function(){
		if(this.sliderInfo){
			var curPos = this.elements[this.curIdx].realIdx + 1;
			var tot = this.realElementsLength;
			this.sliderInfo.set('text', this.addLeadingZeros(curPos)+' / '+this.addLeadingZeros(tot));
		}
	},
	
	moveSlider: function(){
		var t = this;
		t.newPosition =  - (t.curIdx*t.elementComputedSize -t.options.offsetLeft);
		if(t.movable.getStyle('width').toInt() + t.newPosition < t.container.getStyle('width').toInt()){
			t.curIdx = t.curIdx - t.realElementsLength;
			t.movable.setStyle(t.moveProperty, -((t.holdIt-t.realElementsLength)*t.elementComputedSize-t.options.offsetLeft));
			t.newPosition = - (t.curIdx*t.elementComputedSize - t.options.offsetLeft);
		}
		else if(this.newPosition > 0){
			t.curIdx = t.realElementsLength;
			t.movable.setStyle(t.moveProperty, - ((t.realElementsLength+1)*t.elementComputedSize-t.options.offsetLeft));
			t.newPosition = - (t.curIdx*t.elementComputedSize-t.options.offsetLeft);
		}
		t.setSliderInfoText();
		t.moveTween.start(t.moveProperty, t.newPosition);	
		t.options.itemOnShow(t.elements[t.curIdx], t);
	},
	
	addLeadingZeros: function(num){
		var t = this.options.sliderInfoDigits - num.toString().length.toInt();
		for(var i=0;i<t;i++){
			num = '0' + num;
		}
		return num;
	},
	
	log: function(msg){
		if(this.options.log){
			console.log(msg);	
		}
	},
	
	toElement: function(){
		return this.container;
	}
	
});
