/*
  jquery.qlgallery v0.0.4
  https://github.com/quickleft/ql_gallery
*/
(function($){
  $.fn.qlgallery = function(options) {
    var settings = $.extend({}, $.fn.qlgallery.defaultOptions, options),

    qlgallery = function() {
      var _timer,

      $this  = $(this),
      _time  = new Date().getTime(),
      id     = ( !! $this.attr('id') ) ? $this.attr('id') : "gal_"+_time,
      _index = 0,
      images = $this.children(),
      width  = $this.width(),
      height = $this.height,
      length = images.length * width,
      viewer = $("<div>", { "id": "viewer" + _time, "class": "ql_gallery_viewer", "style": "width:2000em;" }),

      api = {

        // Public - Sets up the target element by wrapping it in the viewer
        // object, contionally setting its ID, setting css props on
        //            the viewer. Also adds controls and autoplay hooks.
        //
        // Returns a modified instance of the jQuery object, exposing the 
        init: function(){
          // Give the target a unique ID if it doesn't have one alreay
          if( $this.attr('id') !== id ) {
            $this.attr('id', id);
          }

          // Wrap the images with a container
          images.wrapAll(viewer);

          // And store a reference to the viewer
          viewer = $('#viewer'+_time);

          // Set viewer offest to account for added images
          viewer.css('left', '-'+width+'px');

          // Clone first and last elements
          images.eq(0).clone().appendTo(viewer);
          images.eq(images.length-1).clone().prependTo(viewer);

          // Set length to be cached images.length
          length = images.length;

          // Iterate over the controls object and append them to the Wrapper
          $.each( settings.controls, function(k, elem){
            if( elem.href == "#play" && !settings.play ) { return; }
            $("<a>", elem).appendTo($this);
          });

          $this.delegate('a', 'click', api.animate );
          $this.find('.play').bind('click', api.autoplay);

          if( !!settings.autoplay ) {
            var speed = ( typeof settings.autoplay == "number" ) ? settings.autoplay : 8e3,
                autoplay = function(){
                  if( !!_timer ) { return false; }
                  $this.find('.play').trigger('click');
                };

            setTimeout(autoplay, speed);
          }

          this.qlgallery = api;
          return this;
        },

        // Public - Event handler for gallery controls, but only expects the
        //          class `next` or `back`
        //
        // Returns a call to animate() on the viewer object
        animate: function(e) {
          if( viewer.is(':animated') === true ) {
            return false;
          }

          var el, done,
              flavor = $(this).attr('class'),

              animation_settings = {},
              callback_settings  = {},

              forward = '-='+ width +'px',
              back    = '+='+ width +'px';

            if( flavor == "next" ) {
              animation_settings.left = forward;
              callback_settings.left = back;

              // Set the global index
              _index = (_index + 1) % length;

              el = '> :first-child';

              // Add forward element to end of list
              images.eq(_index).clone().appendTo(viewer);
            }

            if( flavor == "back" ){
              animation_settings.left = back;
              callback_settings.left = forward;

              // Set the global index
              _index = _index - 1 < 0 ?
                      length + (_index - 1):
                      (_index - 1) % length;

              el = '> :last';
            }

            done = function(){
              // Remove un-needed element
              viewer.find(el).remove();

              // Add backwards element to front of list
              if( flavor == "back" ){
                images.eq(_index - 1).clone().prependTo(viewer);
              }

              // Adjust css for the added elem
              viewer.animate(callback_settings, 0);

              // If a callback is present call it with the viewer's jQuery context and some helpful arguments
              if( $.isFunction(settings.callback) ) {
                return settings.callback.apply(this, [_index, viewer.css('left')]);
              }
            };

            return viewer.animate( animation_settings, settings.speed, settings.easing, done );
        },


        // Public - starts the autoplay
        start: function() {
          var speed = ( typeof settings.play == "number" ) ? settings.play : 8e3;
          $this.find('.next').trigger('click');
          _timer = setTimeout(api.start, speed);
        },

        // Public - Event handler for the play / pause button
        autoplay: function( e ){
          if( !!_timer ) {
            clearTimeout(_timer);
            _timer = null;
            $(e.target).text('Play');
          } else {
            api.start();
            $(e.target).text('Stop');
          }
          // stops propogation
          return false;
        }
      };

      return api.init();
    };

    return this.each( qlgallery );
  };

  $.fn.qlgallery.defaultOptions = {
    speed: 600,
    easing: false,
    slides: 1,
    play: false,
    autoplay: false,
    infinite: true,
    callback: false,
    controls: [ { 'href': "#back", 'class': 'back', 'text': "Back" },
              { 'href': "#next", 'class': 'next', 'text': "Next" },
              { 'href': "#play", 'class': 'play', 'text': "Play" } ]
  };
})(jQuery);

