/*
 * jQuery Foundation Clearing 1.2.1
 * http://foundation.zurb.com
 * Copyright 2012, ZURB
 * Free to use under the MIT license.
 * http://www.opensource.org/licenses/mit-license.php
*/

/*jslint unparam: true, browser: true, indent: 2 */

;(function ($, window, document, undefined) {
  'use strict';

  var defaults = {
        templates : {
          viewing : '<a href="#" class="clearing-close">&times;</a>' +
            '<div class="visible-img" style="display: none"><img src="#">' +
            '<p class="clearing-caption"></p><a href="#" class="clearing-main-left"></a>' +
            '<a href="#" class="clearing-main-right"></a></div>'
        },

        // comma delimited list of selectors that, on click, will close clearing, 
        // add 'div.clearing-blackout, div.visible-img' to close on background click
        close_selectors : 'a.clearing-close',

        // event initializers and locks
        initialized : false,
        locked : false
      },

      cl = {
        init : function (options, extendMethods) {
          return this.find('ul[data-clearing]').each(function () {
            var doc = $(document),
                $el = $(this),
                options = options || {},
                extendMethods = extendMethods || {},
                settings = $el.data('fndtn.clearing.settings');

            if (!settings) {
              options.$parent = $el.parent();

              $el.data('fndtn.clearing.settings', $.extend({}, defaults, options));

              cl.assemble($el.find('li'));

              if (!defaults.initialized) {
                cl.events($el);
                if (Modernizr.touch) cl.swipe_events();
              }

            }
          });
        },

        events : function (el) {
          var settings = el.data('fndtn.clearing.settings');

          $(document)
            .on('click.fndtn.clearing', 'ul[data-clearing] li', function (e, current, target) {
              var current = current || $(this),
                  target = target || current,
                  settings = current.parent().data('fndtn.clearing.settings');

              e.preventDefault();

              if (!settings) {
                current.parent().foundationClearing();
              }

              // set current and target to the clicked li if not otherwise defined.
              cl.open($(e.target), current, target);
              cl.update_paddles(target);
            })

            .on('click.fndtn.clearing', '.clearing-main-right', function (e) { cl.nav(e, 'next') })
            .on('click.fndtn.clearing', '.clearing-main-left', function (e) { cl.nav(e, 'prev') })
            .on('click.fndtn.clearing', settings.close_selectors, this.close)
            .on('keydown.fndtn.clearing', this.keydown);

          $(window).on('resize.fndtn.clearing', this.resize);

          defaults.initialized = true;
        },

        swipe_events : function () {
          $(document)
            .bind('swipeleft', 'ul[data-clearing]', function (e) { cl.nav(e, 'next') })
            .bind('swiperight', 'ul[data-clearing]', function (e) { cl.nav(e, 'prev') })
            .bind('movestart', 'ul[data-clearing]', function (e) {
              if ((e.distX > e.distY && e.distX < -e.distY) ||
                  (e.distX < e.distY && e.distX > -e.distY)) {
                e.preventDefault();
              }
            });
        },

        assemble : function ($li) {
          var $el = $li.parent(),
              settings = $el.data('fndtn.clearing.settings'),
              grid = $el.detach(),
              data = {
                grid: '<div class="carousel">' + this.outerHTML(grid[0]) + '</div>',
                viewing: settings.templates.viewing
              },
              wrapper = '<div class="clearing-assembled"><div>' + data.viewing + data.grid + '</div></div>';

          return settings.$parent.append(wrapper);
        },

        open : function ($image, current, target) {
          var root = target.closest('.clearing-assembled'),
              container = root.find('div:first'),
              visible_image = container.find('.visible-img'),
              image = visible_image.find('img').not($image);

          if (!cl.locked()) {

            // set the image to the selected thumbnail
            image.attr('src', this.load($image));

            image.loaded(function () {
              // toggle the gallery if not visible
              root.addClass('clearing-blackout');
              container.addClass('clearing-container');
              this.caption(visible_image.find('.clearing-caption'), $image);
              visible_image.show();
              this.fix_height(target);
              this.center(image);

              // shift the thumbnails if necessary
              this.shift(current, target, function () {
                target.siblings().removeClass('visible');
                target.addClass('visible');
              });
            }.bind(this));
          }
        },

        close : function (e) {
          e.preventDefault();

          var root = (function (target) {
                if (/blackout/.test(target.selector)) {
                  return target;
                } else {
                  return target.closest('.clearing-blackout');
                }
              }($(this))), container, visible_image;

          if (this === e.target && root) {
            container = root.find('div:first'),
            visible_image = container.find('.visible-img');

            defaults.prev_index = 0;

            root.find('ul[data-clearing]').attr('style', '')
            root.removeClass('clearing-blackout');
            container.removeClass('clearing-container');
            visible_image.hide();
          }

          return false;
        },

        keydown : function (e) {
          var clearing = $('.clearing-blackout').find('ul[data-clearing]');

          if (e.which === 39) cl.go(clearing, 'next');
          if (e.which === 37) cl.go(clearing, 'prev');
          if (e.which === 27) $('a.clearing-close').trigger('click');
        },

        nav : function (e, direction) {
          var clearing = $('.clearing-blackout').find('ul[data-clearing]');

          e.preventDefault();
          this.go(clearing, direction);
        },

        resize : function () {
          var image = $('.clearing-blackout .visible-img').find('img');

          if (image.length > 0) {
            cl.center(image);
          }
        },

        fix_height : function (target) {
          var lis = target.siblings();

          lis.each(function () {
              var li = $(this),
                  image = li.find('img');

              if (li.height() > image.outerHeight()) {
                li.addClass('fix-height');
              }
            })
            .closest('ul').width(lis.length * 100 + '%');
        },

        update_paddles : function (target) {
          var visible_image = target.closest('.carousel').siblings('.visible-img');

          if (target.next().length > 0) {
            visible_image.find('.clearing-main-right').removeClass('disabled');
          } else {
            visible_image.find('.clearing-main-right').addClass('disabled');
          }

          if (target.prev().length > 0) {
            visible_image.find('.clearing-main-left').removeClass('disabled');
          } else {
            visible_image.find('.clearing-main-left').addClass('disabled');
          }
        },

        load : function ($image) {
          var href = $image.parent().attr('href');

          this.preload($image);

          if (href) return href;
          return $image.attr('src');
        },

        preload : function ($image) {
          this.img($image.closest('li').next());
          this.img($image.closest('li').prev());
        },

        img : function (img) {
          if (img.length > 0) {
            var new_img = new Image(),
                new_a = img.find('a');

            if (new_a.length > 0) {
              new_img.src = new_a.attr('href');
            } else {
              new_img.src = img.find('img').attr('src');
            }
          }
        },

        caption : function (container, $image) {
          var caption = $image.data('caption');

          if (caption) {
            container.text(caption).show();
          } else {
            container.text('').hide();
          }
        },

        go : function ($ul, direction) {
          var current = $ul.find('.visible'),
              target = current[direction]();

          if (target.length > 0) {
            target.find('img').trigger('click', [current, target]);
          }
        },

        shift : function (current, target, callback) {
          var clearing = target.parent(),
              old_index = defaults.prev_index,
              direction = this.direction(clearing, current, target),
              left = parseInt(clearing.css('left'), 10),
              width = target.outerWidth(),
              skip_shift;

          // we use jQuery animate instead of CSS transitions because we
          // need a callback to unlock the next animation
          if (target.index() !== old_index && !/skip/.test(direction)){
            if (/left/.test(direction)) {
              this.lock();
              clearing.animate({left : left + width}, 300, this.unlock);
            } else if (/right/.test(direction)) {
              this.lock();
              clearing.animate({left : left - width}, 300, this.unlock);
            }
          } else if (/skip/.test(direction)) {

            // the target image is not adjacent to the current image, so
            // do we scroll right or not
            skip_shift = target.index() - defaults.up_count;
            this.lock();

            if (skip_shift > 0) {
              clearing.animate({left : -(skip_shift * width)}, 300, this.unlock);
            } else {
              clearing.animate({left : 0}, 300, this.unlock);
            }
          }

          callback();
        },

        lock : function () {
          defaults.locked = true;
        },

        unlock : function () {
          defaults.locked = false;
        },

        locked : function () {
          return defaults.locked;
        },

        direction : function ($el, current, target) {
          var lis = $el.find('li'),
              li_width = lis.outerWidth() + (lis.outerWidth() / 4),
              up_count = Math.floor($('.clearing-container').outerWidth() / li_width) - 1,
              target_index = lis.index(target),
              response;

          defaults.up_count = up_count;

          if (this.adjacent(defaults.prev_index, target_index)) {
            if ((target_index > up_count) && target_index > defaults.prev_index) {
              response = 'right';
            } else if ((target_index > up_count - 1) && target_index <= defaults.prev_index) {
              response = 'left';
            } else {
              response = false;
            }
          } else {
            response = 'skip';
          }

          defaults.prev_index = target_index;

          return response;
        },

        adjacent : function (current_index, target_index) {
          for (var i = target_index + 1; i >= target_index - 1; i--) {
            if (i === current_index) return true;
          }
          return false;
        },

        center : function (target) {
          target.css({
            marginLeft : -(target.outerWidth() / 2),
            marginTop : -(target.outerHeight() / 2)
          });
        },

        outerHTML : function (el) {
          // support FireFox < 11
          return el.outerHTML || new XMLSerializer().serializeToString(el);
        }

      };

  $.fn.foundationClearing = function (method) {
    if (cl[method]) {
      return cl[method].apply(this, Array.prototype.slice.call(arguments, 1));
    } else if (typeof method === 'object' || !method) {
      return cl.init.apply(this, arguments);
    } else {
      $.error('Method ' +  method + ' does not exist on jQuery.foundationClearing');
    }
  };

  // jquery.imageready.js
  // @weblinc, @jsantell, (c) 2012

  (function( $ ) {
    $.fn.loaded = function ( callback, userSettings ) {
      var
        options = $.extend( {}, $.fn.loaded.defaults, userSettings ),
        $images = this.find( 'img' ).add( this.filter( 'img' ) ),
        unloadedImages = $images.length;

      function loaded () {
        unloadedImages -= 1;
        !unloadedImages && callback();
      }

      function bindLoad () {
        this.one( 'load', loaded );
        if ( $.browser.msie ) {
          var
            src   = this.attr( 'src' ),
            param = src.match( /\?/ ) ? '&' : '?';
          param  += options.cachePrefix + '=' + ( new Date() ).getTime();
          this.attr( 'src', src + param );
        }
      }

      return $images.each(function () {
        var $this = $( this );
        if ( !$this.attr( 'src' ) ) {
          loaded();
          return;
        }
        this.complete || this.readyState === 4 ?
          loaded() :
          bindLoad.call( $this );
      });
    };

    $.fn.loaded.defaults = {
      cachePrefix: 'random'
    };

  }(jQuery));

}(jQuery, this, this.document));
