﻿var Slideshow = new function()
{
    // Private Members
    var caption = null;
    var closeButton = null;
    var currentSource = null;
    var imageDetails = null;
    var initialized = false;
    var navigation = null;
    var navigationCaption = null;
    var navigationSeparator = null;
    var nextButton = null;
    var overlayOpacity = 0.8;
    var overlay = null;
    var previousButton = null;
    var self = this;
    var slide = null;
    var slideshowContainer = null;
    var slideshowLoadingIcon = null;
    var slideshowSets = [];


    // Private Methods
    function AddSource(_element)
    {
        var setName = _element.readAttribute('rel');

        if (!slideshowSets[setName])
        {
            slideshowSets[setName] = new Array();
        }

        slideshowSets[setName].push(new Source(_element));
    }

    function Dispose()
    {
        // Stop the slideshow if we're in one
        self.StopSlideshow();

        // Dispose of all the sources
        slideshowSets.each(function(mySet)
        {
            for (var i = 0, length = mySet.length; i < length; ++i)
            {
                mySet[i].Dispose();
            }
        });

        // Clear the sets out
        slideshowSets.clear();
        slideshowSets = [];
    }

    function HideOverlay()
    {
        //Hide the container
        slideshowContainer.setStyle({ display: 'none' });

        // Hide the loading image
        slideshowLoadingIcon.setStyle({ display: 'none' });

        // Fade out the overlay
        new Effect.Opacity(overlay, { from: 0.7, to: 0.0, duration: 0.3, afterFinish: function() { overlay.setStyle({ display: 'none' }); } });
    }

    function LoadImage()
    {
        // Hide the slideshow container
        slideshowContainer.setStyle({ display: 'none' });

        // Reset the caption width
        caption.setStyle({ width: 'auto' });

        // Show the loading image
        slideshowLoadingIcon.setStyle({ display: 'inline' });

        // Set the caption or hide the caption element
        caption.setStyle({ display: (currentSource.Caption.length > 0 ? 'block' : 'none') }).update(currentSource.Caption);

        // Set the navigation caption
        if (slideshowSets[currentSource.SetName].length > 1)
        {
            navigationCaption.update('Image ' + (currentSource.SetPosition + 1) + ' of ' + slideshowSets[currentSource.SetName].length);
        }

        // Show or hide the navigation buttons
        nextButton.setStyle({ display: (currentSource.SetPosition < slideshowSets[currentSource.SetName].length - 1) ? 'inline' : 'none' });
        previousButton.setStyle({ display: (currentSource.SetPosition > 0) ? 'inline' : 'none' });
        navigationSeparator.setStyle({ display: (currentSource.SetPosition > 0 && currentSource.SetPosition < slideshowSets[currentSource.SetName].length - 1) ? 'inline' : 'none' });

        // Set the url of the image
        slide.src = currentSource.ImageUrl;
    }

    function ShowOverlayAndLoadImage()
    {
        // Set the opacity to 0 and display to block
        overlay.setStyle({ opacity: 0.0, display: 'block' });

        // Now fade in the overlay
        new Effect.Opacity(overlay, { from: 0.0, to: 0.7, duration: 0.3, afterFinish: LoadImage });
    }


    // Priviledged Methods
    this.Initialize = function()
    {
        if (!initialized)
        {
            overlay = new Element('div', { 'class': 'Slideshow_Overlay' });
            slideshowContainer = new Element('div', { 'class': 'Slideshow_Container' });
            slideshowLoadingIcon = new Element('img', { 'class': 'Slideshow_LoadingIcon', 'src': '/Images/Icons/Loading.gif' });
            slide = new Element('img', { 'class': 'Slideshow_Slide' });
            imageDetails = new Element('div', { 'class': 'Slideshow_ImageDetails' });
            navigation = new Element('div', { 'class': 'Slideshow_Navigation' });
            navigationCaption = new Element('span', { 'class': 'Slideshow_NavigationCaption' });
            previousButton = new Element('a', { 'class': 'Slideshow_PreviousButton', 'href': '#' }).update('Previous');
            navigationSeparator = new Element('span', { 'class': 'Slideshow_NavigationSeparator' }).update('|');
            nextButton = new Element('a', { 'class': 'Slideshow_NextButton', 'href': '#' }).update('Next');
            closeButton = new Element('a', { 'class': 'Slideshow_CloseButton', 'href': '#' }).update('Close');
            caption = new Element('div', { 'class': 'Slideshow_Caption' });

            // Build the overlay and slideshow markup
            $(document.body).insert(overlay);
            $(document.body).insert(slideshowLoadingIcon);
            $(document.body).insert(slideshowContainer);
            slideshowContainer.insert(slide);
            slideshowContainer.insert(imageDetails);
            imageDetails.insert(navigation);
            imageDetails.insert(caption);
            navigation.insert(navigationCaption);
            navigation.insert(previousButton);
            navigation.insert(navigationSeparator);
            navigation.insert(nextButton);
            navigation.insert(closeButton);

            /* sample html */
            /*
            <div class="Slideshow">
            <img />
            <div class="ImageDetails">
            <div class="Navigation"><span class="NavigationCaption">Image 1 of 5</span><a class="PreviousButton">Previous</a><span class="NavigationSeparator">|</span><a class="NextButton">Next</a><a class="CloseButton">close</a></div>
            <div class="Caption">Caption</div>                
            </div>            
            </div>
            */

            // Attach all the event handlers
            previousButton.observe('click', PreviousButton_Click);
            nextButton.observe('click', NextButton_Click);
            closeButton.observe('click', CloseButton_Click);
            overlay.observe('click', Overlay_Click);
            slide.observe('load', Slide_Loaded);
        }
        else
        {
            // We need to dispose of current sources and re-parse the dom
            Dispose();
        }

        // Find all the slideshow links
        var anchors = $$('a');

        // loop through all anchor tags
        for (var i = 0, length = anchors.length; i < length; ++i)
        {
            var anchor = anchors[i];
            var relAttribute = String(anchor.readAttribute('rel'));

            // use the string.match() method to catch 'slideshow' references in the rel attribute
            if (anchor.readAttribute('href') && (relAttribute.toLowerCase().match('slideshow')))
            {
                AddSource(anchor);
            }
        }

        initialized = true;
    }

    this.ShowImage = function(source)
    {
        if (source)
        {
            currentSource = source;

            // Show the overlay if it's not already shown
            if (overlay.getStyle('display') != 'block')
            {
                ShowOverlayAndLoadImage();
            }
            else
            {
                LoadImage();
            }
        }
    }

    this.StopSlideshow = function()
    {
        currentSource = null;

        // Hide the slideshow container
        new Effect.Opacity(slideshowContainer, { from: 1.0, to: 0.0, duration: 0.3, afterFinish: HideOverlay });
    }


    // Event Handlers
    function CloseButton_Click(e)
    {
        Slideshow.StopSlideshow();
        e.stop();
    }

    function NextButton_Click(e)
    {
        // Hide the slideshow container
        new Effect.Opacity(slideshowContainer, { from: 1.0, to: 0.0, duration: 0.3, afterFinish: function() { Slideshow.ShowImage(slideshowSets[currentSource.SetName][currentSource.SetPosition + 1]); } });

        e.stop();
    }

    function PreviousButton_Click(e)
    {
        // Hide the slideshow container
        new Effect.Opacity(slideshowContainer, { from: 1.0, to: 0.0, duration: 0.3, afterFinish: function() { Slideshow.ShowImage(slideshowSets[currentSource.SetName][currentSource.SetPosition - 1]); } });

        e.stop();
    }

    function Overlay_Click(e)
    {
        Slideshow.StopSlideshow();
        e.stop();
    }

    function Slide_Loaded(e)
    {
        // Set the visibility and display of the container
        slideshowContainer.setStyle({ visibility: 'hidden', display: 'block' });
        caption.setStyle({ width: slide.getDimensions().width + 'px' });
        navigation.setStyle({ width: slide.getDimensions().width - 50 + 'px' });

        // Get the dimensions of the container
        var dimensions = slideshowContainer.getDimensions();
        var _marginLeft = '-' + Math.ceil(dimensions.width / 2) + 'px';
        var _marginTop = '-' + Math.ceil(dimensions.height / 2) + 'px';

        // Hide the loading image
        slideshowLoadingIcon.setStyle({ display: 'none' });

        // Set the position based on the container size
        slideshowContainer.setStyle({ marginLeft: _marginLeft, marginTop: _marginTop, opacity: 0.0, visibility: 'visible' });
        new Effect.Opacity(slideshowContainer, { from: 0.0, to: 1.0, duration: 0.3 });
    }

    // Private Classes
    Source = function(_element)
    {
        // Private Members
        var element = _element;
        var self = this;

        // Public Properties
        this.Caption = element.readAttribute('title') || '';
        this.SetName = element.readAttribute('rel');
        this.SetPosition = slideshowSets[self.SetName].length;
        this.ImageUrl = element.readAttribute('href');

        // Event Handlers
        function OnClick(e)
        {
            Slideshow.ShowImage(self);
            e.stop();
            return false;
        }

        // Priviledged Methods
        this.Dispose = function()
        {
            element.stopObserving('click', OnClick);
        }

        element.observe('click', OnClick);
    }
}

Event.observe(window, 'load', function() { Slideshow.Initialize(); });
