(function($) {
  $.extend($.fn, {
    setThumbnails: function(options, callback) {
      var panelWidth = options.thumbnail_width;
      var panelHeight = options.thumbnail_height;
      var borderColor = options.thumbnail_border_color;
      var borderSize = options.thumbnail_border_size;
      var highlightColor = options.thumbnail_highlight_color;
      var minOpacity = options.thumbnail_opacity;
      var maxOpacity = 1;
      this.each(function() {
        var li = $(this);
        li.css('overflow', 'hidden');
        li.css('border', borderColor + ' ' + borderSize + 'px solid');
        li.width(panelWidth);
        li.height(panelHeight);

        var img = li.find('img');
        img.css('cursor','pointer');
        img.hover(
          function() {
            if (!$(this).is('.active')) {
              $(this).stop().animate({'opacity':maxOpacity},{queue: false, duration: 200});
            }
          }, 
          function() {
            if (!$(this).is('.active')) {
              $(this).stop().animate({'opacity':minOpacity}, {queue: false, duration: 200});
            }
          }
        );
        img.bind('contextmenu', function() {return false; });
        img.click(function() {
          var image = $(this);
          if (!image.is('.active')) {
            var oldActive = image.parents('div.gallery:first').find('img.active');
            oldActive.removeClass('active');
            oldActive.css('opacity', minOpacity);
            oldActive.parent().css('border', borderColor + ' ' + borderSize + 'px solid');
            image.addClass('active');
            image.css('opacity', maxOpacity);
            image.parent().css('border', highlightColor + ' ' + borderSize + 'px solid');
            var bigImageSource = image.attr('rel');
            var title = image.attr('title');
            var desc = image.attr('alt');
            if (desc && desc != null) {
              desc = desc.replace('&lt;','<').replace('&gt;','>');
            }
            callback(bigImageSource, title, desc);
          }
        });
        img.css('opacity',minOpacity);
        if (img.width() != 0 && img.height() != 0) {
          var imgWidth = img.width();
          var imgHeight = img.height();

          var nImgHeight = panelHeight;
          var nImgWidth = (panelHeight / imgHeight) * imgWidth;
          if (nImgWidth < panelWidth) {
            nImgHeight = (panelWidth / imgWidth) * imgHeight;
            nImgWidth = panelWidth;
          }
          img.width(nImgWidth);
          img.height(nImgHeight);
        }
      });
    },
    scrollButton: function(type) {
      var activeClass = 'gallery-prev-active';
      if (type == 'next') {
        activeClass = 'gallery-next-active';
      }
      return this.hover(
        function() { if (!$(this).is('.gallery-disabled')) { $(this).addClass(activeClass);} },
        function() { if (!$(this).is('.gallery-disabled')) { $(this).removeClass(activeClass); } }
      );
    },
    gallery: function(options) {
      options = $.extend({
        thumbnail_width: 75,
        thumbnail_height: 50,
        thumbnail_opacity: 0.6,
        thumbnail_border_color: '#000',
        thumbnail_highlight_color: '#f00',
        thumbnail_border_size: 5,
        verticle: false,
        circular: true,
        visible: 3,
        speed: 250,
        flipSpeed: 250,
        slideSpeed: 300,
        start: 0,
        scroll: 1,
        onClick: null
      }, options || {});
      
      return this.each(function() {
        var running = false;
        var sizeCSS = options.verticle ? "height" : "width";
        var standardCSS = options.verticle ? "width" : "height";
        var posCSS = options.verticle ? "top" : "left";
        var gallery = $('<div class="gallery-main"></div>');
        var imagePanel = $('<div class="gallery-image-panel"></div>');
        var shadowBox = $('<div class="gallery-light-box"></div>');
        var imageContainer = $('<div class="gallery-container"></div>');
        var carousel = $('<div class="carousel"></div>');
        gallery.append(carousel);
        gallery.append(imagePanel);
        imagePanel.append(shadowBox);
        shadowBox.append(imageContainer);
        imageContainer.css('overflow', 'hidden');
        imageContainer.css('position', 'relative');
        imageContainer.width(shadowBox.innerWidth());
        imageContainer.height(shadowBox.innerHeight());

        var buttonPrev = $('<div class="gallery-prev-button"></div>');
        var buttonNext = $('<div class="gallery-next-button"></div>');
        buttonPrev.scrollButton('prev');
        buttonNext.scrollButton('next');
        if (!options.circular) {
          buttonPrev.addClass('gallery-disabled');
          buttonPrev.addClass('gallery-prev-disabled');
        }
        var thumbHolder = $('<div class="thumbnails"></div>');
        carousel.append(buttonPrev);
        carousel.append(thumbHolder);
        carousel.append(buttonNext);
        var ul = $(this);
        ul.replaceWith(gallery);
        var lis = $('div', ul);
        var liCount = lis.size();
        var v = options.visible;
        thumbHolder.append(ul);
        
        if (options.circular) {
          ul.prepend(lis.slice(liCount-v).clone());
          ul.append(lis.slice(0, v).clone());
          options.start += v;
        }
        lis = $('div', ul);
        liCount = lis.size();
        var curr = options.start;
        lis.setThumbnails(options, loadImage);
        
        thumbHolder.css({"overflow": "hidden","position":"relative"});
        var liSize = (options.verticle ? options.thumbnail_height : options.thumbnail_width) + (options.thumbnail_border_size * 2);
        var liStandardSize = (options.verticle ? options.thumbnail_width : options.thumbnail_height) + (options.thumbnail_border_size * 2);
        var ulSize = liSize * liCount;
        var divSize = liSize * v;

        ul.css({
          "position":'relative',
          "padding":'0px',
          "margin":'0px',
          "display":'block'
        }).css(sizeCSS, ulSize+'px').css(standardCSS, liStandardSize+'px').css(posCSS, '-'+(curr*liSize)+'px');
        thumbHolder.css(sizeCSS, divSize+'px');
        thumbHolder.css(standardCSS, liStandardSize+'px');

        buttonPrev.click(function() {
          if (!$(this).is('.gallery-disabled')) { return go(curr-options.scroll); }
          return false;
        });
        buttonNext.click(function() {
          if (!$(this).is('.gallery-disabled')) { return go(curr+options.scroll); }
          return false;
        });
        if (thumbHolder.mousewheel) {
          thumbHolder.mousewheel(function(e,d) {
            return d>0 ? go(curr-options.scroll) : go(curr+options.scroll);
          });
        }
        function loadImage(src, title, desc) {
          $('div.gallery-slider', imageContainer).remove();
          $('img', imageContainer).fadeOut(options.flipSpeed, function() { $(this).remove(); });
           
          imageContainer.unbind();
          shadowBox.addClass('loading');
          var img = new Image();
          $(img).load(function() {
            var image = $(this);
            shadowBox.removeClass('loading');
            image.hide();
            image.bind('contextmenu', function() { return false; });
            imageContainer.append(image);
            var container = $('<div class="container"></div>');
            var panelWidth = shadowBox.width();
            var panelHeight = shadowBox.height();
            var bw = panelWidth - 20;
            var bh = panelHeight - 20;
            var imgWidth = image.width();
            var imgHeight = image.height();
            var nImgWidth = (bh / imgHeight) * imgWidth;
            var nImgHeight = bh;
            if (nImgWidth > bw) {
              nImgWidth = bw;
              nImgHeight = (bw / imgWidth) * imgHeight;
            }
            image.width(nImgWidth);
            image.height(nImgHeight);
            image.css({'position':'absolute','z-index':'2', 'top':'0px', 'left':'0px'});
            imgWidth = nImgWidth + 4;
            imgHeight = nImgHeight + 4;

            var contAnim = {
              'top': ((panelHeight - imgHeight) / 2)+'px',
              'left': ((panelWidth - imgWidth) / 2)+'px',
              'width': nImgWidth + 'px',
              'height': nImgHeight + 'px'
            };
            imageContainer.css('border', options.thumbnail_border_color + ' 2px inset');
            
            imageContainer.animate(contAnim, options.flipSpeed);
            image.fadeIn(options.flipSpeed, function() {
              // set up div
              var titleDiv = $('<div class="gallery-slider"></div>');
              titleDiv.append("<h2>"+title+"</h2>");
              if (desc && desc.length > 0) {
                titleDiv.append("<p>"+desc+"</p>");
              }
              titleDiv.css({
                'position':'absolute',
                'z-index':'1',
                'width':(nImgWidth-20)+'px',
                'padding':'10px',
                'left':'0px'
              });
              imageContainer.append(titleDiv);
              var titleHeight = titleDiv.height() + 10;
              var titleTop = nImgHeight - titleHeight;
              titleDiv.css({'top':titleTop + 'px', 'height': titleHeight+'px'});
              imageContainer.hover(
                function() { 
                  $('img', this).stop().animate({'top': -titleHeight+'px'}, {queue: false, duration: options.slideSpeed}); 
                },
                function() { 
                  $('img', this).stop().animate({'top': '0px'}, {queue: false, duration: options.slideSpeed}); 
                });
            });
          });
          $(img).attr('title', title);
          $(img).attr('src', src);
        };
        function go(to) {
          if (!running) {
            if (options.circular) {
              if (to <= options.start-v-1) {
                // if first, goto last
                ul.css(posCSS, -((liCount-(v*2))*liSize)+'px');
                curr = (to == options.start-v-1 ? liCount-(v*2)-1 : liCount-(v*2)-options.scroll);
              } else if (to >= liCount-v+1) {
                // if last, goto first
                ul.css(posCSS, -(v * liSize)+'px');
                curr = (to == liCount-v+1 ? v+1 : v+options.scroll);
              } else {
                curr = to;
              }
            } else {
              if (to < 0) {
                to = 0;
              } else if (to > liCount-v) {
                to = liCount - v;
              }
              if (curr == to) return;
              curr = to;
            }

            running = true;
            var animation = {};
            if (posCSS == 'left') {
              animation.left = -(curr*liSize);
            } else {
              animation.top = -(curr*liSize);
            }
            ul.animate(animation, {duration: options.speed, easing: options.easing, complete: function() { running = false; }});
            if (!options.circular) {
              buttonPrev.removeClass('gallery-disabled');
              buttonPrev.removeClass('gallery-prev-disabled');
              buttonNext.removeClass('gallery-disabled');
              buttonNext.removeClass('gallery-next-disabled');
              if (curr == 0) {
                buttonPrev.addClass('gallery-disabled');
                buttonPrev.addClass('gallery-prev-disabled');
                buttonPrev.removeClass('gallery-prev-active');
              } else if (curr == (liCount - v)) {
                buttonNext.addClass('gallery-disabled');
                buttonNext.addClass('gallery-next-disabled');
                buttonNext.removeClass('gallery-next-active');
              }
            }
          }
          return false;
        };
      });
    }
  });
})(jQuery);

