var Gallery = new Class({

    /**
    * Public function initialize
    * Constructor. Sets up each gallery on the page. Each gallery wrapper
    * element must have the class 'gallery' and contain one or more elements
    * with classes 'gallery-thumb' and only one element with the class
    * 'gallery-canvas'
    */
    initialize: function() {
        
        $$('.gallery').each(function(gallery) {
        
            var canvas = gallery.getElement('.gallery-canvas');
            
            // Create and cache a spinner for this canvas
            canvas.spinner = new Element('img', {'src': '/images/ajax-loader.gif',
                                               'class': 'gallery-spinner'});

            $$('.gallery-thumb').each(function(thumb) {
            
                if(thumb.hasClass('hidden')) {
                
                    gallery.hiddenThumb = thumb;
                    thumb.exhibit = canvas.getElement('.gallery-exhibit');
                    thumb.exhibit.set('tween', {link: 'cancel', duration: 'normal'});
                }
            
                var href = thumb.getProperty('href');
                thumb.meta = href.substring(href.indexOf('?') + 1).parseQueryString();
            
                // Add fx options
                thumb.set('tween', {link: 'cancel', duration: 'short'});

                // Add mouseover/out events
                thumb.addEvent('mouseover', this.thumbMouseOverHandler);
                thumb.addEvent('mouseout', this.thumbMouseOutHandler);
                
                // Add mouseclick event
                thumb.addEvent('click', this.thumbMouseClickHandler.bindWithEvent(this, [thumb, canvas, gallery]));
            
            }, this);

        }, this);
    },
    
    /**
    * Private function thumbMouseOverHandler
    * Fades a gallery-thumb to 50% opacity onmouseover
    *
    * @param evt Event Mootools event object
    */
    thumbMouseOverHandler: function(evt) {

        $$(evt.target).fade(0.5);
    },
    
    /**
    * Private function thumbMouseOutHandler
    * Fades a gallery-thumb to 100% opacity onmouseout
    *
    * @param evt Event Mootools event object
    */
    thumbMouseOutHandler: function(evt) {
    
        $$(evt.target).fade(1);
    },
    
    /**
    * Private function thumbMouseClickHandler
    * Shows a loaded image in the gallery-canvas or initiates a preload of an
    * image whilst immediately showing a loading spinner.
    *
    * @param evt Event Mootools event object
    * @param thumb HTMLELement The thumbnail that was clicked
    * @param canvas HTMLElement The gallery canvas to show the image in
    */
    thumbMouseClickHandler: function(evt, thumb, canvas, gallery) {
    
        // Invalidate the current loading exhibit
        canvas.currentExhibit = null;
    
        // Make thumb that was clicked on hidden
        thumb.addClass('hidden');
        gallery.hiddenThumb.replaces(thumb);
        gallery.hiddenThumb.removeClass('hidden');
        gallery.hiddenThumb = thumb;
    
        // Remove current exhibit
        //canvas.empty();

        // Has a preloaded exhibit element been cached?
        if(thumb.exhibit) {

            // Ensure current exhibit is hidden before it is injected
            thumb.exhibit.fade('hide');
        
            // Inject this exhibit replacing either another exhibit or a spinner
            thumb.exhibit.replaces(canvas.getFirst());
            
            thumb.exhibit.fade('in');
            
        } else {
        
            // Add loading spinner
            canvas.spinner.replaces(canvas.getFirst());
            
            switch(thumb.meta.type) {
            
                default:
                case 'image':
                
                    canvas.currentExhibit = new Element('img', {'src': '/images/' + thumb.meta.src,
                                                                'alt': thumb.meta.title});
                break;
                case 'xhtml':
                
                    canvas.currentExhibit = new Element('div');
                
                    // Load this HTML content into the canvas
                    canvas.currentExhibit.load('/xhtml/' + thumb.meta.src);
                
                break;
            }
            
            canvas.currentExhibit.set('tween', {link: 'cancel', duration: 'normal'});
            
            this.exhibitIsLoaded.delay(1000, this, [canvas.currentExhibit, thumb, canvas]);
        }
        
        // Stop the anchor href being navigated to!
        evt.preventDefault();
    },
    
    /**
    * Private function exhibitIsLoaded
    * Periodically checks if an exhibit has been loaded and injects the exhibit 
    * into the canvas if it has.
    *
    * @param evt Event Mootools event object
    * @param image HTMLElement The exhibit being preloaded
    * @param thumb HTMLELement The thumbnail that was clicked
    * @param canvas HTMLElement The gallery canvas to show the image in
    */
    exhibitIsLoaded: function(exhibit, thumb, canvas) {
    
        var isLoaded = false;

        // Determine if the content has been preloaded
        switch(thumb.meta.type) {
            
            default:
            case 'image':
            
                if(exhibit.complete) {
                
                    isLoaded = true;
                }

            break;
            case 'xhtml':
            
                if(exhibit.getChildren().length) {
                
                    isLoaded = true;
                }
            
            break;
        }
    
        // Inject if is loaded
        if(isLoaded == true) {
        
            // Cache
            thumb.exhibit = exhibit;
            
            // Check the exhibit we've loaded is in fact the exhibit we currently want to see
            if(canvas.currentExhibit == exhibit) {
            
                canvas.currentExhibit = null;
                
                // Ensure current exhibit is hidden before it is injected
                exhibit.fade('hide');
                
                // Insert into the canvas, replacing the spinner
                exhibit.replaces(canvas.getFirst());
                
                exhibit.fade('in');
            }

        } else {
        
            // Check again soon
            this.exhibitIsLoaded.delay(1000, this, [exhibit, thumb, canvas]);
        }
    }
});
