(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 = '300px';
                } 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: 320});
            },
            function() {
              $('#thumbnails_' + id).animate({top: barTop}, {queue: false, duration: 320});
                    });

                    barTop = (options.thumbHeight + paddingTop) * (-1);
                } else {
                    var outerHeight = pheight + paddingTop + paddingBottom;

                    $this.hover(

                    function () {
              $('#thumbnails_' + id).animate({top: contentHeight}, {queue: false, duration: 320});
            },
            function() {
              $('#thumbnails_' + id).animate({top: outerHeight}, {queue: false, duration: 300});
                    });

                    barTop = outerHeight;
                }
            }
	$(this).find('li:first').addClass('current');
      $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-1),
            height: options.thumbHeight + 'px',
            width: (jQuery(window).width()*3)+ 'px',//barWidth + 'px',
            zIndex: options.zIndex + 2000
          })

          .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+50),
            left: 0,
            height: iheight,
            width: $this.outerWidth(),
            zIndex: options.zIndex + 0
          })
          .insertAfter('#' + id);
		  */

        $('<div />')
          .addClass(options.infoClass)
          .html('<div id="gdesc_' + id + '" class="' + options.descClass + '" style="display:none;"></div>')
          .css({
            top: 40,
            left: 20,
            height: iheight,
			width: 350,
            zIndex: options.zIndex + 1500
          })
          .insertAfter('#' + id);

			$('<div />').addClass(options.screenClass).css({
				opacity: 0.5,
				top: 204,
				left: 0,
				height: 30,
				width: 633,
				zIndex: options.zIndex
			}).html('<div id="btnIntervene" title="Play/Pause" class="pause">Play/Pause</div>').insertAfter('#gdesc_' + id);
		  
            }

            // content container
            var c = jQuery('#' + id).css({
                position: 'relative',
                width: width,
                height: height,
                overflow: 'hidden'
            }).addClass(options.contentClass);

            $('div#btnIntervene').bind('click', function () {
                $(this).toggleClass("play");
                if ($(this).hasClass("play")) {
                    if (options.slideshow) clearInterval(timeId);
                } else {
                    if (options.slideshow) timeId = setInterval(display, options.interval);
                }
            });

            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)
		  .attr('alt', 'Careers - Our Culture - Sapient Government Services')
          .css({
                        position: 'absolute',
            top: 50,
            right: 28,
                        opacity: 0.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);
			  $t.find('.current').removeClass('current');
                                var indexes = f.map(function () {
                                    return jQuery.data(this, 'index');
                                });
                                var cln = f.clone(true).each(function (j) {
                                    jQuery.data(this, 'index', indexes[j]);
                                }).appendTo(this).fadeIn(duration);
                                f.remove();
                                step = 1;
			  $t.find('li:first').addClass('current');
                            }
                        });
                    } else {
                        // title & description
                        if (typeof title != 'undefined') gtitle.html(title).hide();
                        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: 94,
        thumbHeight: 81,
        zIndex: 0,
        interval: 4500,
        prefix: 'gallery_',
        easing: 'linear',
    ratio: 0.65,
        slideshow: true,
        toggleBar: false,
        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);
