var ElementHighlighter = new Class({
	Implements: [Options, Events],
	currentIndex: 0,
	elements: [],
	styles: { },
	callbacks: { },
	enterFunc: null,
	leaveFunc: null,
	finished: false,
	options: {
		elements: [],
		timer: null,
		currentIndex: 0,
		delay: 4000,
		transTime: 500,
		fps: 15,
		loop: false,
		defaultStyle: {
			'in':	{'opacity': 1},
			'out': {'opacity': 0.6}
		}
	},
	initialize: function(options){
		this.setOptions(options);
		this.setStyles(this.options.defaultStyle);
		if(this.options.currentIndex) 
			this.currentIndex = this.options.currentIndex;
		if(this.options.callbacks) this.callbacks = this.options.callbacks;
		this.addElements(this.options.elements);
		this.addElEvents(this.elements);
	},
	addElEvents: function(elements) {
		if(!this.enterFunc) this.enterFunc = function(i) { 
				this.lastIndex = this.currentIndex;
				this.pause( );
				this.animate(i);
		};
		if(!this.leaveFunc) this.leaveFunc = function(i) { 
				if(!this.finished) {
					this.currentIndex = this.lastIndex;
					this.start( );
				} else this.animate(-1);
		};

		$$(elements).each(function(el, i) {
			el.addEvent("mouseenter", this.enterFunc.bind(this, i));
			el.addEvent("mouseleave", this.leaveFunc.bind(this, i));
		}.bind(this));
	},
	delElEvents: function(elements) {
		$$(elements).each(function(el, i) {
			el.removeEvent("mouseenter", this.enterFunc);
			el.removeEvent("mouseleave", this.leaveFunc);
		});		
	},
	addElements: function(elements) {
		$$(elements).each(function(ele) {
			this.elements.include($(ele));
			$(ele).set('morph', {
				duration: this.options.transTime,
				fps: this.options.fps
			});
		}, this);
		this.animate(-1);
	},
	addElement: function(ele) {
		this.addElements($splat($(ele)));
	},
	setStyles: function(style) {
		if(style['in']) this.styles['in'] = style['in'];
		if(style['out']) this.styles['out'] = style['out'];
	},
	start: function(delay) {
		console.log("Element Highlighter Start Called...");
		if(!this.timer) {
			console.log("Starting Element Highlighter");
			this.currentIndex = 0;
			this.finished = false;
			if(!delay) this.animate( );
			this.timer = this.animate.periodical(this.options.delay, this);
		}
	},
	pause: function( ) {
		if(this.timer) {
			$clear(this.timer); this.timer = null;
		}
	},
	stop: function( ) {
		$clear(this.timer); this.timer = null;
		this.animate(-1);
		this.finished = true;
		if(this.callbacks['finish']) this.callbacks['finish'].run( );
	},
	animate: function(index) {
		var id = this.currentIndex;
		if($type(index) == "number") id = index;
		var state;

		this.elements.each(function(el, i) {
			if(id == i) state='in'; else state='out';
			if(el.cState != state) {
				this.animateElement(el, state, 
					this.callbacks[state] ? this.callbacks[state] : false,
					[el, i, id == i]
				);
			}
		}.bind(this));

		if($type(index) != "number") {
			this.currentIndex++;
			if(this.currentIndex >= this.elements.length)
				if(this.options.loop) {
					this.currentIndex = 0; 
				} else this.stop.delay(this.options.delay, this);
		}
	},
	animateElement: function(el, state, callback, params) {
		var style = this.styles[state];
		var tt = this.options.transTime;

		$splat(el).each(function(el) {
			el.cState = state;
			el.morph(style);
			if(callback) {
				if(callback['start']) callback['start'].run(params);
				if(callback['end']) callback['end'].delay(tt, this, params);
			}
		});
	}
});
