/*
    rsGallery v1.0 - Gallery Control for Displaying Galleries of Images/Content
      - Copyright (c) 1995-2008 EDge Interactive. All rights reserved. <www.edgeip.com>
      - Script Author
            - Robert J. Secord, B.Sc. <Robert.Secord@edgeip.com>
      - Dependancies:
            - Mootools v1.2 or later.  <www.mootools.net>
      - Tested Browsers:
            - Windows: IE 6, IE 7, Firefox 2+, Opera 9+, Netscape 8+, Google Chrome 0.4
      - TODO:
*/
// -----------------------------------------------------------------------------------------------------------------
// rsGalleryThemes Collection
var rsGalleryThemes =
{
    // Common (Silver) Theme
    Common:
    {
        GraphicsSubPath:  'moo/gallery/silver/',
        CssClass:
        {
            Container:        'rsGallery-Container',
            Title:            'rsGallery-Title',
            Image:            'rsGallery-Image',
            Counter:          'rsGallery-Counter',
            Content:          'rsGallery-Content',
            Navigation:       'rsGallery-Navigation',
            NavPrevious:      'rsGallery-Navigation-Previous',
            NavNext:          'rsGallery-Navigation-Next',
            NavPreviousHover: 'rsGallery-Navigation-Previous-Hover',
            NavNextHover:     'rsGallery-Navigation-Next-Hover'
        },
        Styles:
        {
            Container:        'background:#F3F3F3; width:280px;',
            Title:            'font-weight:bold; text-transform:uppercase;',
            Image:            'border: 1px solid #B2B2B2; margin:5px auto;',
            Counter:          'color:#858585; font-size:0.85em; font-weight:bold; text-align:right;',
            Content:          'margin:0 0 10px 0;',
            Navigation:       'height:11px; font-size:1px; line-height:1px; margin:0 0 5px 0;',
            NavPrevious:      'float:left; width:90px; height:11px; font-size:1px; line-height:1px; background:transparent url([GFX-PATH]arrows.gif) no-repeat top right; cursor:pointer;',
            NavNext:          'float:right; width:90px; height:11px; font-size:1px; line-height:1px; background:transparent url([GFX-PATH]arrows.gif) no-repeat top left; cursor:pointer;',
            NavPreviousHover: 'background:transparent url([GFX-PATH]arrows.gif) no-repeat bottom right;',
            NavNextHover:     'background:transparent url([GFX-PATH]arrows.gif) no-repeat bottom left;'
        }
    }
};
// -----------------------------------------------------------------------------------------------------------------
// rsGallery Class Definition
var rsGallery = new Class(
{
    Implements: [Events, Options],

    // -------------------------------------------------------------------------------------------------------------
    // Member Variables
    options:
    {
        Gallery:
        {
            // Required Settings:
            GraphicsPath: '',

            // Required: Gallery Data
            GalleryTitle: '',
            GalleryData:  [],

            // Optional Theme:
            Theme: rsGalleryThemes.Common,

            // Optional Developer Use:
            DebugMode: false
        },

        onGalleryImageClick: $empty
    },

    // -------------------------------------------------------------------------------------------------------------
    // Class Constructor (options = JSON Object)
    initialize: function( options )
    {
        this.setOptions( options );

        // State Flags
        this.bValidControl = true;

        // Check for Required Settings for Object Instantiation
        if( this.options.Gallery.GraphicsPath.length < 1 ) return this.ErrorAlert('Object Construction Failed - Invalid GraphicsPath Supplied!');

        // Check for Required Gallery Data
        if( this.options.Gallery.GalleryTitle.length < 1 ) return this.ErrorAlert('Object Construction Failed - Invalid GalleryTitle Supplied!');
        if( this.options.Gallery.GalleryData.length < 1 ) return this.ErrorAlert('Object Construction Failed - Invalid GalleryData Array Supplied!');

        // Merge Custom Theme with Common Theme
        this.options.Gallery.Theme = $merge(rsGalleryThemes.Common, this.options.Gallery.Theme);

        // Ensure Theme Styles have Proper Graphics Path
        var szGfxPath = '' + this.options.Gallery.GraphicsPath + this.options.Gallery.Theme.GraphicsSubPath;
        $each(this.options.Gallery.Theme.Styles, function(szStyle, szKey){ this.options.Gallery.Theme.Styles[szKey] = szStyle.replace(/\[GFX-PATH\]/i, szGfxPath); }.bind(this));

        // Default Position
        this.iCurrentPosition = 0;

        // Attach Window Events
        window.addEvent('load', this.OnLoad.bind(this));
    },

    // -------------------------------------------------------------------------------------------------------------
    // Internal Routine: DOM Ready Event (before OnLoad)
    OnLoad: function()
    {
        // Insert Required CSS; Invalidates rsGallery on Fail
        this.InsertCSS();

        // Build Gallery Elements
        this.BuildGallery();
    },

    // -------------------------------------------------------------------------------------------------------------
    // Internal Routine: Builds Gallery Elements
    BuildGallery: function()
    {
        if( !this.bValidControl ) return;

        // Get Image Gallery Element on Page
        this.oGalleryContainer = document.getElement('.' + this.options.Gallery.Theme.CssClass.Container);
        if( !this.oGalleryContainer ) return this.ErrorAlert(true, 'BuildGallery Failed:\nGallery Container Element Not Found!');

        // Reset Gallery Contents
        this.oGalleryContainer.empty();

        // Build Gallery Title Element
        this.oGalleryTitle = new Element('div',
        {
            'class': this.options.Gallery.Theme.CssClass.Title,
            'html':  this.options.Gallery.GalleryTitle
        }).inject(this.oGalleryContainer);

        // Build Gallery Image Element
        this.oGalleryImage = new Element('div', {'class': this.options.Gallery.Theme.CssClass.Image}).inject(this.oGalleryContainer);

        // Build Gallery Counter Element
        this.oGalleryCounter = new Element('div', {'class': this.options.Gallery.Theme.CssClass.Counter}).inject(this.oGalleryContainer);

        // Build Gallery Content Element
        this.oGalleryContent = new Element('div', {'class': this.options.Gallery.Theme.CssClass.Content}).inject(this.oGalleryContainer);

        // Build Gallery Navigation Elements
        this.oGalleryNav = new Element('div', {'class': this.options.Gallery.Theme.CssClass.Navigation}).inject(this.oGalleryContainer);
        this.oGalleryNavPrevious = new Element('div', {'class': this.options.Gallery.Theme.CssClass.NavPrevious}).inject(this.oGalleryNav);
        this.oGalleryNavNext = new Element('div', {'class': this.options.Gallery.Theme.CssClass.NavNext}).inject(this.oGalleryNav);

        // Add Click Event & Hover Effects to Navigation
        this.oGalleryNavPrevious.addEvents(
        {
            'mouseenter': function(){ this.oGalleryNavPrevious.addClass(this.options.Gallery.Theme.CssClass.NavPreviousHover); }.bind(this),
            'mouseleave': function(){ this.oGalleryNavPrevious.removeClass(this.options.Gallery.Theme.CssClass.NavPreviousHover); }.bind(this),
            'click': function()
            {
                this.iCurrentPosition--;
                this.UpdateGallery();
            }.bind(this)
        });
        this.oGalleryNavNext.addEvents(
        {
            'mouseenter': function(){ this.oGalleryNavNext.addClass(this.options.Gallery.Theme.CssClass.NavNextHover); }.bind(this),
            'mouseleave': function(){ this.oGalleryNavNext.removeClass(this.options.Gallery.Theme.CssClass.NavNextHover); }.bind(this),
            'click': function()
            {
                this.iCurrentPosition++;
                this.UpdateGallery();
            }.bind(this)
        });

        // Add Click Event to Gallery Image
        this.oGalleryImage.addEvents(
        {
            'click': function()
            {
                this.fireEvent('galleryImageClick', [this.iCurrentPosition, this], 0);
            }.bind(this)
        });

        // Initial Gallery Update
        this.UpdateGallery();
    },

    // -------------------------------------------------------------------------------------------------------------
    // Internal Routine:
    UpdateGallery: function()
    {
        // Ensure Valid Current Position
        this.ValidatePosition();

        // Get Data for Current Position
        var oData = this.options.Gallery.GalleryData[this.iCurrentPosition];

        // Ensure Valid Content Element
        var oContentEl = $(oData.ContentID);
        if( !oContentEl ) return this.ErrorAlert(false, 'UpdateGallery Failed:\nInvalid ContentID for Gallery Data as Position: ' + this.iCurrentPosition);

        // Update Gallery Imge
        this.oGalleryImage.setStyles(
        {
            'width':      oData.Size.x,
            'height':     oData.Size.y,
            'background': 'transparent url(' + this.options.Gallery.GraphicsPath + oData.ImageUrl + ') no-repeat top left'
        });

        // Update Gallery Content
        this.oGalleryContent.empty().set('html', oContentEl.get('html'));

        // Update Gallery Counter
        var szCounterHtml = '' + (this.iCurrentPosition + 1) + '/' + this.options.Gallery.GalleryData.length;
        this.oGalleryCounter.set('html', szCounterHtml);
    },

    // -------------------------------------------------------------------------------------------------------------
    // Internal Routine: Ensures Valid Gallery Position (Rolls over to first/last index)
    ValidatePosition: function()
    {
        // Ensure Valid Current Position
        if( this.iCurrentPosition < 0 ) this.iCurrentPosition = this.options.Gallery.GalleryData.length - 1;
        if( this.iCurrentPosition > this.options.Gallery.GalleryData.length - 1 ) this.iCurrentPosition = 0;
    },

    // -------------------------------------------------------------------------------------------------------------
    // Insert Required Elements
    // ~~~~~~~~~~~~~~~~~~~~~~~~

    // -------------------------------------------------------------------------------------------------------------
    // Internal Routine: Insert CSS Display Styles
    InsertCSS: function()
    {
        if( $(this.ClassName + 'RequiredCSS') ) return; // CSS Already Inserted

        var bDebug = this.options.Gallery.DebugMode;
        var crlf = bDebug ? '\n' : '', tab = bDebug ? '    ' : '';

        var szCSS = ''
        + crlf + '.' + this.options.Gallery.Theme.CssClass.Container
        + crlf + '{'
        + crlf + tab + this.options.Gallery.Theme.Styles.Container
        + crlf + '}'
        + crlf + '.' + this.options.Gallery.Theme.CssClass.Title
        + crlf + '{'
        + crlf + tab + this.options.Gallery.Theme.Styles.Title
        + crlf + '}'
        + crlf + '.' + this.options.Gallery.Theme.CssClass.Image
        + crlf + '{'
        + crlf + tab + this.options.Gallery.Theme.Styles.Image
        + crlf + '}'
        + crlf + '.' + this.options.Gallery.Theme.CssClass.Counter
        + crlf + '{'
        + crlf + tab + this.options.Gallery.Theme.Styles.Counter
        + crlf + '}'
        + crlf + '.' + this.options.Gallery.Theme.CssClass.Content
        + crlf + '{'
        + crlf + tab + this.options.Gallery.Theme.Styles.Content
        + crlf + '}'
        + crlf + '.' + this.options.Gallery.Theme.CssClass.Navigation
        + crlf + '{'
        + crlf + tab + this.options.Gallery.Theme.Styles.Navigation
        + crlf + '}'
        + crlf + '.' + this.options.Gallery.Theme.CssClass.NavPrevious
        + crlf + '{'
        + crlf + tab + this.options.Gallery.Theme.Styles.NavPrevious
        + crlf + '}'
        + crlf + '.' + this.options.Gallery.Theme.CssClass.NavNext
        + crlf + '{'
        + crlf + tab + this.options.Gallery.Theme.Styles.NavNext
        + crlf + '}'
        + crlf + '.' + this.options.Gallery.Theme.CssClass.NavPreviousHover
        + crlf + '{'
        + crlf + tab + this.options.Gallery.Theme.Styles.NavPreviousHover
        + crlf + '}'
        + crlf + '.' + this.options.Gallery.Theme.CssClass.NavNextHover
        + crlf + '{'
        + crlf + tab + this.options.Gallery.Theme.Styles.NavNextHover
        + crlf + '}';

        try
        {
            // Create Style Element
            var oCSS = new Element('style', {'type': 'text/css', 'media': 'all', 'id': this.ClassName + 'RequiredCSS'}).inject(document.head, 'top');

            // Append CSS Text to Style Element
            if( Browser.Engine.trident ) document.styleSheets[document.styleSheets.length-1].cssText = szCSS;
            else oCSS.appendText( szCSS );

            // Insert Succesful
            return true;
        }
        catch( szError )
        {
            // Insert Failed
            return this.ErrorAlert(true, 'InsertCSS Failed:\n' + szError);
        }
    },

    // -------------------------------------------------------------------------------------------------------------
    // Standard Class Data
    // ~~~~~~~~~~~~~~~~~~~

    // -------------------------------------------------------------------------------------------------------------
    // Internal Routine: Debug-Mode Error Alerts
    ErrorAlert: function( bInvalidate, szErrorMsg )
    {
        // Invalidate Control
        if( bInvalidate ) this.bValidControl = false;

        // Debug Alert Message
        if( this.options.Gallery.DebugMode )
            alert('[' + this.ClassName + ' ' + this.ClassVersion + '] -- DEV-ERROR --\n\n' + szErrorMsg);
        return false;
    },

    // -------------------------------------------------------------------------------------------------------------
    // Class Name, Version, Author
    ClassName:    'rsGallery',
    ClassVersion: '1.0',
    ClassAuthor:  'Robert J. Secord, B.Sc.'
});