/**
 *	Basic Slideshow App using Prototype and Scriptaculous
 *
 *	Plagerised from Tom Doyle by Isotope Communications Ltd, Dec 2008
 *	http://www.tomdoyletalk.com/2008/10/28/simple-image-gallery-slideshow-with-scriptaculous-and-prototype/
 *
 *
 *	Plagerised again by Bryan Morrow at Rocket Jones Interactive
 *	http://rocketjones.com/
 *
 *	Changes: More objectified, more options, more transitions and more beautification.
 *
 *
 */

var RocketSlideShow = new Class.create();

RocketSlideShow.prototype = {

    initialize : function (oArgs){
        // General settings
        this.id                 = oArgs.id ? oArgs.id : 'rocketslider1';
        this.wait 		= oArgs.wait ? oArgs.wait : 4000; // The length of time to dispay and image before going to the next
        this.start 		= oArgs.start ? oArgs.start : 0; // Which index of the array to start with.
        this.duration		= oArgs.duration ? oArgs.duration : 0.5; // Duration of the transition
        this.transition         = oArgs.transition ? oArgs.transition : 'fade'; // fade, hard, blindUp, blindDown, collapseY, collapseX
        this.autostart		= (typeof(oArgs.autostart)=='undefined' || oArgs.autostart == true) ? true : false; // Automatically start the slideshow.
        this.resumeAutoplayTime = (typeof(oArgs.resumeAutoplayTime)=='undefined' || oArgs.resumeAutoplayTime == 0 || isNaN(oArgs.resumeAutoplayTime)) ? 0 : oArgs.resumeAutoplayTime; // Resume autoplay after someone jumps to a specific frame? false for no or a number in ms.
        this.random             = (typeof(oArgs.random)=='undefined' || oArgs.random==false) ? false : true;
        this.loop               = (typeof(oArgs.loop)=='undefined' || oArgs.loop==false) ? false : true;
        this.scaleImages        = (typeof(oArgs.scaleImages)=='undefined' || oArgs.scaleImages==true) ? true : false; // Scale the width to fit the window?
        this.forceScale         = (typeof(oArgs.forceScale)=='undefined' || oArgs.forceScale == false) ? false : true; // Force an image to the exact size of the slider window?
        this.forceScale = false;
        this.height             = (isNaN(oArgs.height)) ? 200 : oArgs.height;
        this.width              = (isNaN(oArgs.width)) ? 500 : oArgs.width;

        //Buttons
        this.showPrev		= (typeof(oArgs.showPrev)=='undefined' || oArgs.showPrev==true) ? true : false;
        this.showNext		= (typeof(oArgs.showNext)=='undefined' || oArgs.showNext==true) ? true : false;
        this.showPlay		= (typeof(oArgs.showPlay)=='undefined' || oArgs.showPlay==true) ? true : false;
        this.showPause          = (typeof(oArgs.showPause)=='undefined' || oArgs.showPause==true) ? true : false;
        this.showShortcuts	= (typeof(oArgs.showShortcuts)=='undefined' || oArgs.showShortcuts==true) ? true : false;

        // Other
        this.slides 		= oArgs.slides; // Expecting a JSON object of slides.
        this.iImageId		= this.start;
        this.slideIDs           = new Array();
        this.playint            = '';
        this.resumeplayint      = '';
        this.inTransition       = false;
        this.transDirection     = 'forward';
        this.transOppMap        = {'swipeLeft':'swipeRight', 'swipeRight':'swipeLeft'}; // For mapping which transactions have which opposite transaction
        this.loadedSlides       = {};
        this.preloadedSlides    = {};

        if ( this.slides ) {
            this.numOfImages	= this.slides.length;
            if ( !this.numOfImages ) {
                alert('No slides?');
            }
        }

        // Hide all slides but the first
        if(this.id == '' || typeof this.id == 'undefined') return false;
        
    },

    buildPlayer : function (){
        // Set correct sizes
        $(this.id).setStyle({
          height: this.height+'px',
          width: this.width+'px'
        });

		$(this.id).up().setStyle({
          height: this.height+'px',
          width: this.width+'px'
        });

        // Build HTML of slides
        $(this.id).childElements().each(function(s, index){$(s).remove();});
        var obj = this;
        var i = 0;
        var newhtml = '';
        var shortcuts = '';
        while (i<=this.slides.length-1)
            {
            id = this.id+'_slide'+i;
            this.slideIDs[i] = id;
            newhtml += '<div id="'+id+'" '+(i>0?' style="display:none;"':'')+'>';
            if(typeof this.slides[i].href != 'undefined') linkstart = '<a href="' +this.slides[i].href+ '" '+(typeof this.slides[i].target != 'undefined'?'target="'+this.slides[i].target+'"':'')+'>';
			else linkstart = '';
            if(typeof this.slides[i].href != 'undefined') linkend = '</a>';
			else linkend = '';
			
            this.preloadedSlides[i] = linkstart+'<img src="' + this.slides[i].src + '"  border="0" alt="'+(typeof this.slides[i].alt != 'undefined'?this.slides[i].alt:'')+'" '+(this.scaleImages||this.forceScale?'width="100%"':'')+(this.forceScale?' height="100%"':'')+' />'+linkend; //alt="'+this.slides[i].caption+'"
            if(i == 0 || i ==1) {
            	this.loadedSlides[i] = true;
                newhtml += this.preloadedSlides[i]; // Load first two slides
            }
            if(typeof this.slides[i].caption != 'undefined') newhtml += '<div class="rocketslidercaption"><h4>' +this.slides[i].caption+ '</h4></div>';
            newhtml += '</div>';
            $(this.id).insert(newhtml);
            
            if(i != 0) $(this.slideIDs[i]).hide();

            // Create shortcuts
            shortcuts += '<li>'+i+'</li>';

            i++;
            newhtml = '';
            }

         // Set button displays
         if(this.showPlay == true) {
             $(this.id).insert({'before':'<a class="rocketsliderplay" id="'+this.id+'_play" href="javascript:;" /></a>'});
             $(this.id+'_play').observe('click', function(event){obj.autoplay();obj.clearSelection();return false;});
         }
         if(this.showPause == true) {
             $(this.id).insert({'before':'<a class="rocketsliderpause" id="'+this.id+'_pause" href="javascript:;" /></a>'});
             $(this.id+'_pause').observe('click', function(event){obj.stop();obj.clearSelection();return false;});
         }

         if(this.showPrev == true) {
             $(this.id).insert({'before':'<a class="rocketsliderprev" id="'+this.id+'_prev" href="javascript:;" /></a>'});
             $(this.id+'_prev').observe('click', function(event){obj.goPrevious();obj.clearSelection();return false;});
         }

         if(this.showNext == true) {
             $(this.id).insert({'before':'<a class="rocketslidernext" id="'+this.id+'_next" href="javascript:;" /></a>'});
             $(this.id+'_next').observe('click', function(event){obj.goNext();obj.clearSelection();return false;});
         }

         if(this.showShortcuts == true) {
             $(this.id).insert({'before':'<ul id="'+this.id+'_shortcuts">'+shortcuts+'</ul>'});
             $(this.id+'_shortcuts').childElements().each(function(s, index){
                 $(s).observe('click', function(event){obj.goTo(index);obj.clearSelection();return false;});
                 if(index == 0) $(s).addClassName('selected');
             });

         }
    },

    // Image transitions
    swapImage: function (x, y, transition) {
        // x = new slide to show.
        var x = x; // make it global within this function
        
        // y = old slide to hide.
        var y = y; // make it global within this function

        // Don't do anything if we're trying to go to the same slide
        if(x == y) return false;

        // transition; you can specify a particular transition for this single swap
        transition = this.transition; // transition changing is not currently in use.

        // See if we're back to the start
        if (x >= this.numOfImages) x = 0;

        // See if we're going backwards to the end
        if (x < 0) x = this.numOfImages-1;

        // Set direction to allow us to pause clicking
        var oldDirection = this.transDirection;
        var newDirection = false;
        if((x > y && y != 0) || (x == 0 && y == this.numOfImages-1)) newDirection = 'forward';
        else if(x < y || (x == this.numOfImages-1 && y == 0)) newDirection = 'backward';
        else newDirection = 'forward';

        // Check for transitioning
        if(this.inTransition !== false) { // && oldDirection != newDirection - to allow for same direction multiples
            // If currently in transition, don't allow
            return false;
        }

        // Set direction
        this.transDirection = newDirection;

        // We're good to go! Set that we're in transition
        this.inTransition = x;

		// Make sure the image has been loaded. This might get triggered if we're jumping to a frame that hasn't been loaded yet.
  		 if(typeof this.loadedSlides[x] == 'undefined') {
	         this.loadedSlides[x] = true;
         	if(typeof this.slideIDs[x] !== 'undefined') {
				$(this.slideIDs[x]).hide();
	            $(this.slideIDs[x]).insert(this.preloadedSlides[x]);
	         }
	     }
	
        // Load frame after this one
        next = ((x*1)+1);
        if(typeof this.loadedSlides[next] == 'undefined') {
            this.loadedSlides[next] = true;
            if(typeof this.slideIDs[next] !== 'undefined') {
                $(this.slideIDs[next]).insert(this.preloadedSlides[next]);
            }
        }
		
        // Next image in line after this transition
        // We set it here in case you go to another slide in the middle of a transition
        this.iImageId = x;

        // Set correct transitions, which might change for this one swap
        if(newDirection == 'backward'){
            if(typeof this.transOppMap[this.transition] != 'undefined') {
                transition = this.transOppMap[this.transition];
            } else {
                transition = this.transition;
            }
        }

        // Set selected shortcut
        if(this.showShortcuts){
            $(this.id+'_shortcuts').childElements().each(function(s, index){
                 if(index != x) $(s).removeClassName('selected');
                 else $(s).addClassName('selected');
             });
        }

        // Perform the selected transition
        var obj = this;
        if(transition == 'fade') {
            // Find x, remove it, and place it directly before (behind) y.
            backslide = $(this.slideIDs[x]).remove();
            $(this.id).insertBefore(backslide, $(this.slideIDs[y]));
            // Show both slides. y (old) is in front of x (new).

            new Effect.Parallel([
                new Effect.Fade(this.slideIDs[x], {
                    duration: this.duration,
                    from: 0.0,
                    to: 1.0,
                    beforeSetup: function(effect){
                        effect.element.show();
                    },
                    afterFinish: function(effect) {
                        effect.element.show();
                    }
                }),
                new Effect.Fade(this.slideIDs[y], {
                    duration: this.duration,
                    from: 1.0,
                    to: 0.0,
                    afterFinish: function() {
                        if(x == obj.inTransition) {obj.inTransition = false;}
                    }
                })
            ], {duration: this.duration});
        } else if(transition == 'hard'){
            // Find x, remove it, and place it directly before (behind) y.
            backslide = $(this.slideIDs[x]).remove();
            $(this.id).insertBefore(backslide, $(this.slideIDs[y]));

            // Show both slides. y (old) is in front of x (new).
            $(this.slideIDs[x]).show();
            $(this.slideIDs[y]).hide();

			if(x == obj.inTransition) {obj.inTransition = false;}

        } else if(transition == 'blindUp'){
            // Find x, remove it, and place it directly before (behind) y.
            backslide = $(this.slideIDs[x]).remove();
            $(this.id).insertBefore(backslide, $(this.slideIDs[y]));

            // Show both slides. y (old) is in front of x (new).
            $(this.slideIDs[x]).show();
            $(this.slideIDs[y]).blindUp({duration: this.duration,afterFinish: function() {if(x == obj.inTransition) {obj.inTransition = false;}}});
        } else if(transition == 'blindDown'){ // TODO: Don't  use this one yet.
            $(this.slideIDs[y]).blindDown({duration: this.duration, afterFinish: function() {if(x == obj.inTransition) {obj.inTransition = false;}}})
        } else if(transition == 'swipeRight') {
             var obj = this;
            $(this.slideIDs[x]).cleanWhitespace();
			
            new Effect.Parallel([
                new Effect.Move($(this.slideIDs[x]), {
                    x: $(this.slideIDs[x]).getWidth(),
                    sync: true,
                    mode: 'relative',
                    beforeStartInternal: function(effect) {
                        if(window.opera) effect.element.setStyle({left: ''});
                        effect.element.setStyle({left: '-' + obj.width + 'px'});
                    },
                    beforeSetup: function(effect){
                        effect.element.parentNode.makeClipping();
                        effect.element.makeClipping();
                        effect.element.show();
                    }
                }),
                new Effect.Move($(this.slideIDs[y]), {
                    x: $(this.slideIDs[y]).getWidth(),
                    sync: true,
                    mode: 'relative',
                    beforeSetup: function(effect){
                        effect.element.parentNode.makeClipping();
                        effect.element.makeClipping();
                    }
                })
               ], Object.extend({
                    beforeSetup: function(effect){
                        effect.effects[0].element.parentNode.makeClipping();
                        effect.effects[0].element.makeClipping();
                    },
                    afterFinishInternal: function(effect){
                        effect.effects[0].element.undoClipping();
                        if(x == obj.inTransition) {obj.inTransition = false;}
                    }
                }, arguments[1] || {})
            );

        } else if(transition == 'swipeLeft') {
            var obj = this;
            new Effect.Parallel([
               // Old out
                new Effect.Move($(this.slideIDs[y]), {
                    x: $(this.slideIDs[y]).getWidth()*-1,
                    sync: true,
                    mode: 'relative',
                    beforeSetup: function(effect){
                        effect.element.parentNode.makeClipping();
                        effect.element.makeClipping();
                    },
                    afterFinishInternal: function(effect){
                        effect.element.hide();
                        effect.element.undoClipping();
                    }
                }),
                // New in
                new Effect.Move($(this.slideIDs[x]), {
                    x: obj.width*-1,
                    sync: true,
                    mode: 'relative',
                    beforeStartInternal: function(effect) {
                        if(window.opera) effect.element.setStyle({left: ''});
                        effect.element.setStyle({left: obj.width + 'px'});
                    },
                    beforeSetup: function(effect){
                        effect.element.parentNode.makeClipping();
                        effect.element.makeClipping();
                         effect.element.show();
                    }
                })
                ], Object.extend({
                    beforeSetup: function(effect){
                        effect.effects[1].element.parentNode.makeClipping();
                        effect.effects[1].element.makeClipping();
                    },
                    afterFinishInternal: function(effect){
                        effect.effects[0].element.undoClipping();
                        if(x == obj.inTransition) {obj.inTransition = false;}
                    }
                }, arguments[1] || {})
            );


        } else if(transition == 'collapseY'){
            // Find x, remove it, and place it directly before (behind) y.
            backslide = $(this.slideIDs[x]).remove();
            $(this.id).insertBefore(backslide, $(this.slideIDs[y]));
            // Show both slides. y (old) is in front of x (new).
            $(this.slideIDs[x]).show();

            oldOpacity = $(this.slideIDs[y]).getInlineOpacity();
            new Effect.Scale($(this.slideIDs[y]), 1, {
                duration: this.duration,
                scaleFromCenter: true,
                scaleX: false,
                scaleContent: false,
                restoreAfterFinish: true,
                beforeSetup: function(effect) {effect.element.makePositioned().makeClipping();},
                afterFinishInternal: function(effect) {effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity});if(x == obj.inTransition) {obj.inTransition = false;}}
                });
        } else if(transition == 'collapseX'){
            // Find x, remove it, and place it directly before (behind) y.
            backslide = $(this.slideIDs[x]).remove();
            $(this.id).insertBefore(backslide, $(this.slideIDs[y]));
            // Show both slides. y (old) is in front of x (new).
            $(this.slideIDs[x]).show();

            oldOpacity = $(this.slideIDs[y]).getInlineOpacity();
            new Effect.Scale($(this.slideIDs[y]), 1, {
                duration: this.duration,
                scaleFromCenter: false,
                scaleY: false,
                scaleContent: false,
                restoreAfterFinish: true,
                beforeSetup: function(effect) {effect.element.makePositioned().makeClipping();},
                afterFinishInternal: function(effect) {effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity});if(x == obj.inTransition) {obj.inTransition = false;}}
                });
        } else if(transition == 'blindLeft'){
            // Find x, remove it, and place it directly before (behind) y.
            backslide = $(this.slideIDs[x]).remove();
            $(this.id).insertBefore(backslide, $(this.slideIDs[y]));
            // Show both slides. y (old) is in front of x (new).
            $(this.slideIDs[x]).show();
            
            element = $(this.slideIDs[y]);
            element.makeClipping();
            new Effect.Scale(element, 0,
                Object.extend({
                  scaleContent: false,
                  scaleY: false,
                  restoreAfterFinish: true,
                  afterFinishInternal: function(effect) {
                    effect.element.hide().undoClipping();
                  }
                }, arguments[1] || { })
            );


                /*
            $(this.slideIDs[y]).blindLeft({
                duration: this.duration,
                afterFinish: function() {if(x == obj.inTransition) {obj.inTransition = false;}}
            });*/
            
        } else {
            $(this.slideIDs[y]).fade({duration: this.duration,afterFinish: function() {if(x == obj.inTransition) {obj.inTransition = false;}}});
        }

        return false;
    },

    // the onload event handler that starts the fading.
    startSlideShow: function () {
        // Randomize the order of the slides?
        if (this.random){this.randomize();}

        // Build the HTML, set sizes and bind button actions
        this.buildPlayer();

        // Autoplay?
        if (this.autostart){this.autoplay();}
        else {this.stop();}
    },

    autoplay: function(){
        // Clear interval, so we don't get duplicates'
        clearInterval(this.playint);


        // Show correct controls
        if(this.showPlay) $(this.id+'_play').hide();
        if(this.showPause) $(this.id+'_pause').appear({duration: 0});

        // If at end of loop and starting again, go to beginning
        if(this.loop != true && this.iImageId == this.numOfImages-1) {
            this.swapImage(0, this.iImageId);
        }

        // Start interval
        this.playint = setInterval(this.play.bind(this),this.wait);
        return false;
    },

    resumeAutoplay: function(){
         // Resume autoplay after jumping
        if((this.resumeAutoplayTime != false && this.resumeAutoplayTime > 0) && (this.loop == true || this.iImageId != this.numOfImages-1)){
            clearTimeout(this.resumeplayint);
            this.resumeplayint = setTimeout(this.autoplay.bind(this),this.resumeAutoplayTime);
        }
    },

    randomize: function(){
        function randord(){return (Math.round(Math.random())-0.5);}
        this.slides.sort(randord);
    },

    play: function () {
        // Loop?
        if(this.loop != true && this.iImageId == this.numOfImages-1){
            // We're not looping and we're at the end of the line
            this.stop();
        } else {
            // Keep going!
            this.swapImage(this.iImageId+1,this.iImageId);
        }
        
        return false;
    },

    stop: function  () {
        clearInterval(this.playint);
        if(this.showPlay) $(this.id+'_play').appear({duration: 0});
        if(this.showPause) $(this.id+'_pause').hide();
        return false;
    },

    goTo: function (index) {
        this.clearSelection();
        this.stop();
        this.swapImage(index, this.iImageId);
        this.resumeAutoplay();
        return false;
    },

    goNext: function () {
        this.clearSelection();
        this.stop();
        this.swapImage(this.iImageId+1,this.iImageId);
        this.resumeAutoplay();
        return false;
    },

    goPrevious: function () {
        this.clearSelection();
        this.stop();
        this.swapImage(this.iImageId-1,this.iImageId, 'opposite');
        this.resumeAutoplay();
        return false;
    },

    clearSelection: function(){
        //Clear text selection so it doesn't highlight the player
        if (window.getSelection) {
          if (window.getSelection().empty) window.getSelection().empty(); // Chrome
          else if (window.getSelection().removeAllRanges) window.getSelection().removeAllRanges(); // FF
        } else if (document.selection) {  // IE?
            if(document.selection.empty) document.selection.empty();
        }
        return false;
    }
}

/* #### Additional Effects #### */


