/**
 * jQuery Gallery Plugin
 *   http://code.google.com/p/jquery-gallery-plugin/
 *
 * Copyright (c) 2009 Yusuke Horie
 *
 * Released under the MIT License:
 * http://www.opensource.org/licenses/mit-license.php
 *
 * Since  : 0.1.0 - 08/02/2009
 * Version: 0.3.0 - 08/25/2009
 */
(function(jQuery) {

    /** private properties **/

    var _inc = 0;

    /** public methods **/

    jQuery.fn.gallery = function(options) {
        var options = jQuery.extend({}, jQuery.fn.gallery.defaults, options);

        return this.each(function(i, e) {
            var 
        $this = jQuery(e),
        id = options.prefix + _inc,
        i = 0,
        n = 0,
        limit = 5,
        step = 1,
        duration = Math.ceil(options.interval * 0.3),
        timeId = null;

            var height;
            if (!options.height) {
                if (!parseInt($this.css('height'), 10)) {
                    height = '368px';
                } else {
                    height = $this.height();
                }
            } else {
                height = options.height;
            }

            var 
        width = (!options.width) ? $this.width() : options.width,
        paddingTop = parseInt($this.css('padding-top'), 10),
        paddingBottom = parseInt($this.css('padding-bottom'), 10),
        pheight = parseInt(height, 10),
        contentHeight = pheight - options.thumbHeight + paddingTop,
        o = $this.offset(),
        barWidth = jQuery(window).width() - o.left;

            // thumbnail bar
            var barTop = (options.barPosition == 'top') ? paddingTop : contentHeight;

            if (options.toggleBar) {
                if (options.barPosition == 'top') {
                    $this.hover(
            function() {
                $('#thumbnails_' + id).animate({ top: paddingTop }, { queue: false, duration: 300 });
            },
            function() {
                $('#thumbnails_' + id).animate({ top: barTop }, { queue: false, duration: 300 });
            });
                    barTop = (options.thumbHeight + paddingTop) * (-1);
                } else {
                    var outerHeight = pheight + paddingTop + paddingBottom;
                    $this.hover(
            function() {
                $('#thumbnails_' + id).animate({ top: contentHeight }, { queue: false, duration: 300 });
            },
            function() {
                $('#thumbnails_' + id).animate({ top: outerHeight }, { queue: false, duration: 300 });
            });
                    barTop = outerHeight;
                }
            }

            $this
        .css({
            width: width,
            height: height,
            zIndex: options.zIndex
        })
        .prepend('<div id="' + id + '"></div>')
        .find('ul')
          .attr('id', 'thumbnails_' + id)
          .addClass(options.barClass)
          .css({
              top: barTop,
              height: options.thumbHeight + 'px',
              //width: barWidth + 'px',
              width: '1000px',
              zIndex: options.zIndex + 2000,
              borderColor: 'white',
              borderWidth: '1px'
          })
          .find('li')
            .css({
                width: options.thumbWidth + 'px',
                height: options.thumbHeight + 'px'
            })
            .each(function(index) {
                jQuery.data(this, 'index', index);
            })
            .click(function(event) {
                event.preventDefault();
                if (options.slideshow) clearInterval(timeId);

                if ($.isFunction(options.onSelect))
                    options.onSelect.apply(this, [event]);

                var $e = this;
                bar.find('li').each(function(index, e) {
                    if (e == $e) {
                        step = index;
                        return false;
                    }
                });

                i = jQuery.data(this, 'index');

                // pre load
                for (var j = i; j < i + limit; j++) {
                    var o = pictures.eq(j);
                    if (o.length > 0 && typeof o.data('loaded') == 'undefined') {
                        preLoad(o.attr('href'));
                        o.data('loaded', true);
                    }
                }

                display();
                if (options.slideshow)
                    timeId = setInterval(display, options.interval);
            });

            if (options.showOverlay) {
                var 
          itop = pheight * (1 - options.ratio) + paddingTop,
          ileft = $this.css('padding-left'),
          iheight = (pheight * options.ratio) + paddingTop;

                // screen
                $('<div />')
          .addClass(options.screenClass)
          .css({
              opacity: 0.5,
              top: itop,
              left: 0,
              height: iheight,
              width: $this.outerWidth(),
              zIndex: options.zIndex + 1000
          })
          .insertAfter('#' + id);

                $('<div />')
          .addClass(options.infoClass)
          .html('<div id="gtitle_' + id + '" class="' + options.titleClass + '" style="display:none;"></div>' +
            '<div id="gdesc_' + id + '" class="' + options.descClass + '" style="display:none;"></div>')
          .css({
              top: '5px', //hardcode top margin of title-description div
              height: '40px', //hardcode height of title-description div
              width: '1000px',
              marginLeft: 'auto', //center div
              marginRight: 'auto', //center div
              zIndex: options.zIndex
          })
          .insertAfter('#gallery-bottom'); //edit position of title and description

                /*
                $('<div />')
                .addClass(options.infoClass)
                .html('<div id="gtitle_' + id + '" class="' + options.titleClass + '" style="display:none;"></div>' +
                '<div id="gdesc_' + id + '" class="' + options.descClass + '" style="display:none;"></div>')
                .css({
                top: itop,
                left: 0,
                height: iheight,
                zIndex: options.zIndex + 1500
                })
                .insertAfter('#' + id);
                */
            }

            // content container
            var c = jQuery('#' + id).css({
                position: 'relative',
                width: width,
                height: height,
                overflow: 'hidden'
            }).addClass(options.contentClass);

            var 
        bar = $this.find('ul').show(),
        thumbnails = bar.find('img'),
        pictures = $this.find('a').bind('click.gallery', function(e) { e.preventDefault(); }),
        gtitle = $('#gtitle_' + id),
        gdesc = $('#gdesc_' + id),
        len = thumbnails.length,
        w = $this.find('li:first').outerWidth(true);

            var display = function() {
                var t = thumbnails.eq(i);
                var pict = pictures.eq(i);
                var p = pict.attr('href');
                var pid = id + '_' + i;

                // pre load
                var next = pictures.eq(i + limit);
                if (next.length > 0 && typeof next.data('loaded') == 'undefined') {
                    preLoad(next.attr('href'));
                }

                // delete previous picture
                c.find('img').animate({ opacity: 0.0 }, {
                    queue: false,
                    duration: duration,
                    easing: 'linear',
                    complete: function() { jQuery(this).remove(); }
                });

                // append new picture
                jQuery('<img />')
          .attr('src', p)
          .attr('id', pid)
          .css({
              position: 'absolute',
              top: 0,
              left: 0,
              opacity: 1.0
          })
          .bind('click.gallery', function(event) {
              options.onClick.apply(this, [event, pict.get()]);
          })
          .appendTo('#' + id)
          .animate({ opacity: 1.0 }, {
              queue: false,
              duration: duration,
              easing: 'linear'
          })
          .load(function() {
              pict.data('loaded', true);
          });

                var title = t.attr('title');
                var id_of_desc = pict.attr('rel');
                var desc = (id_of_desc && $('#' + id_of_desc).length > 0)
          ? $('#' + id_of_desc).html() : pict.attr('title');

                if (n != 0) {
                    // title
                    if (typeof title != 'undefined')
                        gtitle.fadeOut(duration * 0.3, function() {
                            jQuery(this).html(title).show();
                        });

                    // description
                    if (typeof desc != 'undefined')
                        gdesc.fadeOut(duration * 0.3, function() {
                            jQuery(this).html(desc).show();
                        });

                    // scrolle
                    /*
                    bar.animate({left: w*(-1)*step}, {
                    queue: false,
                    duration: 300,
                    easing: options.easing,
                    complete: function () {
                    var $t = jQuery(this).css({left: 0});
                    var f = $t.find('li').slice(0, step);
                    var indexes = f.map(function () {
                    return jQuery.data(this, 'index');
                    });
                    var cln = f.clone(true).each(function (j) {
                    jQuery.data(this, 'index', indexes[j]);
                    }).hide().appendTo(this).fadeIn(duration);
                    f.remove();
                    step = 1;
                    }
                    });
                    */
                } else {
                    // title & description
                    if (typeof title != 'undefined') gtitle.html(title).show();
                    if (typeof desc != 'undefined') gdesc.html(desc).show();
                }

                options.onChange.apply($this.get(), [i, pict.get()]);

                if (i < (len - 1)) {
                    i++;
                } else {
                    i = 0;
                }
                n++;
            };

            // pre load
            for (var j = 0; j < limit; j++) {
                var o = pictures.eq(j);
                if (o.length > 0) {
                    preLoad(o.attr('href'));
                    o.data('loaded', true);
                }
            }

            display();
            if (options.slideshow)
                timeId = setInterval(display, options.interval);

            _inc++;
        });
    };

    jQuery.fn.gallery.defaults = {
        width: null,
        height: null,
        thumbWidth: 100,
        thumbHeight: 64,
        zIndex: 1000,
        interval: 4500,
        prefix: 'gallery_',
        easing: 'linear',
        ratio: 0.35,
        slideshow: true,
        toggleBar: true,
        showOverlay: true,
        barPosition: null,
        barClass: 'galleryBar',
        contentClass: 'galleryContent',
        infoClass: 'galleryInfo',
        screenClass: 'galleryScreen',
        titleClass: 'galleryTitle',
        descClass: 'galleryDesc',
        onClick: function() { return; },
        onSelect: function() { return; },
        onChange: function() { return; }
    };

    /** private methods **/

    var preLoad = function(url) {
        jQuery('<img />').attr('src', url);
    };

})(jQuery);