var Timer = new Class({
	
	Implements: [Options, Events],
	
	options: {
		periode: 500
	},
	
	initialize: function(instances, options){
		this.setOptions(options);
		this.timer = null;
		this.instances = [];
		this.register(instances);
		this.start();
	},
	
	register: function(){
		var instances = Array.flatten(arguments);
		instances.each(function(instance){
			instance.addEvent('stop', this.stop.bindWithEvent(this));
			instance.addEvent('start', this.start.bindWithEvent(this));
			instance.addEvent('periodic', instance.periodic.bindWithEvent(instance));
		}, this);
		this.instances.push.apply(this.instances, instances);
	},
	
	stop: function(e){
		$clear(this.timer);
	},
	
	start: function(){
		this.timer = this.execute.periodical(this.options.periode, this);
	},
	
	execute: function(){
		this.instances.each(function(instance){
			instance.fireEvent('periodic');
		});
	}
	
});

var Cycle = new Class({
	setCycle: function(initialIndex, maxIndex){
		this.cycle = function(increment){
			increment = increment || 1;
			var nextIndex = (this.cycle.index + increment) % this.cycle.maxIndex;
			if(nextIndex < 0) nextIndex = (this.cycle.maxIndex + increment) % this.cycle.maxIndex;
		    return (this.cycle.index = nextIndex);
		}.bind(this);
		if(!$chk(maxIndex)){
			maxIndex = initialIndex;
			initialIndex = 0;
		}
		this.cycle.index = initialIndex;
		this.cycle.maxIndex = maxIndex;
	}
});

var Slide = new Class({
	
	Implements: [Options, Events, Cycle],
	
	options: {
		'property': 'margin-top'
	},
	
	initialize: function(container, elements, options){
		this.container = $(container) || $$(container)[0] || null;
		if(!this.container) return;
		this.elements = $$(elements);
		this.elementsFx = [];
		this.setCycle(this.elements.length);
		this.setOptions(options);
		this.currentIndex = 0;
		this.elements.each(function(element, index){
			this.elementsFx[index] = new Fx.Tween(element, {property: this.options.property});
		}, this);
		this.setHoverEvents();
	},
	
	setHoverEvents: function(){
		this.container.addEvent('mouseenter', this.mouseEnter.bindWithEvent(this));
		this.container.addEvent('mouseleave', this.mouseLeave.bindWithEvent(this));
	},
	
	mouseEnter: function(){
		this.fireEvent('stop');
	},
	
	mouseLeave: function(){
		this.fireEvent('start');
	},
	
	periodic: function(e){
		this.elementsFx[this.cycle.index].start(-this.elements[this.cycle.index].getHeight()).chain(function(){
			this.set(0);
			this.element.inject(this.element.getParent());
		});
		this.cycle();
	}
	
});
