/*
    SiteComponents version:
    6.7.0.1, tag SC_6_7_0_1, created Mon May 10 09:27:59 +0200 2010

    Disclaimer
    
    While we make every effort to ensure that this code is fit for its intended
    purpose, we make no guarantees as to its functionality. CoreTrek AS will
    accept no responsibility for the loss of data or any other damage or
    financial loss caused by use of this code.


    Copyright
    
    This programming code is copyright of CoreTrek AS. Permission to run this
    code is given to approved users of CoreTrek's publishing system CorePublish.
    
    This source code may not be copied, modified or otherwise repurposed for use
    by a third party without the written permission of CoreTrek AS.
    
    Contact webmaster@coretrek.com for information.
    
*/

/*jslint laxbreak: true, sub: true, white: false, browser: true,
onevar: false, nomen: false, noindent: true, eqeqeq: false, plusplus: false,
forin: true */
/*global siteComponentsConfig: false, getSiteComponentsConfig: false,
Ajax: false, $$: false, $: false, Element: false, window: false, Class: false,
Effect: false, lightbox: false, PeriodicalExecuter: false, Event: false,
CtCookie: false, cpKeywords: false, CtTooltip: false, Prototype: false,
cpWriteMediaObject: false, getThemeName: false, Hash: false, $H: false,
$break: false */

/*

    ============================================================================
    IMPORTANT! This javascript is dependent on Prototype. If Scriptaculous is
               available the tooltip will use some nice effects.
    ============================================================================

    SiteComponents slideshowtile.js

    Adds navigation to the slideshow tile.
    
*/

