/**
 * Based on innerfade.js by Torsten Baldes http://medienfreunde.com
 * 
 * author Arjay Aquino
 * 
 * This Plugin adds callbacks and a Widget-like plugin architecture to the existing innerfade.js
 * Other features: Ability to pause slideshow when user hovers on slide, and can auto rotate the slides 
 * how ever many times it is set to.
 * 
 * Sample Usage with Callbacks:
 * 		$('#slideshowCont').slideshow({
 *			speed             : 1400,
 *			timeout           : 6000,
 *			type              : 'sequence',
 *			containerheight   : 'auto',
 *			autoRotate        : true,
 *			maxRotateCount    : 0, //how many times the slide show will auto rotate. 0 is infinite
 *			pauseOnHover      : false, //if true, the slideshow will pause if mouse hovers on slideshow
 *			slideDesc         : 'banner-desc',
 *			slideshowNav      : 'banner-menu',
 *			slideChangeStart  : function(args){ onSlideChangeStart(args); }, //called when slide is called to show
 *			slideChangeEnd    : function(args){ onSlideChangeEnd(args); }    //called when slide is done showing
 *		});
 *
 * Each call back passes in an args object. The object keys are: slideID, cause, tagName, count
 * 
 * To call a public function for this plugin do this:
 * 		$("elementname").data("SlideShow").publicMethod(args);
 * 
 */

