/*
* Lightbox jQuery Plugin
* by Erik Friend
*
* Got a back-end image serving script with resize capability?  Use this lightbox.
*
* A simple lightbox plugin with a unique feature not found in other popular lightboxes.
* This lightbox can maximize the lightbox size to fit the browser window and pass image
* dimension arguments to a backend image resizing script.  Enable/disable maximization
* via 'maximize' option.
*
* Activate lightbox by calling lightbox() method on image links.
*
* $('#gallery a').lightbox({ maximize: true });
*/

(function($) {

    // plugin definition
    $.fn.lightbox = function(options) {
        // build main options before element iteration
        var opts = $.extend({}, $.fn.lightbox.defaults, options);

        // instantiate the lightbox
        $.lightboxinstance = $.lightboxinstance || new $.lightboxclass();

        // maximize image dimensions to window size if maximize option is set.
        if (opts.maximize) { $.lightboxinstance.maximize(); }

        // each image link becomes an imageclass in lightboxinstance.images
        return this.each(function() {
            var link = $(this);

            // create an imageclass for this image link
            var image = new imageclass;
            image.index  = $.lightboxinstance.images.length;
            image.group  = link.attr('rel')   || image.group;
            image.src    = link.attr('src')   || link.attr('href') || image.src;
            image.title  = link.attr('title') || link.attr('alt')  || image.title;
            image.width  = null; image.height = null; image.loaded = false;
            if ((s = image.title.indexOf(': ')) > 0) {
                image.description = image.title.substring(s + 2) || image.description;
                image.title = image.title.substring(0, s) || image.title;
            }
            // append the imageclass to the lightboxinstance images array
            $.lightboxinstance.images.push(image);

            // image link now opens a lightbox instead of direct linking
            link.unbind().click(function() { image.loaded = false; $.lightboxinstance.show(image); return(false); });
        });
    };

    // defaults
    $.fn.lightbox.defaults = {
        maximize: true
    };
    
    $.lightboxclass = function () {
        return this;        
    }
    $.extend($.lightboxclass.prototype, {
        images:[],
        current_image:false,
        is_open:false,
        is_maximized:false,
        suffix:'',

        // LIGHTBOX FUNCTIONS
        // BEGIN show->open?->show->preload?->show->boxresize?->show:DONE
        show:function (image) {
            // Show an image in the lightbox
            // This requires several steps completed in order
            // Uncompleted steps interrupt this function, and then return once completed.
            
            // Is lightbox markup present?  No?  Go create it and come back later.
            if ($.lightboxinstance.is_open === false) { $.lightboxinstance.open(image); return(false); }

            // Existing image should fade out while new one loads
            $('#lightbox-image').hide();

            // Is image ready to display?  No?  Go preload it and come back later.
            if (image.loaded != (image.src + $.lightboxinstance.suffix)) { $.lightboxinstance.preload(image); return(false); }

            // Is lightbox sized properly?  No?  Resize and center it then come back.
            if ($.lightboxinstance.boxfits(image) === false) { $.lightboxinstance.boxresize(image); return(false); }

            // Place image into lightbox
            $('#lightbox-image').attr('src', image.src + $.lightboxinstance.suffix).fadeIn(250, function () { $('#lightbox-previous, #lightbox-next').show(); });

            // lightboxinstance now references active image
            $.lightboxinstance.currentimage = image;

            return(true);
        },

        boxresize:function (image) {
            var border = 5;
            var $window = $(window);
            var new_width = image.width + (border * 2);
            var new_height = image.height + (border * 2);
            var new_left = ($window.width() / 2) - (new_width / 2);
            var new_top = ($window.height() / 2) - (new_height / 2) + $(window).scrollTop();
            $('#lightbox-content').stop().animate({ width: new_width - (border * 2), height: new_height - (border * 2) }, 500);
            $('#lightbox-previous').stop().animate({ width: (new_width - (border * 2)) / 2, height: new_height - (border * 2) }, 500);
            $('#lightbox-next').stop().animate({ width: (new_width - (border * 2)) / 2, height: new_height - (border * 2) }, 500);
            $('#lightbox').stop().animate({ left: new_left, top: new_top, width: new_width, height: new_height }, 500, function () { $.lightboxinstance.show(image); });
            delete $window;
        },

        preload:function (image) {
            // Preload an image
            preload = new Image();
            preload.onload = function() {
                // Once loaded, transfer some properties back to lightboxinstance.images array
                image.loaded = image.src + $.lightboxinstance.suffix;
                image.width  = preload.width;
                image.height = preload.height;
                // Proceed
                $.lightboxinstance.show(image);
            };
            // Start preloading
            preload.src = image.src + $.lightboxinstance.suffix;
        },
        
        open:function (image) {
            // Add lightbox markup to the DOM
            // Clear existing lightbox, just in case
            $('#lightbox, #lightbox-overlay').remove();
            // Add overlay w/close link
            $('body').append('<div id="lightbox-overlay"><a id="lightbox-close" href="#"><span>Click to close</span></a></div>');
            // Streth overlay to fill long pages
            $('#lightbox-overlay').height($(document).height());
            // Add lightbox w/loading image & nav links
            $('body').append('<div id="lightbox"><div id="lightbox-pad"><div id="lightbox-content"><div id="lightbox-image-wrap"><img id="lightbox-image" /></div><a id="lightbox-previous" href="#">Previous</a><a id="lightbox-next" href="#">Next</a></div></div></div>');

            // Center the lightbox in window
            $.lightboxinstance.boxcenter();
            
            // Attach handlers for next/previous/close actions  
            $('#lightbox-overlay, #lightbox-close').unbind().click(function (e) {
                e.preventDefault();
                $.lightboxinstance.close();
            });
            $('#lightbox-previous').unbind().click(function (e) {
                e.preventDefault();
                var prev_image = $.lightboxinstance.previous();
                if (prev_image == false) { $.lightboxinstance.close(); } 
                else { $.lightboxinstance.show(prev_image); }
            });
            $('#lightbox-next').unbind().click(function (e) {
                e.preventDefault();
                var next_image = $.lightboxinstance.next();
                if (next_image == false) { $.lightboxinstance.close(); } 
                else { $.lightboxinstance.show(next_image); }
            });

            // Hide the lightbox initially
            $('#lightbox, #lightbox-previous, #lightbox-next, #lightbox-overlay').hide();
            
            // If the window resizes, update the overlay and image size (if maximized)
            $(window).unbind().resize(function () {
                $.lightboxinstance.resize();
            });

            // Proceed
            $('#lightbox-overlay').css('opacity', .8).fadeIn(250, function () {
                $('#lightbox').fadeIn(250, function () {
                    $.lightboxinstance.show(image);
                });
            });

            // Lightbox is now opened
            $.lightboxinstance.is_open = true;
        },

        // Close the lightbox and remove it's markup from the dom.
        close:function () {
            $.lightboxinstance.stop();
            // Remove lightbox markup
            $('#lightbox, #lightbox-overlay').remove();
            // Lightbox is now closed
            $.lightboxinstance.is_open = false;
        },

        // Interrupt current image load.  Called before next/previous/close actions.
        stop:function () {
            // Stop any animations
            $('#lightbox-content').stop();
            $('#lightbox-previous').stop();
            $('#lightbox-next').stop();
            $('#lightbox-pad').stop();
            $('#lightbox').stop();
            // Prevent image-load completion from triggering display cycle
            if (preload.onload != undefined) { preload.onload = null; }
        },

        // UTILITY FUNCTIONS
        maximize:function () {
            $.lightboxinstance.suffix = ($(window).width() - 100) + '/' + ($(window).height() - 100);
            $.lightboxinstance.is_maximized = true;
        },

        unmaximize:function () {
            $.lightboxinstance.suffix = '';
            $.lightboxinstance.is_maximized = false;
        },

        // Moves lightbox to center of window using animation
        boxcenter:function () {
            var $window = $(window);
            var $lightbox = $('#lightbox');
            var new_left = ($window.width() / 2) - ($lightbox.width() / 2);
            var new_top = ($window.height() / 2) - ($lightbox.height() / 2) + $(window).scrollTop();
            $lightbox.animate({ left: new_left, top: new_top }, 500);
            delete $lightbox;
            delete $window;
        },

        boxfits:function (image) {
            var $lightbox = $('#lightbox-content');
            if (($lightbox.width() == image.width) && ($lightbox.height() == image.height)) { delete $lightbox; return(true); }
            else { delete $lightbox; return(false); }
        },

        // Recenter and resize (if necessary) lightbox and refresh image
        resize:function () {
            $.lightboxinstance.boxcenter();
            if ($.lightboxinstance.is_maximized) { $.lightboxinstance.maximize(); }
            $.lightboxinstance.stop();
            $.lightboxinstance.show($.lightboxinstance.current());
        },

        // NAVIGATION
        first:function () {
            return $.lightboxinstance.images[0];
        },
        previous:function () {
            var n = $.lightboxinstance.currentimage.index - 1;
            if (n < 0) { return false; }
            return $.lightboxinstance.images[n];
        },
        current:function () {
            return $.lightboxinstance.images[$.lightboxinstance.currentimage.index];
        },
        next:function () {
            var n = $.lightboxinstance.currentimage.index + 1;
            if (n > ($.lightboxinstance.images.length - 1)) { return false; }
            return $.lightboxinstance.images[n];
        },
        last:function () {
            return $.lightboxinstance.images[$.lightboxinstance.images.length];
        }
    });

    function imageclass () {
        return {
            index:       -1,
            group:       'default',
            src:         '',
            title:       'Untitled',
            description: '',
            width:       null,
            height:      null,
            loaded:      false
        }
    };

})(jQuery);
