(function($){
  $.FreestyleSlideshow = function( element, options ){
    var default_options = {
      left_trigger: '.left',
      right_trigger: '.right',
      snapshots: '.snaps li',
      main_container: '.main',
      snap_image: 'img',
      start_position: 0,
      snaplist_css_attr: 'margin-left',
      snapToImageHook: function( snapList ){
        var imageList = [];

        $.each( snapList, function( i, snap ){
          var $snap  = $( snap );
          var $image = $( new Image() );
          $image.attr( 'src', $snap.attr( 'src' ).replace( /tiny\.(jpg|jpeg|png|gif)/i, '.$1' ) );
          imageList.push( $image );
        });

        return imageList;
      }
    };

    this.options  = $.extend( default_options, options );
    this.$element = $( element );
    this.initialize();
  };

  $.FreestyleSlideshow.prototype.extend = $.extend;


  $.FreestyleSlideshow.prototype.extend({ 
    initialize: function(){
      this.$left      = this.$element.find( this.options.left_trigger );
      this.$right     = this.$element.find( this.options.right_trigger );
      this.$snaps     = this.$element.find( this.options.snapshots );
      this.$snapList  = this.$snaps.parent();
      this.$main      = this.$element.find( this.options.main_container );

      this.imageList = this.options.snapToImageHook( this.$snaps.find( this.options.snap_image ) );
      this.current   = this.options.start_position;

      this.$left.click( $.proxy( this.left, this ) );
      this.$right.click( $.proxy( this.right, this ) );
      this.$snaps.click( $.proxy( this.changeTo, this ) );

      this.prepareDOM();
      this.computeLimit();

      this.changeTo( this.current );
    },


    prepareDOM: function(){
      var sliderWidth = this.$snapList.width();
      this.$snapList.wrap( '<div class="sliderContainer" />' );
      this.$sliderContainer = $( this.$snapList.parent() );

      this.$sliderContainer.css({ 
        position: 'relative',
        overflow: 'hidden',
        width: sliderWidth
      });


      var totalWidth = 0;

      this.$snaps.each( function( i, snap ){ 
        totalWidth       += $( snap ).width();
      });

      this.$snapList.css({ 
        width: totalWidth + 500
      });

      this.$snaps.each( function( i, snap ){ 
        snap.initial_pos  = $( snap ).position().left;
      });
    },


    left: function( event ){
      event.preventDefault();
      event.stopPropagation();
      this.current = ( this.current - 1 >= 0 ? this.current - 1 : this.limit );
      this.slideTo( this.current );
    },


    right: function( event ){
      event.preventDefault();
      event.stopPropagation();
      this.current = ( this.current + 1 <= this.limit ? this.current + 1 : 0 );
      this.slideTo( this.current );
    },


    slideTo: function( i ){
      var prop = {};

      if ( i <= this.limit ){
        prop[ this.options.snaplist_css_attr ] = -( this.$snaps.eq(i)[0].initial_pos );
      }

      else {
        prop[ this.options.snaplist_css_attr ] = -( this.$snaps.eq( this.limit )[0].initial_pos );
      }

      this.$snapList.animate( prop );
    },


    changeTo: function( option ){
      /*
      var i;

      if ( option.target ){
        option.stopPropagation();
        option.preventDefault();

        var target = $( option.target ).parents( 'li' )[0];

        this.$snaps.each( function( index, snap ){
          if ( target == snap ){
            i = index;
          }
        });
      }

      else {
        i = option;
      }

      var $image = this.imageList[i].clone();
      this.$main.find( 'img' ).remove();
      //this.$main.append( $image );
      //$image.hide();
      //$image.fadeIn();
      */
    },


    computeLimit: function(){
      var righter   = this.$snaps.last()[0].initial_pos + this.$snaps.last().width();
      var viewWidth = this.$sliderContainer.width();
      var limit     = null;

      this.$snaps.each( function( i, snap ){ 
        if ( snap.initial_pos - $( snap ).width() + viewWidth > righter && limit === null ){
          limit = i;
        }
      });

      this.limit = limit;
    }
  });


  $.fn.freestyleSlideshow = function( options ){
    return this.each( function(){
      ( new $.FreestyleSlideshow( this, options ) );
    });
  };
})(jQuery);

