/*
    Copyright 2008 Thierry Dulieu (http://www.linuance.com/)
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/
(function($) {
    //---------------------------------------------------------------------------
    // $.transition plugin class
    //---------------------------------------------------------------------------
    $.transition = function($el, settings)
    {
        this.settings = settings;
        this.current = 0;
        this.slideshowRunning = false;
        this.thumbstripOffset = 0;
        
        var self = this;
        
        if ($el.is('ul') || $el.is('ol')) {
            // create gallery from HTML code
            this.$thumbnails = $el;
            this.count = $('li', $el).size();
        } else if (this.settings.images && this.settings.images.length > 0) {
            // create gallery from plugin settings
            this.$thumbnails = $('<ul></ul>');
            $.each(this.settings.images, function(i, data) {
                var title = data.title ? ' title="' + data.title + '"' : '';
                self.$thumbnails.append('<li><a href="' + data.image + '"' + title + '><img src="' + data.thumb + '" alt="" /></a></li>');
            });
            $el.append(this.$thumbnails);
            this.count = this.settings.images.length;
        } else {
            // nothing to display ?
            return;
        }
        
        // clicking on a thumbnail display the corresponding image
        $('a', this.$thumbnails).each(function(i) {
            $(this).attr('rel', i).click(function(evt) {
                evt.preventDefault();
                evt.stopPropagation();
                self.stopSlideshow();
                self.displayImage(parseInt($(this).attr('rel')), true);
                return false;
            });
        });
        
        if (typeof(this.settings.thumbSize) == 'number') {
            this.thumbWidth = this.settings.thumbSize;
            this.thumbHeight = this.settings.thumbSize;
        } else {
            this.thumbWidth = this.settings.thumbSize.width;
            this.thumbHeight = this.settings.thumbSize.height;
        }
        
        // build the gallery structure around the thumbnails list
        var $wrapper = $(HTML).width(this.settings.width);
        this.$thumbnails.before($wrapper);
        this.$thumbstrip = $('.transition-thumbstrip', $wrapper)
            .prepend(this.$thumbnails)
            .width(this.settings.width)
            .height(this.thumbHeight);
        
        // get references on some gallery elements
        this.$image = $('img:eq(0)', $wrapper);
        this.$caption = $('.transition-caption', $wrapper);
        this.$previousButton = $('.transition-prev', $wrapper).hide();
        this.$slideshowButton = $('.transition-slideshow', $wrapper).hide();
        this.$nextButton = $('.transition-next', $wrapper).hide();
        this.$backwardButton = $('.transition-backward', $wrapper).hide();
        this.$forwardButton = $('.transition-forward', $wrapper).hide();
        
        // set attributes and css properties
        $('.transition-view', $wrapper).width(this.settings.width).height(this.settings.height);
        var $title = $('.transition-title', $wrapper).text(this.$thumbnails.attr('title') || this.settings.title || 'jQuery Transition');
        
        if ($.browser.msie) {
            // IE7 is unable to handle correctly alpha transparency and css opacity
            $('.transition-view a', $wrapper).css({opacity: '.67'});
            self.$backwardButton.css({opacity: '.67'});
            self.$forwardButton.css({opacity: '.67'});
        }
        
        // bind main view controls with their respective action
        this.$previousButton.click(function() {
            self.stopSlideshow();
            self.displayPreviousImage();
        });
        this.$nextButton.click(function() {
            self.stopSlideshow();
            self.displayNextImage();
        });
        this.$slideshowButton.click(function() {
            if (self.slideshowRunning) {
                self.stopSlideshow();
            } else {
                self.displayNextImage(true);
            }
        });
        
        // buind thumbstrip controls with their respective action
        this.$backwardButton.click(function() {
            self.stopSlideshow();
            self.moveThumbstrip(-self.settings.thumbs);
        });
        this.$forwardButton.click(function() {
            self.stopSlideshow();
            self.moveThumbstrip(self.settings.thumbs);
        });
    
        // show or hide controls depending on mouse position
        $wrapper.hover(
            function() {
                if (self.settings.displayCaption) {
                    self.$caption.animate({marginBottom: 0}, 'fast');
                }
                if (self.settings.displayTitle) {
                    $title.animate({marginTop: 0}, 'fast');
                }
                $('.transition-view a', $wrapper).fadeIn('fast');
                self.$backwardButton.fadeIn('fast');
                self.$forwardButton.fadeIn('fast');
            },
            function() {
                if (self.settings.displayCaption) {
                    self.$caption.animate({marginBottom: '-3em'}, 'slow');
                }
                if (self.settings.displayTitle) {
                    $title.animate({marginTop: '-3em'}, 'slow');
                }
                $('.transition-view a', $wrapper).fadeOut('slow');
                self.$backwardButton.fadeOut('slow');
                self.$forwardButton.fadeOut('slow');
            }
        );
        
        if (this.settings.autoRun) {
            this.current = -1;
            this.displayNextImage(true);
        } else {
            this.displayImage(0, false);
        }
    };
    
    //---------------------------------------------------------------------------
    // loads an image with the given src attribute
    //---------------------------------------------------------------------------
    $.transition.prototype.loadImage = function(img, src, callback)
    {
        $(img).load(function() {
            $(this).css({
                marginLeft : -$(this).width()  / 2,
                marginTop  : -$(this).height() / 2
            }).show();
            if (callback) callback();
        }).hide().attr('src', src);
    };
    
    //---------------------------------------------------------------------------
    // displays the image with the given index with or without fading effect
    //---------------------------------------------------------------------------
    $.transition.prototype.displayImage = function(index, effect)
    {
        var $link = $('a:eq(' + index + ')', this.$thumbnails);
        
        if (effect) {
            var self = this;
            var $shadow = $('<img src=""/>').css({zIndex: 0});
            this.$image.css({zIndex: 1}).after($shadow);
            
            this.loadImage($shadow, $link.attr('href'), function() {
                self.$image.animate({opacity: 0}, self.settings.transitionTime, function() {
                    self.$image.remove();
                    self.$image = $shadow;
                });
            });
        } else {
            this.loadImage(this.$image, $link.attr('href'));
        }
        var title = (index + 1) + '/' + this.count;
        if ($link.attr('title')) {
            title += ' - ' + $link.attr('title');
        }
        this.$caption.text(title);
        
        this.current = index;
        var offset = index - Math.floor(this.settings.thumbs / 2);
        this.displayThumbstrip(offset);
        this.maintainControls();
    };
    
    //---------------------------------------------------------------------------
    // displays the previous image
    //---------------------------------------------------------------------------
    $.transition.prototype.displayPreviousImage = function()
    {
        var index = this.current - 1;
        if (index <= 0) {
            index = 0;
        }
        this.displayImage(index, true);
    };
    
    //---------------------------------------------------------------------------
    // displays the next image
    //---------------------------------------------------------------------------
    $.transition.prototype.displayNextImage = function(slideshowMode)
    {
        var index= this.current + 1;
        if (index > this.count - 1) {
            if (slideshowMode) {
                index = 0;
            } else {
                index = this.count - 1
            }
        }
        if (slideshowMode) {
            var self = this;
            this.slideshowRunning = setTimeout(function() {
                self.displayNextImage(true);
            }, self.settings.displayTime);
        }
        this.displayImage(index, true);
    };
    
    //------------------------------------------------------------------------------
    // stops the slideshow animation
    //------------------------------------------------------------------------------
    $.transition.prototype.stopSlideshow = function()
    {
        if (this.slideshowRunning) {
            clearTimeout(this.slideshowRunning);
            this.slideshowRunning = false;
        }
        this.$slideshowButton.removeClass('transition-stop');
    };
    
    //---------------------------------------------------------------------------
    // moves the thumbstrip by the given offset
    //---------------------------------------------------------------------------
    $.transition.prototype.displayThumbstrip = function(offset) {
                
        if (offset < 0) {
            offset = 0;
        } else if (offset > this.count - this.settings.thumbs) {
            offset = this.count - this.settings.thumbs;
        }
        
        var width = 1 + this.settings.width / this.settings.thumbs;
        
        // outlines the current thumb
        $('.transition-current', this.$thumbnails).remove();
        var $outerFrame = $('<span class="transition-current"></span>');
        var $innerFrame = $('<span></span>');
        
        $outerFrame.width(this.thumbWidth - 4).height(this.thumbHeight - 4);
        $innerFrame.width(this.thumbWidth - 8).height(this.thumbHeight - 8);
        $('li:eq(' + this.current + ')', this.$thumbnails).append($outerFrame.append($innerFrame));
        
        // set the thumbstrip position
        if (offset != this.thumbstripOffset) {
            this.$thumbnails.animate({marginLeft: (-width * offset) + 'px'}, 'fast');
            this.thumbstripOffset = offset;
            this.maintainControls();
        }
    };
    
    //---------------------------------------------------------------------------
    // moves the thumbstrip by the given offset
    //---------------------------------------------------------------------------
    $.transition.prototype.moveThumbstrip = function(offset) {
        var newOffset = this.thumbstripOffset + offset;
        this.displayThumbstrip(newOffset);
    };

    //---------------------------------------------------------------------------
    // maintain main view control buttons
    //---------------------------------------------------------------------------
    $.transition.prototype.maintainControls = function()
    {
        if (this.current == 0) {
            this.$previousButton.addClass('transition-disabled');
        } else {
            this.$previousButton.removeClass('transition-disabled');
        }
        if (this.current == this.count - 1) {
            this.$nextButton.addClass('transition-disabled');
        } else {
            this.$nextButton.removeClass('transition-disabled');
        }
        if (this.slideshowRunning) {
            this.$slideshowButton.addClass('transition-stop');
        } else {
            this.$slideshowButton.removeClass('transition-stop');
        }
        
        if (this.thumbstripOffset == 0) {
            this.$backwardButton.addClass('transition-disabled');
        } else {
            this.$backwardButton.removeClass('transition-disabled');
        }
        if (this.thumbstripOffset >= this.count - this.settings.thumbs) {
            this.$forwardButton.addClass('transition-disabled');
        } else {
            this.$forwardButton.removeClass('transition-disabled');
        }
    };
    
   //---------------------------------------------------------------------------
    // instanciates $.transition class for each matched element
    //---------------------------------------------------------------------------
    $.fn.transition = function(settings)
    {
        var opts = $.extend({}, $.fn.transition.defaults, settings);
        
        return this.each(function() {
            var $this = $(this);
            var o = $.meta ? $.extend({}, opts, $this.data()) : opts;
            new $.transition($this, o);
        });
    };
    
    //---------------------------------------------------------------------------
    // plugin default settings
    //---------------------------------------------------------------------------
    $.fn.transition.defaults = {
        title: '',             // Gallery title
        images: null,          // A list of images to display
        autoRun: true,        // Autorun slideshow ?
        displayTime: 5000,     // How long an image is displayed
        transitionTime: 1000,  // Duration of the fade in/fade out effect
        width: 900,            // Maximum width of the gallery images
        height: 600,           // Maximum height of the gallery images
        thumbs: 10,               // Number of thumbnails to display
        thumbSize: 76,         // Size of each thumbnail
        displayTitle: false,    // Display the gallery title
        displayCaption: false   // Display the images caption
    };

    var HTML = '<div class="transition"><div class="transition-view"><img src="clear.gif" /><p class="transition-title"></p><p class="transition-caption"></p><a class="transition-prev" href="javascript:;"><span>Previous</span></a><a class="transition-slideshow" href="javascript:;"><span>Start/stop slideshow</span></a><a class="transition-next" href="javascript:;"><span>Next</span></a></div><div class="transition-thumbstrip"><a class="transition-backward" href="javascript:;"><span>Backward</span></a><a class="transition-forward" href="javascript:;"><span>Forward</span></a></div></div>';
})(jQuery);
