TLP.CRot = Class.create();

TLP.CRot.prototype = {
	Version: '1.0',
	testForRequired: function(){
		if(parseFloat(TLP.Version.split(".")[0] + "." + TLP.Version.split(".")[1]) < 1.0)
			TLP.throwEx("TLP Form Validation requires the TLP Javascript Library Version 1.0");
	},
	// initialize method
	initialize: function(containerEl, oOptions) {
		
		// test to see if the required libs are available
		this.testForRequired();
		// parse optional arguments and assign defaults
		this.options = TLP.augment(
		{
			// default values
      		elClassName: 'CRot_el', 			// rotator element classname
			activeElClassName: 'active', 		// active element classname
			navClassName: 'nav', 				// rotator navigation classname
			navShowingClassName: 'show', 		// rotator navigation shown classname
			navHiddenClassName: 'hide',			// rotator navigation hidden classname
			animate: true, 						// anitmate
			animateShowTransition: 'Appear', 	// show transistion
			animateHideTransition: 'Fade', 		// hide transition
			animationShowDuration: 0.5,
			animationHideDuration: 0.5,
			duration: 5, 						// time in seconds for each loop
			sort: 'linear'						// [random|linear]
		}, oOptions );
		
		if(this.options.duration * 2 < this.options.duration){
			alert('The rotator update duration must be atleast twice as long as the animation duration');
		}
			
		// set unique object id
		this.id = 'containerEl';
		this.animating = false;
		// get the rotator
		this.rotator = $(containerEl);

		// get the rotator els
		this.rotatorEls = document.getElementsByClassName(this.options.elClassName, this.rotator);

		// for each of the rotator content elements
		for(var i=0; i<this.rotatorEls.length; i++){
			// if the element has the active element class name
			if(Element.hasClassName(this.rotatorEls[i], this.options.activeElClassName)){
				// set this element as the active element.
				this.activeEl = this.rotatorEls[i];		
			}
			Event.observe(this.rotatorEls[i], 'mouseover', this.stop.bindAsEventListener(this));
			Event.observe(this.rotatorEls[i], 'mouseout', this.start.bindAsEventListener(this));
		}

		// if there is no active element
		if(!this.activeEl){
			// set the active element as the first element
			this.activeEl = this.rotatorEls[0];
			// add active classname to element
			Element.addClassName(this.activeEl, 'this.options.activeClassName');
		}
		
		this.navigationEls = document.getElementsByClassName(this.options.navClassName, this.rotator);
		if (this.navigationEls.length > 0 && this.options.sort == 'linear'){
			for(var i=0; i<this.navigationEls.length; i++){
				Element.removeClassName(this.navigationEls[i], this.options.navHiddenClassName);
				Element.addClassName(this.navigationEls[i], this.options.navShowingClassName);
			}
		}
		// create new periodical executer to call this.update
		this.executer = new PeriodicalExecuter(this.cycle.bind(this), this.options.duration);
				
	},
	// update method
	cycle: function(targetEl){
		if (this.options.animate == true && this.animating == false){	
		
		this.nextEl = targetEl;
			
		if(this.options.sort == 'linear' && this.nextEl == undefined){
			var currentIndex = this.rotatorEls.indexOf(this.activeEl);
			if (currentIndex + 1 < this.rotatorEls.length){
				newIndex = currentIndex + 1;
			} else {
				newIndex = 0;
			}
			this.nextEl = this.rotatorEls[newIndex];
		} else if (this.options.sort == 'random' && this.nextEl == undefined){
			this.nextEl = this.rotatorEls[Math.floor(Math.random()*(this.rotatorEls.length))];
		}
			new Effect[this.options.animateHideTransition](this.activeEl,{
				queue: {scope: this.id},
				duration: this.options.animationHideDuration,
				beforeStart: function(){
					this.animating = true;
					Element.addClassName(this.rotator, 'animating');
				}.bind(this),
				afterFinish: function (){
					Element.removeClassName(this.activeEl, this.options.activeClassName);				
				}.bind(this)
			});
			new Effect[this.options.animateShowTransition](this.nextEl, {
				queue: {position: 'end', scope: this.id},
				duration: this.options.animationHideDuration,
				beforeStart: function(){
					Element.addClassName(this.nextEl, this.options.activeClassName);
				}.bind(this),
				afterFinish: function (){
					this.activeEl = this.nextEl;
					this.animating = false;
					Element.removeClassName(this.rotator, 'animating');
				}.bind(this)
			});
		}
	},
	
	stop: function(){
		// set the animation boolean to false
		this.options.animate = false;
	},
	
	start: function(){
		// set the animation boolean to true
		this.options.animate = true;
	},
	
	adjustPosition:function(adjustment){
		// get the current elements index
		var currentIndex = this.rotatorEls.indexOf(this.activeEl);
		// set the rotators els length
		var elsLength = this.rotatorEls.length;
		// if the adjustment is a negative
		if (adjustment < 0){
			// do some crazy mod math stuff
			newIndex = (currentIndex + elsLength - (Math.abs(adjustment) % elsLength)) % elsLength; // thanks carli
		} else {
			// the adjustment is a positive.. do carzy mod math stuff
			newIndex = (currentIndex + adjustment) % elsLength;
		}
		// cycle to the new target element
		this.cycle(this.rotatorEls[newIndex]);
	},
	
	skipTo: function(targetIndex){
		// skip to the target index
		this.cycle(this.rotatorEls[targetIndex]);
	}
}
