(function($) {
  
  function Scroller(element, options) {
  
    var settings = $.extend({
      'slide': 'li',
      'cycle': 1,
      'frequency': 4000,
      'animation': 'fade',
      'easingSpeed': '500',
      'controls' : Array('prev', 'items', 'next'),
      'hover': false,
      'reverse': false}, options || {});
  
    //setup variables
    var obj = this, $obj = $(this);
    var $element = $(element);
    
    obj.activeClass = 'scroller-active';
    obj.nextClass = 'scroller-next';
    obj.prevClass = 'scroller-prev';
    obj.element = element;
    
    var slides = $(settings.slide, element);
    var cycle = settings.cycle;
    var animationIds = new Array ();
    var animation = settings.animation;
    var forward = !settings.reverse;
    var currentPosition = 0;
    var slideWidth = $(slides).eq(0).outerWidth(true);
    
    if (animation == 'slide') {
      $(slides).parent().width((slideWidth * $(slides).length) + 'px');
    }
    
    this.totalSlides = function () {
      return parseInt(slides.length);
    };
    
    this.setAnimation = function (animationType) {
      if (animationType == 'slide') {
        
      } else {
        animation = 'fade';
      }
    }
    
    var getCurrentSlide = function () {
      return $(slides).filter('.'+obj.activeClass);
    };
    
    var setCurrentSlide = function (objSlide) {
      $(slides).removeClass(obj.activeClass);
      $(objSlide).addClass(obj.activeClass);
      return objSlide;
    };
    
    var getNextSlide = function () {
      return $(slides).filter('.'+obj.nextClass);
    };
    
    var setNextSlide = function (objSlide) {
      $(slides).removeClass(obj.nextClass);
      $(objSlide).addClass(obj.nextClass);
      return objSlide;
    };
    
    var getPrevSlide = function () {
      return $(slides).filter('.'+obj.prevClass);
    };
    
    var setPrevSlide = function (objSlide) {
      $(slides).removeClass(obj.prevClass);
      $(objSlide).addClass(obj.prevClass);
      return objSlide;
    };
    
    this.animateNext = function () {

      var nextSlide;
      
      if (currentPosition+(1*cycle) < this.totalSlides()) {
        currentPosition += (1*cycle);
        nextSlide = $(slides).eq(currentPosition); 
      } else {
        currentPosition = 0;
        nextSlide = $(slides).eq(currentPosition); 
      } 
      
      setNextSlide(nextSlide);
      
      this.animate();
    }
    
    this.animatePrev = function () {
      var prevSlide;
      
      if (currentPosition-(1*cycle) >= 0) {
        currentPosition -= (1*cycle);
        prevSlide = $(slides).eq(currentPosition); 
      } else {
        //find last position within cycle
        var last = this.totalSlides()-1;
        while (last%cycle != 0) {
          last -= 1
        }
        currentPosition = last;
        prevSlide = $(slides).eq(currentPosition); 
      }
      
      setNextSlide(prevSlide);
      
      this.animate();
    }
    
    this.animateTo = function (index) {
      
      if (index == currentPosition) { return false}
      currentPosition = index;
      setNextSlide(slides.eq(currentPosition));
      
      this.animate();
    }
    
    this.animate = function (obj) {
      if (animation == 'slide') {
        this.animationSlide();
      } else {
        this.animationFade();
      }
    }
    
    this.animationFade = function () {
      
      var nextSlide = getNextSlide();
      var currentSlide = getCurrentSlide();
      var prevSlide = setPrevSlide($(currentSlide));
      var speed = 300;
      
      if (animationIds.length > 0) {
        speed = settings.easingSpeed;
      }
      
      currentSlide = setCurrentSlide(nextSlide);
      prevSlide = getPrevSlide();
      
      $(currentSlide).stop(true, true).css('opacity', 1).show();
      $(prevSlide).stop(true, true).css('opacity', 1).show().fadeTo(speed, 0);

    };
    
    this.animationSlide = function () {
      
      var nextSlide = getNextSlide();
      var currentSlide = getCurrentSlide();
      var prevSlide = setPrevSlide($(currentSlide));
      var speed = 300;
      
      currentSlide = setCurrentSlide(nextSlide);
      prevSlide = getPrevSlide();
      
      $(slides).parent().animate({
        'left' : slideWidth*(-currentPosition)
      });
    };
    
    this.start = function () {
      if (slides.length > 1 && $(animationIds).length == 0) {
        animationIds.push(setInterval(function () {
          if (forward)
            obj.animateNext();
          else
            obj.animatePrev();
        }, settings.frequency));
      }
    };
    
    this.stop = function () {
      $(animationIds).each(function () {
        clearInterval(animationIds.shift());
      });
    };
    
    var setControls = function () {
      
      var controls = settings.controls;
      var hover = settings.hover;
      
      if (hover) {
        $(element).hover(function(){
          obj.stop();
        }, function(){
          obj.start();
        })
      }

      if (controls) {
        var contolsMarkup = $('<ul class="scroller-controls">');
        
        if ($.inArray("prev", controls) >= 0) {
          $(contolsMarkup).append($('<li class="scroller-control scroller-control-prev">').append(($('<a class="icon icon-previous">Previous</a>').click(function() {
            obj.animatePrev();
            return false;
          }))));
        } 
        
        if ($.inArray("items", controls) >= 0) {
          slides.each(function(index) {
            $(contolsMarkup).append($('<li class="scroller-control scroller-control-item">').append(($('<a class="scroller-item">' + parseInt(index+1) + '</a>').click(function() {
              obj.animateTo(parseInt(index));
              return false;
            }))));  
          })
        }
        
        if ($.inArray("next", controls) >= 0) {
          $(contolsMarkup).append($('<li class="scroller-control scroller-control-next">').append(($('<a class="icon icon-next">Next</a>').click(function() {
            obj.animateNext();
            return false;
          }))));
        }
        
        $(element).append(contolsMarkup);
        
      }
    };

    //Setup Initial Slide
    setCurrentSlide($(slides).eq(0));
    setControls();
    
    //Setup Slide
    
  };
  
  jQuery.fn.scroller = function (options) {
    
    return this.each(function(){
			
      var element = $(this);
      if (element.data('scroller')) return;
      if (isNaN(options.cycle)) options.cycle = 1;

      if ($(options.slide, element).length <= 1*options.cycle) return false;
      
      var scroller = new Scroller(this, options);
      //scroller.start()
      element.data('scroller', scroller);
    });
    
  };
})(jQuery);
