var ElementSlider = Class.create({
	initialize: function(slideContainers, slideTargets)
	{   
		this.sliders = { containers: slideContainers, targets: slideTargets };
		this.options = Object.extend({
		    slideEffect: 'horizontal',              // horizontal, vertical, both or random
			activeIndex: 		0,
			previousIndex: 		0,
			contentWidth:		0,  					// width of content to slide as integer
			contentHeight:		750,					// width of content to slide as integer
			afterFinish:		'',						// client function to call after finish as string, ex: 'callThisFunc'							
			beforeStart:		'',						// client function to call before start as string, ex: 'callThisFunc'							
			duration: 			0.5,						// duration of the effect
			rotationInterval: 	0
			
		}, arguments[2] || {});			    	
		this.slideEffects = ['horizontal', 'vertical', 'both', 'random'];
		this.activate();
	},
	swapContent: function(index, e)
	{
		if (index == this.options.activeIndex) return false;
		
		if (e)
		{
			Event.stop(e);
			if (this.options.rotationInterval && this.executer)
			{
				this.executer.stop();
				this.executer = null;
			}
		}
		
		this.options.previousIndex = this.options.activeIndex;
		this.options.activeIndex = index;
		
		var activePair = this.getActivePair();
		var previousPair = this.getPreviousPair();
		
		Element.addClassName(activePair.target.up(), 'active');
		Element.removeClassName(previousPair.target.up(), 'active');
		
		//TODO: only if not animating 	
		var dimensions = this.getActiveContentDimensions()
		var moveX = index > this.options.previousIndex ? -dimensions.width : dimensions.width;
		var moveY = index > this.options.previousIndex ? -dimensions.height : dimensions.height;
		
		var slideEffect = this.options.slideEffect;
		if (this.options.slideEffect == 'random')
		{
		    var rand = Math.floor(Math.random()*3);
		    slideEffect = this.slideEffects[rand];
		}
		switch (slideEffect)
		{
		    case 'horizontal':
		        moveY = 0;
		    break;
		    case 'vertical':
		        moveX = 0;
		    break;
		    case 'random':
		        
		    default:
		    
		}
		new Effect.Parallel([
				new Effect.MoveBy(previousPair.container, moveY, moveX, { 
					sync: true,
					queue: {position:'end', scope:'cs1'}
				}),
				new Effect.MoveBy(activePair.container, moveY, moveX, { 
					sync: true,
					queue: {position:'end', scope:'cs2'}, 
					beforeStart: function() {
					    switch (slideEffect)
		                {
		                    case 'horizontal': 
		                        activePair.container.style.top = 0;
		                        activePair.container.style.left = moveX * -1 + 'px';
		                    break;
		                    case 'vertical': 
		                        activePair.container.style.top = moveY * -1 + 'px';
		                        activePair.container.style.left = 0;
		                    break;
		                    default:
                		        activePair.container.style.left = moveX * -1 + 'px';
					            activePair.container.style.top = moveY * -1 + 'px';
		                }
					}
				})
			],{
				duration: this.options.duration,
				beforeStart: this.beforeStart.bind(this),
				afterFinish: this.afterFinish.bind(this)
		});
		return false;			    
	},
	getActiveContentDimensions: function()
	{
	    var dimensions = {width: 0, height: 0};
	    
	    if (this.options.contentHeight)
	        dimensions.height = this.options.contentHeight;
	    else
	        dimensions.height = this.sliders.containers[this.options.activeIndex].getHeight();
	        
	    if (this.options.contentWidth)
	        dimensions.width = this.options.contentWidth;
	    else
	        dimensions.width = this.sliders.containers[this.options.activeIndex].getWidth();
	    return dimensions;
	        
	},
	
	getPreviousPair: function()
	{   
	    return {target: this.sliders.targets[this.options.previousIndex], container: this.sliders.containers[this.options.previousIndex]};
	},
	getActivePair: function()
	{
	     return {target: this.sliders.targets[this.options.activeIndex], container: this.sliders.containers[this.options.activeIndex]};
	},
	getActiveIndex: function()
	{
	     return this.options.activeIndex;
	},
	getNextIndex: function()
	{
		var maxLength = this.sliders.targets.length-1;
		var nextIndex = this.options.activeIndex + 1;
		if (nextIndex > maxLength)
			nextIndex = 0;
	     return nextIndex;
	},
	getNextPair: function()
	{
		 var nextIndex = this.getNextIndex();
	     return {target: this.sliders.targets[nextIndex], container: this.sliders.containers[nextIndex]};
	},
	cacheEvents: function()
	{
		//TODO: create an array of cached events for each sliding element
		this.cachedWindowUnload = this.dispose.bindAsEventListener(this);		
	},
	afterFinish: function()
	{
		//alert(this.options.afterFinish);
		this.sliders.containers[this.options.previousIndex].style.left = '9999em';
		if (this.options.afterFinish)
			eval(this.options.afterFinish + '(undefined)');
	},
	beforeStart: function()
	{
		if (this.options.beforeStart)
			eval(this.options.beforeStart + '(undefined)');
	},
	activate: function()
	{
		this.cacheEvents();
		for(var i = this.sliders.targets.length-1, target; target = this.sliders.targets[i]; i--) 
		{
			target.observe('click', this.swapContent.bind(this, i));	
		}     
		
		if (this.options.rotationInterval)
		{
			this.executer = new PeriodicalExecuter(function(){this.swapContent(this.getNextIndex())}.bind(this), this.options.rotationInterval);
		}
		Element.observe(window, 'unload', this.cachedWindowUnload );
	},
	deactivate: function()
	{
		this.sliders.targets.invoke('stopObserving');
		Element.stopObserving(window, 'unload', this.cachedWindowUnload );
	},
	dispose: function(e)
	{
		this.deactivate();
	}

});