/**
 * 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
              
               '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));
    
          if (this.$current == -1) {
               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
          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(){
          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);
          });
     };
})();