var SlideshowTile = Class.create({

    initialize: function(element) {
        this.element = $(element);

        this.interval = this.getInterval();

        this.current = 0;
        this.images = element.select('div.slideshow-image');
        
        // Get navigation bar if set (previous/next links)
        this.navigation = this.element.select('.slideshow-navigation').first();
        
        // Check if navigation bar is set
    	if(typeof this.navigation == 'undefined' || this.navigation ==  null) {
    		// We now that navigation isn't added, so the variable must be set to null
            this.navigation = null;
        }
        else {
        	// If navigation should be available display it, since it by default set to display none in html
        	this.navigation.show();
        }
        
        // Get thumbnail container if set
        this.thumbnailContainer = this.element.select('.slideshow-thumbnails').first();
        
        // Check if thumbnail container is set
        if(typeof this.thumbnailContainer == 'undefined' || this.thumbnailContainer == null) {
            // We now that thumbnail container isn't added, so the variable must be set to null
            this.thumbnails = null;
        } else {
            // Get all thumbnails
            this.thumbnails = this.thumbnailContainer.childElements();
            
            // If thumbnails should be available display their container, since it by default set to display none in html
            this.thumbnailContainer.show();
            
            // Since we display thumbs, we have to mark the thumbnail that is active initially
            this.setActiveThumb(this.images[this.current]);
        }
        
        // Add listeners used for this slideshow
        this.addListeners();
    },
    
    addListeners: function() {
        
        // Start periodical executer with given interval. Interval like 0 indicates that periodical execution should not happen
        if(this.interval > 0) {
    		this.pe = new PeriodicalExecuter(this.periodicalExecutor.bind(this), this.interval);
    	}
    	
        
        this.images.each(function(element) {
            var image = element.down('img');
            
            // Check if images has en url to another side
            var antoherUrlATag = image.up('a.another-side-url');
            if(antoherUrlATag == undefined) {
                image.observe('click', this.nextListener.bindAsEventListener(this));
            }
        }.bind(this));
        
        // If there are any navigation divs we add listeners to the navigation links
        if(this.navigation !== null) {
            this.element.select('a.slideshow-previous').first()
                .observe('click', this.previousListener.bindAsEventListener(this));
            this.element.select('a.slideshow-next').first()
                .observe('click', this.nextListener.bindAsEventListener(this));
        } 
        
        // If there are any thumbnail divs we add listeners to each thumbnail
        if(this.thumbnails !== null) {
            this.thumbnailContainer.select('a').each(function(element) {
               element.observe('click', this.thumbnailListener.bindAsEventListener(this));
            }.bind(this));
        } 

    },
    
    /**
     * Get interval seconds, number of seconds between each rotation
     * The interval value is added as content in a div element, so we get this value
     * from here if this specific element exists
     * 
     * @return interval - numeric value, defaults to 0, that indicates that no rotation should happen
     */
    getInterval: function() {
        // Default value
        var interval = 0;
        
        // Get inteval value from div element, if exists
        var intervalElement = this.element.select('.slideshow-interval').first();
        
        if(typeof intervalElement != 'undefined') {
            interval = intervalElement.innerHTML;
        }
        
        return interval;
    },
    
    /**
     * Navigate to the next image
     */
    previous: function() {
        
        var previous = this.current;
        var next = this.current - 1;
        
        if(next < 0) {
           next = this.images.size() - 1;
        }
        
        this.fadeFromTo(previous, next);
    },
    
    /**
     * Navigate to the previous image
     */ 
    next: function() {
        
        var previous = this.current;
        var next = this.current + 1;
        
        if(next >= this.images.size()) {
           next = 0;
        }
        
        this.fadeFromTo(previous, next);
    },
    
    /**
     * Navigate to a given element id. The element must be an image container
     * element
     */
    showElementId: function(elementId) {
        var i = 0;
        this.images.each(function(image) {
            if(image.id == elementId) {
                throw $break;
            }
            i++;
        });
        
        var previous = this.current;
        var next = i;
        
        try {
            this.fadeFromTo(previous, next);
        } catch (err) {
            // An error will occur if the loop above did not find any matches..
            // Should not happen, but with IE6 you cannot be sure 
        }
    },
    
    /**
    * Mark active thumbnail
    *
    * If no thumbnails set, we return from function
    *
    */
    setActiveThumb: function(to) {
        // return if there are no thumbnails (updating on interval)
        if(typeof this.thumbnails == "undefined" || this.thumbnails == null) {
            return;
        }
        var idKey = to.id.substring(to.id.lastIndexOf('-') + 1);
        
        this.thumbnails.each(function(thumb) {
            var href = thumb.down().readAttribute('href');
            var thumbIdKey = href.substring(href.lastIndexOf("#show_image_") + 12);
            if(thumb.hasClassName('active')) {
                thumb.removeClassName('active');
            } else if(idKey == thumbIdKey) {
                thumb.addClassName('active');
            }
        }.bind(this));
    },
    
    /**
     * Fade from a given image container to a new one. This method should only
     * be used inside this class. Use either next(), previous() or
     * showElementId() to toggle images.
     */
    fadeFromTo: function(from, to) {
        if(from == to) {
            return;
        }
        
        var toImage = this.images[to];
        var fromImage = this.images[from];
        
        this.setActiveThumb(toImage);
        
        try {
            var toDimensions = Element.getHiddenElementDimensions(toImage);
            
            new Effect.Opacity(fromImage, {
                to: 0.0,
                from: 1.0,
                duration: 0.3,
                afterFinish: function() {
                    this.eff = new Effect.Morph(fromImage, {
                        duration: 0.1,
                        style: {
                            height: toDimensions.height + 'px'
                        },
                        afterFinish: function() {
                            this.eff = new Effect.Appear(toImage, {
                                duration: 0.3,
                                afterUpdate: function(effect) {
                                    if(effect.currentFrame === 0) {
                                        fromImage.hide();
                                        fromImage.setOpacity(1.0);
                                        fromImage.setStyle({ height: 'auto' });
                                        
                                        // Lets check if the image has been
                                        // enhanced, if it has we need to
                                        // reinitialize the elements
                                        try {
                                            var ratings = toImage.select("div.rating-container");
                                            if(ratings.size() > 0) {
                                                ratings.each(function(element) {
                                                    if(typeof element.enhancer == 'object') {
                                                        element.enhancer.reinitializeElements();
                                                    }
                                                });
                                            }
                                        } catch (err) {
                                            // Something went wrong trying to
                                            // reinitialize the element
                                        }
                                        
                                    }
                                }.bind(this)
                            });
                        }
                    });

                }.bind(this)
            });
            
        } catch (e) {
            // No scriptaculous - hide/show without effect
            fromImage.hide();
            toImage.show();   
        }
        
        this.current = to;
    },
    
    // ========================================================================
    // Event listeners
    
    nextListener: function(event) {
        event.stop();
        
        // Periodical execution should be stopped
        this.stopPeriodicalExecutor();
      
        this.next();
    }, 
    
    previousListener: function(event) {
        event.stop();
        
        // Periodical execution should be stopped
        this.stopPeriodicalExecutor();
      
        this.previous();
    },
    
    thumbnailListener: function(event) {
        event.stop();
        
        // Periodical execution should be stopped
        this.stopPeriodicalExecutor();
        
        var href = event.findElement('a').readAttribute('href');
        var imageContainerId = 'image-' + this.element.id + '-' + href.substring(href.lastIndexOf("#show_image") + 12);
        
        this.showElementId(imageContainerId);
    },
    
    periodicalExecutor: function(pe) {
        this.next();
    },
    
    /**
    *	Function used to stop the periodical execution
    *	It's used if some of the click listeners triggers
    */
    stopPeriodicalExecutor: function() {
    	// stop periodical executer if it's defined
    	if(typeof this.pe != "undefined") {
            this.pe.stop();
        }
    }

});

