(function ($) {
  /**
   * simplde slider class
   * 
   * @param HTMLElement el the wrapping element
   * @param Object settings
   */
  function Slider(el, settings) {
    this.slider = el;
    this.settings = settings;
    this.index = this.settings.firstPage || 0;
    this.init();
    this.setPage(this.index);
    this.startAutoSlide();
  }
  
  
  /**
   * Starts the auto slide
   * 
   * @return void
   */
  Slider.prototype.startAutoSlide = function () {
    if (this.settings.autoSlide) {
      this.autoSlideTimeout = setTimeout($.proxy(function () {
        this.gotoPage(this.index + 1, undefined);
      }, this), this.settings.autoSlideDelay);
    }
  };
  
  
  /**
   * Stops the auto slide
   * 
   * @return void
   */
  Slider.prototype.stopAutoSlide = function () {
    clearTimeout(this.autoSlideTimeout);
  };
  

  
  /**
   * Initialises the slider
   * 
   * @return void
   */
  Slider.prototype.init = function () {
    this.sliderCarriage = $('.slider-carriage', this.slider);
    this.pages = $('.slider-page', this.slider);

    // correct carriage width
    $(this.sliderCarriage).css({
      width: 100 * this.pages.length + '%'
    });

    // correct page width
    $(this.pages).css({
      width: 100 / this.pages.length + '%'
    }).show();
    
    // init page controls
    this.pageControls = $('<ul>').appendTo('.slider-pages', this.slider);
    $(this.pages).each($.proxy(function (idx, el) {
      var li = $('<li />').appendTo(this.pageControls).on({
        click: $.proxy(function (evt) {
          this.gotoPage(
            $(evt.target).index()
          );
        }, this)
      });
    }, this));
    
    // init prev/next controls
    $('.slider-ctrl.slider-prev').on({
      click: $.proxy(function (evt) {
        this.gotoPage(this.index + 1);
      }, this)
    });
    
    $('.slider-ctrl.slider-next').on({
      click: $.proxy(function (evt) {
        this.gotoPage(this.index - 1);
      }, this)
    });
    
    
    // init auto-slide
    $('.slider-viewport', this.slider).on({
      // block autoslide on mouseenter
      mouseenter: $.proxy(this.stopAutoSlide, this),
      
      // reinit autoslide on mouseleave
      mouseleave: $.proxy(this.startAutoSlide, this)
    });
  };
  
  
  /**
   * Executes the slider animation
   * 
   * @param int index
   * @return int new index
   */
  Slider.prototype.gotoPage = function (index, duration, callback) {
    this.stopAutoSlide();
    this.index = index > this.pages.length - 1 ? 0 : (index < 0 ? this.pages.length - 1 : index);
    $('.slider-carriage').stop(false, false).animate({
      left: (-100 * $(this.pages[this.index]).position().left / $('.slider-viewport', this.slider).width()) + '%'
    }, duration !== undefined ? duration : this.settings.duration, $.proxy(function () {
      $('li', this.pageControls).removeClass('active').eq(this.index).addClass('active');
      this.startAutoSlide();
    }, this));
    
    return index;
  };
  
  
  /**
   * Goes to a specific page without animation
   * 
   * @param int index
   * @return int new index
   */
  Slider.prototype.setPage = function (index) {
    return this.gotoPage(index, 0);
  };

  
  /**
   * jQuery hook
   */
  $.fn.extend({
    slider: function (settings) {
      // init initial slider
      return $(this).each(function () {
        if (!$(this).data('slider')) {
          $(this).data('slider', new Slider(this, $.extend({}, $.slider.defaults, settings)))
        }
      });
    }
  });
  
  
  /**
   * plugin defaults
   */
  $.extend({
    slider: {
      defaults: {
        firstPage: 0,
        duration: 1000,
        autoSlide: true,
        autoSlideDelay: 2000
      }
    }
  });
}(jQuery));
