/*
@version:
0.9

@TODO:
- add animation for inactive handles
- add support for slidehandles inside slidecontainers

@copyright:
deepblue networks AG / Julian Gieseke

*/
var simpleSlider = Class.create({
	instances: {},
	
	initialize: function(id, options) {
		this.id = id;					// slidecontainer (needs another container with position:relative)
		
		// set some default values
		this.inEffect = false;			// needed if options.effect is true, if true no slide can be initiated
		this.currentActive = 0;			// stores active element, !stores index in array! (starts with 0)
		this.offsetArray = [];			// stores slideoffsets of elements
		this.lastDirection = 0;			// stores direction of last slideaction
		
		// set default options
		this.options = {
			activeClass: 'active',		// class that get active handles
			effect: true,				// set if effect should be used or just realign slidecontainer
			//next 4 options only needed if above is true
			effectDuration: 0.5,		// duration of slideffect
			effectTransition: Effect.Transitions.linear,	// slideeffect
			handleDuration: 0.5,		// duration of animation for active handles
			handleTransition: Effect.Transitions.linear,	// handleeffect
			start: 0,					// set startElement, index of array (starts with 0)
			elements: 'li',				// elements that should recognized as slidelements (css selector)
			handleContainer: 'body',	// if there are handles without given target, they have to be in this container to be recognizes as handles
			handleElement: 'a',			// handleelement, default handles can only be links, if you need something else - change here
			loop: true,					// set if next on last element should go to first one (and prev on first to last..)
			deeplinks: false			// enable deeplinks (#id of slideelement) !!ALPHA!!
		};
		Object.extend(this.options, options);
		
		this.instances[this.id] = true;
		
		// hey ho, lets go
		this.load();
	},
	load: function(){
		Element.addClassName($$('body')[0], 'simpleslider');
		
		this.setOffsets();
		this.setSlideElements();
		
		//console.log('start');
		
		i = 0;
		$$(this.options.handleElement+'[rel*='+this.id+']').each(function(elm){
			var pattern = this.id+"\\[(.*)\\]";
			var regex = elm.rel.match(pattern);
			//console.log('1', elm.rel, pattern, regex);
			elm.i = (regex) ? regex[1] : i;
			if(typeof(elm.up(this.options.handleContainer)) != 'undefined') {
				if(!i) this.setActive(elm);
				i++;
			}
			//console.log('2');
			elm.href = '#'+this.id+':'+elm.href.split('#')[1];
			
			Event.observe(elm, 'click', function(evt){
				evt.stop();
				if(!this.inEffect) this.setActive(elm);
				//console.log(elm);
				this.slideTo(elm.i, this.options.effect);
			}.bind(this));
		}.bind(this));
		
		Event.observe(window, 'resize', this.resize.bind(this));
		//console.log('done');
		if(this.options.deeplinks && window.location.hash) this.goToDeeplink(window.location.hash);
	},
	refresh: function(){
		this.setSlideElements();
		this.setOffsets();
	},
	goToDeeplink: function(hash){
		//console.log(hash);
		var dlId = hash.substring(1);
		if($$('#'+this.id+' #'+this.id+'-'+dlId).length) {
			this.removeActiveClasses();
			$$('[href=#'+this.id+':'+dlId+']').each(function(ae){
				this.slideTo(ae.i, false);
				//console.log(ae);
				this.addClass(ae);
			}.bind(this));
		}
	},
	resize: function() {
		this.setOffsets();
		this.slideTo(this.currentActive, false);
	},
	setSlideElements: function(){
		this.slideElements = $$('#'+this.id+' '+this.options.elements).length-1;
	},
	setOffsets: function() {
		var i = 0;
		this.offsetArray = [];
		$$('#'+this.id+' '+this.options.elements).each(function(elm){
			this.offsetArray[i] = {
				top: elm.offsetTop,
				left: elm.offsetLeft
			};
			//console.log(elm.id, this.offsetArray);
			i++;
		}.bind(this));
	},
	slideTo: function(i, e) {
		var mod = null;
		//console.log(i, e);
		this.lastDirection = this.getRealTarget(i, true);
		i = this.getRealTarget(i);
		//console.log(this.currentActive,i,this.offsetArray[i]);
		if(typeof(Effect)=='object' && e) {
			//scriptaculous
			//console.log(this.inEffect, this.currentActive, i);
			if(!this.inEffect && this.currentActive != i) {
				this.inEffect = true;
				this.currentActive = i;
				new Effect.Move(this.id, {
					mode: 'absolute', 
					y: (this.offsetArray[i].top*(-1)),
					x: (this.offsetArray[i].left*(-1)),
					duration: this.options.effectDuration,
					transition: this.options.effectTransition,
					afterFinish: function(){
						this.inEffect = false;
						$(this.id).fire('simpleslider:slide:done');
					}.bind(this)
				});
			}
		} else {
			//prototype
			$(this.id).style.top = (this.offsetArray[i].top*(-1)) + 'px';
			$(this.id).style.left = (this.offsetArray[i].left*(-1)) + 'px';
			this.currentActive = i;
			$(this.id).fire('simpleslider:slide:done');
		}
	},
	
	// from here: internal functions, normally you dont call them directly
	removeActiveClasses: function(){
		$$(this.options.handleElement+'[rel*='+this.id+']').each(function(elm){
			this.removeClass(elm);
		}.bind(this));
	},
	removeClass: function(elm) {
		//if(this.options.effect) elm.morph(this.options.inactiveClass);
		//else 
		Element.removeClassName(elm, this.options.activeClass);
	},
	addClass: function(elm) {
		if(this.options.effect && this.currentActive != this.getRealTarget(elm.i)) elm.morph(this.options.activeClass, {duration:this.options.handleDuration, transition: this.options.handleTransition});
		else Element.addClassName(elm, this.options.activeClass);
	},
	setActive: function(e) {
		//console.log(this.options);
		//console.log(e);
		this.removeActiveClasses();
		//console.log(e.rel, this.id, e.rel.match(this.id));
		if(e.rel.match(this.id)) {
			var i = this.getRealTarget(e.i);
			var j = 0;
			$$(this.options.handleElement+'[rel~='+this.id+']').each(function(elm){
				if(j==i) {
					this.addClass(elm);
				}
				j++;
			}.bind(this));
			$$(this.options.handleElement+'[rel*='+this.id+'['+i+']]').each(function(elm){
				this.addClass(elm);
			}.bind(this));
		} /* else {
			this.addClass(e);
		}  */
	},
	getRealTarget: function(i, d) {
		direction = (d) ? d:false;
		if(/\+|\-/.test(i)) {
			//console.log(i+' has +/-');
			var regex = i.match(/(\+|\-)?([0-9]+)/);
			mod = (regex[1]) ? regex[1] : null;
			
			if(mod=='+') {
				i = parseInt(this.currentActive) + parseInt(regex[2]);
				if(direction) return 1;
			} else if(mod=='-') {
				i = parseInt(this.currentActive) - parseInt(regex[2]);
				if(direction) return -1;
			} else {
				i = regex[2];
				if(direction) {
					if(this.currentActive>i) return -1;
					else if(this.currentActive<i) return 1;
					else return 0;
				}
			}
			//console.log(i,this.slideElements);
			if(i>this.slideElements) {
				while(i>this.slideElements) {
					i = i - this.slideElements - 1;
				}
				i = (this.options.loop) ? i : this.slideElements;
			}
			if(i<0) {
				while(i<0) {
					i = this.slideElements + i + 1;
				}
				i = (this.options.loop) ? i : 0;
			}
		}
		return i;
	}
});