(function($){
	
/**
 * PLUGIN CONSTRUCTOR
 */
	$.fn.slideshow = function(options){
		
		return this.each(function(){
			new SlideShow(this, options);
		});
	}

	
/**
 * PLUGIN CLASS
 * 
 * This plugin uses a Class pattern. An instance of this class will be attached to the HTML Element which 
 * allows for calling public methods on a specific INSTANCE.
 * 
 * init() method is called on SlideShow creation.
 */
	var SlideShow = function(element, options){
		
		var PLUGIN_NAME    = "SlideShow";
		
		element            = $(element);
		element.data(PLUGIN_NAME, this); //store reference to SlideShow object in the element
		
		var counter        = 0; //keeps track of how many times the slides have reached the end
		var isPlaying      = false; //play state
		var currentSlideID = 0;    //reference to slide that needs to show
		var oldSlideID     = currentSlideID; //reference to slide that needs to hide
		var changeCause    = "Auto"; //what causes the slides to change.. 
									   //can be 'Click' for clicking on the nav or 'Auto' for auto rotation
		
		var options, slideList, slideDescList, slideInterval;
		
	/**
	 * PUBLIC METHODS
	 */
		this.togglePause = function(){
			pausePlay();
			
		/*
		 * added so that pause on hover doesnt toggle the slideshow to play when 
		 * the slideshow has been paused intentionally by something else
		 */
			if(isPlaying)
				options.pauseOnHover = true;
			else
				options.pauseOnHover = false;
		}
		
		this.setHoverOnPause = function(value){
			options.pauseOnHover = value; //true or false
		}
		
	
	/**
	 * SLIDE SHOW
	 */
		/**
		 * Hide the slides and give them appropriate z index.
		 * Show the first Slide.
		 */
		var setUpSlideShow = function(){
			
			if(slideList.length > 1){
				for(var i=0; i<slideList.length; i++){
					$(slideList[i]).css('z-index', String(slideList.length-i)).css('position', 'absolute').hide();
					
					if(options.slideDesc != null)
						$(slideDescList[i]).css('z-index', String(slideDescList.length-i)).css('position', 'absolute').hide();
				}
			}
			
			if(options.type == "sequence"){
				
				showFirstSlide();
				
				if(options.autoRotate)
					setUpTimer();
				
			}else{
				alert('Innerfade-Type must either be \'sequence\', \'random\' or \'random_start\'');
			}
		}
		
		
		/**
		 * Display the first slide and its description.
		 */
		var showFirstSlide = function(){
			
			$(slideList[0]).show();
	        
			if(options.slideDesc != null)
	        	$(slideDescList[0]).show();
	        
	        if(options.slideShowNav != null){
	        	$("#"+options.slideShowNav+" li").removeAttr("id");
	    		$("#"+options.slideShowNav+" .slide_0").attr("id", "button_selected");
	    	}
		}
		
		
		/**
		 * Shows the new slide using the updated ids.
		 * Hide the old slide before showing the new one.
		 */
		var showSlide = function(){
			
			initiateCallBack("start");
			
			switch(options.animationtype){
				case "fade":
					//fade out the old slide before fading in the new one
						$(slideList[oldSlideID]).fadeOut(options.speed);
						if(options.slideDesc != null)
							$(slideDescList[oldSlideID]).fadeOut(options.speed);
						
					//fade in the new slide
						$(slideList[currentSlideID]).fadeIn(options.speed, function() {
							removeFilter($(this)[0]);
							initiateCallBack("end");
						});
						if(options.slideDesc != null){
							$(slideDescList[currentSlideID]).fadeIn(options.speed, function() {
								removeFilter($(this)[0]);
							});
						}
					break;//end fade
			}
		
		//update nav items
			if(options.slideShowNav != null){
				$("#"+options.slideShowNav+" li").removeAttr("id");
				$("#"+options.slideShowNav+" .slide_"+currentSlideID).attr("id", "button_selected");
			}
		}
		
		
		/**
		 * Updates the current slide id and keeps a reference to the last id.
		 * These will be used by showSlide method.
		 */
		var nextSlide = function(){
			
			changeCause = "Auto";
			
			/*
			 * if it is not at the end, show the next one otherwise show the first one
			 * and keep a reference to the last id
			 */ 
			if(currentSlideID < (slideList.length-1)){
				oldSlideID      = currentSlideID;
				currentSlideID += 1;
				var biTagNameAuto 	= $('.slide_'+currentSlideID).attr("name");   
                crmEvent4({"num":currentSlideID+1, "placement":"Auto", "name":biTagNameAuto, "pageType":biPageType, "flashHTML":biPageType});
			}else{
				oldSlideID      = currentSlideID;
				currentSlideID  = 0;
				counter        += 1; //count everytime the slide reaches the end

			}
			
			//stop auto rotating if max rotate count is reached
			if(counter == options.maxRotateCount){
				stopTimer();
			}
			
			//show the slide using the updated ids
			showSlide();
		}
		
		
		var pausePlay = function(){
			//make sure it's set to auto rotate before toggling
			if(options.autoRotate){
				if(isPlaying){
		    		
					if(options.slideShowPauseBTN != null){
						$("#"+options.slideShowPauseBTN+" span").html("play");
						$("#"+options.slideShowPauseBTN).attr("class", "paused_button");
					}

		    		stopTimer();
		        	
		    	}else{
		    		
		    		if(options.slideShowPauseBTN != null){
		    			$("#"+options.slideShowPauseBTN+" span").html("pause");
		    			$("#"+options.slideShowPauseBTN).attr("class", "pause_button");
						
	    		}
		        	
					setUpTimer(); //load next slide
		    	}
			}
		}
		
		
		/**
		 * Attach a click even to the nav items and grab the id from them.
		 */
		var setUpNavButtons  = function(){
			
			var buttonClass, splitButtonClassString, buttonClassString;
			
			$("#"+options.slideShowNav+" li").each(function(){
				
				$(this).click(function(){
					
					if(options.slideShowPauseBTN != null){
						$("#"+options.slideShowPauseBTN+" span").html("play");
						$("#"+options.slideShowPauseBTN).attr("class", "paused_button");
					}
					
					buttonClass              = $(this).attr("class");
					splitButtonClassString   = buttonClass.split("_");
					buttonClassString        = splitButtonClassString.pop();
		            oldSlideID               = currentSlideID;
		            currentSlideID           = parseFloat(buttonClassString);  
					
                    var biTagName 			 = $(this).attr("name");
                    crmEvent4({"num":currentSlideID+1, "placement":"Number", "name":biTagName, "pageType":biPageType, "flashHTML":biPageType});
					
		            changeCause = "Click";
		            
		            options.autoRotate     = false; //turns off auto rotate
		            

					
		            stopTimer();
		            showSlide();
				});
				
			});//each
		}
		
		
		/**
		 * If there's a pause button, attach click to it
		 */
		var setUpPauseButton = function(){
			
			var pauseButton = $(options.slideShowPauseBTN);
			
			pauseButton.click(function(){
				togglePause();
			});
		}
		
		
		/**
		 * If slide desc is available use that for the hover on pause,
		 * otherwise use the slide itself.
		 */
		var setUpPauseOnHover = function(){
			
			if(options.slideDesc != null){
				slideDescList.hover(function(){
					if(options.pauseOnHover)
						pausePlay();
				});
			}else{
				slideList.hover(function(){
					if(options.pauseOnHover)
						pausePlay();
				});
			}
		}
		
		
	/**
	 * UTILS
	 */
		var getDefaults = function(){
			
			return { animationtype     : 'fade',
					 speed             : 'normal',
					 type              : 'sequence',
					 timeout           : 5000,
					 containerheight   : 'auto',
					 autoRotate        : false,
					 maxLoopCount      : 0,
					 pauseOnHover      : false,
					 slideDesc         : null,
					 slideShowNav      : null,
					 slideShowPauseBTN : null,
					 slideChangeStart  : null,
					 slideChangeEnd    : null       
				  };
		}
		
		var setUpTimer = function(){
			isPlaying     = true;
			slideInterval = setInterval(nextSlide, options.timeout);
		}

		var stopTimer = function(){
			isPlaying         = false;
			
			if(slideInterval != null){
				clearInterval(slideInterval);
				slideInterval = null;
			}
		}
		
		/**
		 * remove Opacity-Filter in ie
		 */ 
		var removeFilter = function(target){
			if(target.style.removeAttribute){
				target.style.removeAttribute('filter');
			}
		}
		
		
		/**
		 * Call the callback methods and pass in information so that it can be used by the listener.
		 */
		var initiateCallBack = function(name){
			
			var slideTagName;
			
			/**
			 * Grab the name of the slide from the nav items if there are any
			 * otherwise use the id from the slide elements
			 */
			if(options.slideShowNav != null){
				slideTagName = $('.slide_'+currentSlideID).attr("name");
			}else{
				slideTagName = $(slideList[currentSlideID]).attr("id");
			}
			
			var callbackArgs = { slideID   : currentSlideID,
								 cause     : changeCause,
								 tagName   : slideTagName,
								 count     : counter
						       };
				
			switch(name){
				case "start":
						$.isFunction( options.slideChangeStart ) && options.slideChangeStart.call(this, callbackArgs);
					break;
				case "end":
						$.isFunction( options.slideChangeEnd ) && options.slideChangeEnd.call(this, callbackArgs);
					break;
			}
		}
		
		
	/**
	 * INIT
	 */
		var init = function(){
			
			var defaults   = getDefaults();
			options        = $.extend(defaults, options );
			
			element.css({ position :"relative", 
						  height : options.containerheight})
				   .addClass(PLUGIN_NAME);
			
			slideList      = element.children();
			
			if(options.slideDesc != null)
				slideDescList  = $("ul#"+options.slideDesc+" li");
			
			if(options.slideShowNav)
				setUpNavButtons();
			
			if(options.slideShowPauseBTN)
				setUpPauseButton();
			
			if(options.pauseOnHover)
				setUpPauseOnHover();
			
			setUpSlideShow();
		}
		init();
		
		
	}//slideshow class
	
	
})(jQuery);

