(function () {
    // We define a type to represent the functionality of our slideshows.
    function PhotoSlideshow(jq_ul) {
        this.ul = jq_ul;
        this.photos = jQuery('li', jq_ul);
        this.num_photos = this.photos.length;
        
        this.current_photo_index = -1;
        this.current_interval = null;
        this.current_timeout = null;
        
        // The time to wait before showing the next slide.
        this.advance_time = 4500;

        // The time to wait after a click before starting to auto-advance again.
        this.pause_time = 5000;
        
        this.init();
    } 
    
    PhotoSlideshow.prototype.init = function() {
        var show_obj = this;
		
        // Set photos to appear on top of one another
        this.ul.css('position', 'relative');
        this.photos.css('position', 'absolute');
        this.photos.css('left', '0');
        this.photos.css('top', '0');
        
        // Create the photo carousel navigation.
        var ul = jQuery("<ul class='nav dl_navigation'>");
        ul.append(jQuery("<li class='prev'/>").append(
            jQuery("<a class='hiddenText' href='#'>Previous</a>").click(function () {
                show_obj.pauseSlideshow();
                show_obj.previousPhoto();
                return false;
                })));
        this.photos.each(function(index) {
            var link_obj = jQuery(
                "<a href='#' title='"+
                $('p.caption', this).text() + " - " + $('p.credit', this).text()+
                "'>"+(index+1)+"</a>"
                );
            ul.append(jQuery("<li/>").append(
                link_obj.click(function() {
                    show_obj.pauseSlideshow();
                    show_obj.showPhoto(index);
                    return false;
                    })));
        })
        ul.append(jQuery("<li class='next'/>").append(
            jQuery("<a class='hiddenText' href='#'>Next</a>").click(function() {
                show_obj.pauseSlideshow();
                show_obj.nextPhoto();
                return false;
                })));
                ul.append(jQuery("<li class='pause'/>").append(
                    jQuery("<a class='hiddenText' href='#'>Pause</a>").toggle(
                          function () {
                              show_obj.stopSlideshow();
                              return false;
                          },
                          function () {
                              show_obj.startSlideshow();
                              return false;

                          }
                        )));

        this.ul.after(ul);        
        
        // Collect the links we just made.
        this.links = jQuery('li', ul);
        
        // Hide all but the first photo.
        this.photos.hide();
        this.showPhoto(0);
        this.startSlideshow();
    }
    
    PhotoSlideshow.prototype.flushTimers = function() {
        if (this.current_timeout) clearTimeout(this.current_timeout);
        if (this.current_interval) clearInterval(this.current_interval);
        this.current_timeout = this.current_interval = null;
    }
    
    PhotoSlideshow.prototype.startSlideshow = function() {
        var show_obj = this;
        this.flushTimers();
        this.current_interval = setInterval(function() {
            show_obj.nextPhoto();
            }, this.advance_time);
    }
    
    PhotoSlideshow.prototype.stopSlideshow = function() {
        var show_obj = this;
        this.flushTimers();
    }
    
    PhotoSlideshow.prototype.pauseSlideshow = function() {
        var show_obj = this;
        this.flushTimers();
        this.current_timeout = setTimeout(function() {
            show_obj.startSlideshow();
            }, this.pause_time = this.advance_time);
    }
    
    PhotoSlideshow.prototype.showPhoto = function(photo_index) {
        if (this.current_photo_index >= 0) {
            var old_photo = jQuery(this.photos[this.current_photo_index]);
            old_photo.css('z-index', 0);
            old_photo.fadeOut('slow');
            jQuery(this.links[this.current_photo_index+1]).removeClass('selected');
        }

        var new_photo = jQuery(this.photos[photo_index]);
        new_photo.css('z-index', 1);
        new_photo.fadeIn('slow');
        this.current_photo_index = photo_index;
        
        // Select the appropriate navigation link
        jQuery(this.links[photo_index+1]).addClass('selected');
    }
    
    PhotoSlideshow.prototype.nextPhoto = function() {
        var next_photo_index = (this.current_photo_index + 1) % this.num_photos;
        this.showPhoto(next_photo_index);
    }
    
    PhotoSlideshow.prototype.previousPhoto = function() {
        var prev_photo_index = 
            (this.current_photo_index - 1 + this.num_photos) % this.num_photos;
        this.showPhoto(prev_photo_index);
    }

    // Expose the jquery plugin method
    jQuery.fn.slideshow = function() {
        this.each(function() {
            new PhotoSlideshow(jQuery(this));
        });    
    };
    
})();