/**
 * SF Content rotator
 * Version 0.1 (04.28.2009)
 * Possible effects to use :
 *  - if UI effects have been added: 'blind', 'bounce', 'clip', 'drop', 'explode', 'fold', 'highlight', 'puff', 'pulsate', 'scale', 'shake', 'size', 'slide', 'transfer'
 *  - basic effects from jQuery: fadeIn, fadeOut, show, hide, slideUp, slideDown
 */
(function(){
	
	var SFRotator = function(el, options){

		this.settings = {
			'item' : 'li', //rotated items
			'activeClass' : 'active',  //active item indicator
			'duration' : 5000, //duration cycle in miliseconds
			'autorotate' : true,
			
			'effectIn' : 'fadeIn', //effect triggered on showing new item
			'optionsIn' : {}, //additional options used in show transition			
			'speedIn' : 'normal', //effectIn speed			
			
			'effectOut' : 'fadeOut', //effect triggered on hiding old item
			'optionsOut' : {}, //additional options used in hide transition
			'speedOut' : 'normal' //effectOut speed
		};
		jQuery.extend(this.settings, options);

		this.$container = jQuery(el);
		this.build();
	};
	
	SFRotator.prototype.build = function(){
		
		this.$container.addClass('sfitems');
		
		this.$wrapper = jQuery('<div class="sfrotator" />');
		this.$container.before(this.$wrapper);
		this.$wrapper.append(this.$container);
		
		this.$controls = jQuery('<ul class="sfcontrols" />');
		this.$wrapper.append(this.$controls);
		
		this.$items = this.$container.children(this.settings.item);
		this.$current = this.$items.index(this.$items.filter('.'+this.settings.activeClass));
	
		//in case there are no items marked as active in the code
		if (this.$current < 0) {
			this.$current = 0;
		}
		
		var self = this;
		
		this.$items.addClass('sfitem').each(function(index, item){
			var trigger = jQuery('<li><a href="#">'+parseInt(index+1,10)+'</a></li>');
			self.$controls.append(trigger);
			//attach rotator item to controls trigger
			trigger.find('a').data('item',item).bind('click', { self : self }, self.trigger);
		});
		
		this.activate(this.$current, true);
		
		//auto rotation
		if (this.settings.autorotate) {
			this.autorotate();
		}
		
	};
	
	/**
	 * Function triggered by click on controls item
	 */
	SFRotator.prototype.trigger = function(event){
		event.preventDefault();
		var self = event.data.self;
		
		self.stopAutorotate();
		self.$rotationTerminated = true;
		
		var position = self.$items.index(jQuery(this).data('item'));
		self.activate(position);
	};
	
	/**
	 * Activate item identified by position
	 */
	SFRotator.prototype.activate = function(position) {
		
		var instant = arguments[1] || false;
		
		var activeClass = this.settings.activeClass;
		
		var oldItem = this.$items.eq(this.$current);
		var newItem = this.$items.eq(position);
		
		var onHide = function(){
			oldItem.removeClass(activeClass);
		};
		
		var onShow = function(){
			newItem.addClass(activeClass).css('zIndex', 10);
		};
		
		var effects = ['blind', 'bounce', 'clip', 'drop', 'explode', 'fold', 'highlight', 'puff', 'pulsate', 'scale', 'shake', 'size', 'slide', 'transfer'];
		
		//instant change
		if (instant === true) {
			oldItem.removeClass(activeClass).hide();
			newItem.addClass(activeClass).show();			
		}
		else {
			//advanced UI effect
			if (jQuery.inArray(this.settings.effectOut, effects) > -1) {
				oldItem.hide(this.settings.effectOut, this.settings.optionsOut, this.settings.speedOut, onHide);
			}
			//regular effect - fadeIn, fadeOut, slideUp, slideDown, show, hide
			else if(jQuery.isFunction(oldItem[this.settings.effectOut])) {		
				oldItem[this.settings.effectOut](this.settings.speedOut, onHide);
			}
			else {
				throw "Unsupported hide transition";
			}
			
			//place new item on top of the stack
			newItem.css('zIndex', 100);
			
			//advanced UI effect			
			if (jQuery.inArray(this.settings.effectIn, effects) > -1) {
				newItem.show(this.settings.effectIn, this.settings.optionsIn, this.settings.speedIn, onShow);
			}
			//regular effect - fadeIn, fadeOut, slideUp, slideDown, show, hide			
			else if(jQuery.isFunction(newItem[this.settings.effectIn])) {
				newItem[this.settings.effectIn](this.settings.speedIn, onShow);
			}
			else {
				throw "Unsupported show transition";
			}			
		}
		
		//update controls state
		this.$controls.find('a').removeClass('active').eq(position).addClass('active');
		
		this.$current = position;
	};

	/**
	 * enable autorotate on elements
	 */
	SFRotator.prototype.autorotate = function(){
		this.$rotationTerminated = false;
		
		var self = this;
		
		this.$container.mouseenter(function(){
			self.stopAutorotate();
		});
		
		this.$container.mouseleave(function(){									
			self.startAutorotate();
		});
		
		this.startAutorotate();
	};
	
	SFRotator.prototype.startAutorotate = function(){
		if (this.$rotationTerminated === true) {
			return;
		}

		var self = this;
		this.$rotationInterval = window.setInterval(function(){
			var next = self.$current + 1;
			if ( next === self.$items.length) {
				next = 0;	
			}
			self.activate(next);
		}, this.settings.duration);
	};
	
	
	SFRotator.prototype.stopAutorotate = function(){
		if (this.settings.autorotate) {
			window.clearInterval(this.$rotationInterval);
		}
	};
	
	//attach as jQuery plugin
	jQuery.fn.sfrotator = function(options){
		options = options || {};
		
		return this.each(function(){
			var r = new SFRotator(this, options);
		});
	};
})();