/*@FILE INFORMATION
----------------------------------------
Author:		Mark Wise 
File:		ImageGallery_1.0.4.js 
Created:	12/11/09 5:11 PM
Updated:	3/9/10 9:45 AM

/*@END--------------------------------*/










/*@IMAGE COLLECTION MODEL
----------------------------------------
imageCollection = [
	{source:"", caption:"", href:"", alt:""},
	{source:"", caption:"", href:"", alt:""}

]
/*@END--------------------------------*/

var ImageGallery = new Class({
	//CONSTRUCTOR
	initialize:function(ele, arr, hsh){
		//Declare local scope variables
		var ele = $(ele), imageOld, imageNew, spinner, tempArray;
		
		//Is 'ele' an element
		if($defined(ele)){
			//Initialize 'Spinner' object and pass 'ele' as an argument
			spinner = new Spinner(ele, {
				message: "Loading"
					
			});
			//Passing a boolean value of true will show the spinner immediately, which is what we
			//want while the images are being preloaded
			spinner.show(true);
			//Try to get a reference to '.image_old'; will return null if '.image_old' is not an element
			imageOld = ele.getElement('.image_old');
			//Try to get a reference to '.image_new'; will return null if '.image_new' is not an element
			imageNew = ele.getElement('.image_new');
			
			//Is 'image_old' and 'image_new' elements
			if($defined(imageOld) && $defined(imageNew)){
				//Assign 'imageOld' to an instance variable so it can be referenced by class methods
				this.imageOld = imageOld;
				//Assign 'imageNew' to an instance variable so it can be referenced by class methods
				this.imageNew = imageNew;
				//Initialize Fx object and pass 'imageNew' as an argument
				this.fx = new Fx.Tween(this.imageNew, {
					onComplete:function(){
						//Set 'this.eventLock' to false to allow an image to be transitioned
						if(this.eventLock) this.eventLock = false;
						//Set google analytics attribute
						ele.set("ga", this.getGoogleAnalytics());
						//Set new href attribute for 'ele'
						ele.store('href', this.getImageHref());
						//If an href is defined, change the default cursor to a pointer
						if(this.getImageHref() != 'javascript:void(0)'){
							ele.addClass('cursor');
							
						}else{
							ele.removeClass('cursor');
						
						}
						//Set alt attribute if it exists; will default to an empty string ""
						this.imageNew.set('alt', this.getImageAlt());
						//Call optional function after all updates are complete
						if(this.listener.afterUpdate) this.listener.afterUpdate(); 
						//Start the delay to transition one image if the 'setDelay' method has been
						//called on the instance of the ImageGallery object
						if(this.delay.use) this.startDelay();
																												
					}.bind(this)
								
				});
					
			}
				
		}
			
		//Does an array collection exist
		if(arr){
			this.imageCollection = arr.filter(function(item){
				//Source is required; If there is no source, remove item from array
				if(item.source) return item;
			
			});
				
		}
		this.arrayLength = (this.imageCollection)? this.imageCollection.length : 0;
		this.arrayIndex = -1;
		this.imageGalleryTitle = (hsh && hsh.imageGalleryTitle)? hsh.imageGalleryTitle : "\u00a0";
		this.imagePath = (hsh && hsh.imagePath)? hsh.imagePath : "";
		this.imageExtension = (hsh && hsh.imageExtension)? hsh.imageExtension : "";
		this.eventLock = true;
		this.delay = {
			use:false,
			id:null,
			seconds:3000
						
		};
		this.listener = {
			beforeUpdate:null,
			afterUpdate:null
		
		};
		
		
		//Make sure the array has items in it before we try to preload images
		if(this.arrayLength > 0){
			//Map a temp array of all the image sources so the images can be preloaded
			tempArray = this.imageCollection.map(function(item){
				return this.imagePath + item.source + this.imageExtension;
			
			}.bind(this));
			
			//Preload images
			var pre = new Asset.images(tempArray, {
				onComplete:function(){
					//Set 'this.eventLock' to false to allow an image to be transitioned
					this.eventLock = false;
					//Try to transition one image
					this.nextImage();
					//Hide loading spinner
					spinner.hide();
				
				}.bind(this)
						
			});
					
		}
													
	},
	//PRIVATE	
	updateImageGalleryDisplay:function(){
		//Call optional function before updates are started
		if(this.listener.beforeUpdate) this.listener.beforeUpdate(); 
		//Set the bottom image source to the top image source
		this.imageOld.set("src", this.imageNew.get("src"));
		//Make the top image transparent and load it's new source
		this.imageNew.setStyle("opacity", 0).set("src", this.getImageSource());
		//Fade in the top image
		this.fx.cancel().start("opacity", 1);
	
	},
	//PRIVATE
	nextArrayIndex:function(){
		if(this.arrayLength > 0){
			this.arrayIndex = (this.arrayIndex + 1) % this.arrayLength;
			
		}
					
	},
	//PRIVATE
	prevArrayIndex:function(){
		if(this.arrayLength > 0){
			var n = this.arrayIndex - 1;
			this.arrayIndex = (n < 0)? n + this.arrayLength : n;
			
		}
		
	},
	//PRIVATE
	setArrayIndex:function(arrayIndex){
		this.arrayIndex = arrayIndex;
			
	},
	//PRIVATE
	startDelay:function(){
		//Register the delay functions id
		this.delay.id = function(){
			//Try to transition one image
			this.nextImage();
							
		}.delay(this.delay.seconds, this);
	
	},
	//PRIVATE
	clearDelay:function(){
		//Clear the delay and set 'this.delay.id' to null
		this.delay.id = $clear(this.delay.id);
				
	},
	//PUBLIC
	beforeUpdate:function(fnc){
		//Is an argument defined and is it a function
		if($defined(fnc) && $type(fnc) == 'function'){
			this.listener.beforeUpdate = fnc;
		
		}
		
	},
	//PUBLIC
	afterUpdate:function(fnc){
		//Is an argument defined and is it a function
		if($defined(fnc) && $type(fnc) == 'function'){
			this.listener.afterUpdate = fnc;
		
		}
	
	},
	//PUBLIC
	nextImage:function(){
		//Clear the delay to prevent transition overlap
		this.clearDelay();
		//Is the event lock in use
		if(!this.eventLock){
			//Prevents any further action until the transition is complete
			this.eventLock = true;
			//Increment the array's index by one
			this.nextArrayIndex();
			//Change the image
			this.updateImageGalleryDisplay();
			
		}
	
	},
	//PUBLIC
	prevImage:function(){
		//Clear the delay to prevent transition overlap
		this.clearDelay();
		//Is the event lock in use
		if(!this.eventLock){
			//Prevents any further action until the transition is complete
			this.eventLock = true;
			//Decrement the array's index by one
			this.prevArrayIndex();
			//Change the image
			this.updateImageGalleryDisplay();
			
		}
		
	},
	//PUBLIC
	setImageIndex:function(imageIndex){
		//Clear the delay to prevent transition overlap
		this.clearDelay();
		//Is the event lock in use
		if(!this.eventLock){
			//Prevents any further action until the transition is complete
			this.eventLock = true;
			//Set the array's index to the passed value
			this.setArrayIndex(imageIndex.toInt() - 1);
			//Change the image
			this.updateImageGalleryDisplay();
			
		}
	
	},
	//PUBLIC
	getArrayIndex:function(){
		return this.arrayIndex;
		
	},
	//PUBLIC
	getArrayLength:function(){
		return this.arrayLength;

	},
	//PUBLIC
	getImageIndex:function(){
		if(this.arrayLength > 0){
			//Define local scope variables
			var imageIndex, characters;
			//The image index is always the current array index plus one
			imageIndex = this.arrayIndex + 1;
			//Calculate the number of zeros to prepend to the image index
			characters = this.arrayLength.toString().length - imageIndex.toString().length;
			//Prepend zeros and return the string
			return "0".repeat(characters) + imageIndex;
			
		}
		
	},
	//PUBLIC
	getImageGalleryTitle:function(){
		return this.imageGalleryTitle;
			
	},
	//PUBLIC
	getGoogleAnalytics:function(){
		//If the image collection array does not exist and it is referenced as an array, a javascript
		//error will be thrown. Always check for the existence of 'this.imageCollection'.
		if(this.imageCollection) return this.imageCollection[this.arrayIndex].ga || '';
		
	},
	//PUBLIC
	getImageSource:function(){
		//If the image collection array does not exist and it is referenced as an array, a javascript
		//error will be thrown. Always check for the existence of 'this.imageCollection'.
		if(this.imageCollection) return this.imagePath + this.imageCollection[this.arrayIndex].source + this.imageExtension;
		
	},
	//PUBLIC
	getImageCaption:function(){
		//If the image collection array does not exist and it is referenced as an array, a javascript
		//error will be thrown. Always check for the existence of 'this.imageCollection'.
		if(this.imageCollection) return this.imageCollection[this.arrayIndex].caption || "\u00a0";
	
	},
	//PUBLIC
	getImageHref:function(){
		//If the image collection array does not exist and it is referenced as an array, a javascript
		//error will be thrown. Always check for the existence of 'this.imageCollection'.
		if(this.imageCollection) return this.imageCollection[this.arrayIndex].href || "javascript:void(0)";
	
	},
	//PUBLIC
	getImageAlt:function(){
		//If the image collection array does not exist and it is referenced as an array, a javascript
		//error will be thrown. Always check for the existence of 'this.imageCollection'.
		if(this.imageCollection) return this.imageCollection[this.arrayIndex].alt || "";
	
	},
	//PUBLIC
	setDelay:function(sec){
		//Lets other code know that a delay is being used
		this.delay.use = true;
		//Is an argument defined and is it a number
		if($defined(sec) && $type(sec) == 'number'){
			//Set the seconds as milliseconds so the timer understands the value
			this.delay.seconds = sec * 1000;
				
		}
					
	},
	//PUBLIC
	isLocked:function(){
		return this.eventLock;
		
	}

});




