/**
 * Creates a story gallery, displays a random story upon start up, and rotates through the available stories until the user
 * selects a specific story.  Requires a javascript object data source that contains an array of objects with the following 
 * attributes/properties: headline, teaser, image, thumb, href.
 * 
 *  -Headline should be the text you want displayed as the story headline.  Also used for the alt text of the image, and for the 
 *    'read more' text.
 *    
 *  -Teaser should be the paragraph text you want displayed
 *  
 *  -Image should be the location of and the image file that you want displayed
 *  
 *  -Thumb should be the location of and the image file you want to be used as the thumbnail in the control section
 *  
 *  -Href is the location and file of where the 'read more' links should point to
 * 
 * @author Paul F. Gilzow, Web Communications, University of Missouri
 * @copyright 2008, Curators of the University of Missouri
 * @version 0.35.2008.03.10
 * @uses mootools v1.11 or greater w Core.Core, Native.Array, Native.String, Native.Function, Native.Number, Native.Element, 
 * Element.Event, Window.DomReady, Fx.Base, Fx.CSS, Fx.Style, Fx.Transitions
 * @example
 * 		<script src="mootools.js" type="text/javascript"></script>
 *		<script src="class.muGallery.js" type="text/javascript"></script>
 *		<script type="text/javascript">
 			
 *			var dataGallerySource = [
 *					{
 *                   	"headline":"The Missourian Unstructure",
 *                   	"teaser":"&#8220;First you blow up the structure,&#8221; says Tom Warhover, <em>Columbia Missourian<\/em> executive editor. &#8220;Then you reorganize.&#8221; Change in the newsroom brought surprises for everyone, including Warhover himself. Read his account, the first in a series about this project.",
 *                   	"image":"./home.php_files/temp-lead.jpg",
 *						"thumb":"./home.php_files/temp-thumb.jpg",
 *						"href":"lead1.htm"
 *					},
 *					{
 *						"headline":"a 2nd headline",
 *						"teaser":"First you collect underpants, then you...???..., and then, PROFIT!",
 *						"image":"./home.php_files/lead2.jpg",
 *						"thumb":"./home.php_files/temp-thumb2.jpg",
 *						"href":"lead2.htm"
 *					},
 *					{
 *						"headline":"a 3rd headline",
 *						"teaser":"Kenny is crushed to death in the Underpants Gnomes underground lair when one of their trolley carts falls on him. Stan and Kyle deliver their trademark \"Oh my God, they killed Kenny \"You [censored]\" speech very fast as if they're not particularly troubled by the incident.",
 *						"image":"./home.php_files/lead3.jpg",
 *						"thumb":"./home.php_files/temp-thumb3.jpg",
 *						"href":"lead3.htm"
 *					}
 *			];
 *
 *			var myGallery = new objMuGallery('muGallery',dataGallerySource,true,2000);	
 *			
 *      </script>
 *
 *
 * @TODO code clean-up, change the buildGallery section to just build the pieces and NOT actually set up
 * the initial story, then run updateStory afterwards(?)
 * @TODO there are binding issues with both the start and buildErrors functions. 
 * @TODO add additional error checking to make sure the data source has the correct properties 
 */
objMuGallery = new Class({
	/**
	 * Sets up the class to truly start once the dom is ready
	 * 
	 * @param {String} strGalleryID
	 * @param {Object} objDataSource
	 * @param {Boolean} boolRandom
	 * @param {Integer} intFadeDuration
	 * @param {Integer} intStoryDuration
	 */
	initialize:function(strGalleryID,objDataSource,boolRandom,intFadeDuration,intStoryDuration){
		window.addEvent('domready',function(){
			this.start(strGalleryID,objDataSource,boolRandom,intFadeDuration,intStoryDuration);		
		}.bind(this));		
	},
	
	/**
	 * Sets up the defaults for the object, does error checking to make sure it has what it needs.  If so then creates the 
	 * gallery, sets up a random starting story (if applicable), and creates and starts the story rotator.  If not, it 
	 * hijacks the page and displays a list of error to the user.
	 * 
	 * @param {String} strGalleryID The ID of the element where you want the Gallery to be 
	 * @param {Object} objDataSource the JSON object that has the information on the stories
	 * @param {Boolean} boolRandom whether or not you want a random story on start-up.  Default is false.
	 * @param {Integer} intFadeDuration how much time (in milliseconds) for the fade effect.  Default is 750.
	 * @param {Integer} intStoryDuration how much time (in milliseconds) should each story should be displayed.  Default is 10000. 
	 */
	start:function(strGalleryID,objDataSource,boolRandom,intFadeDuration,intStoryDuration){
		this.error 				= false;
		this.errMsgs 			= new Array();
		this.fadeDuration 		= 600; 
		this.storyDelay			= 0;
		this.storyDuration 		= 6000;
		this.boolRandomOnStart 	= false;
		this.initialindex		= 0;
		this.galName			= 'MU Gallery Rotator';
		this.errMsgHeaderText	= 'Errors Encountered with the ' + this.galName;
		this.errMsgIntroText	= 'I apologize for the inconvenience, but the following errors were encountered while trying to create the ' + this.galName;
		
		if($type(strGalleryID) == 'string' && strGalleryID != '' && $chk($(strGalleryID))){
			this.galleryID = strGalleryID;
		} else {
			this.error = true;
			this.errMsgs.include('I have to have the ID of the element that will contain the Gallery, and that element must exist.');			
		}
		
		if(($type(objDataSource) == 'object' || $type(objDataSource) == 'array') && objDataSource.length > 0) {
			this.datasource = objDataSource;	
		} else {
			this.error = true;
			this.errMsgs.include('I have to have a valid Data Source');	
		}
		
		if($defined(boolRandom)){
			var strCantDetermineBoolRandom = 'I am unable to determine if you want a random story on start-up.  Please include a boolean true or false as your value.';
			switch($type(boolRandom)){
				case 'string':
					switch(boolRandom){
						case 'true':
							this.boolRandomOnStart = true;
							break;
						case 'false':
							this.boolRandomOnStart = false;
							break;
						default:
							this.error = true;
							this.errMsgs.include(strCantDetermineBoolRandom);
							break;
					}	
					break;
				case 'boolean':
					this.boolRandomOnStart = boolRandom;
					break;
				default:
					this.error = true;
					this.errMsgs.include(strCantDetermineBoolRandom);
					break;
			}	
		} 
		
		if($defined(intFadeDuration)){
			this.SetFadeDuration(intFadeDuration);			
		}
		
		if($defined(intStoryDuration)){
			this.SetStoryDuration(intStoryDuration);	
		}
		
		if(!this.error){
			//do we need a random index for the startup?
			if(this.boolRandomOnStart){
				this.initialindex = $random(0,(this.datasource.length - 1));
			}
			
			this.currentindex = this.initialindex;
			
			//let's build the gallery elements and start the rotator
			this.beginGallery();
					
		} else {
			this.buildErrors();
		}
		
	},
	/**
	 * Error checks what we were given for the fade duration.  If we can convert what they gave us to an integer, we set the internal
	 * fade storage container (this.fadeDuration) to the passed value, and then calculate the delay for the story change, and fade 
	 * back in.  If there is an error, we set the error notifier to true, and add a message to the error array.
	 * 
	 * @param {Integer} intFadeDuration
	 */
	SetFadeDuration:function(intFadeDuration){
		var strCantDetermineFadeDuration = 'I am unable to determine how long you want the Fade Duration to be. Please double-check the value you have provided.  Remember, Fade Duration is in milliseconds.';
		switch($type(intFadeDuration)){
			case 'number':
				if(intFadeDuration > 0){
					this.fadeDuration = intFadeDuration;
				}
				break;
			case 'string':
				if(intFadeDuration != ''){
					this.fadeDuration = intFadeDuration.toInt();
				}
				break;
			default:
				this.error = true;
				this.errMsgs.include(strCantDetermineFadeDuration);
				break;
		}
		
		if($defined(this.fadeDuration)){
			this.storyDelay = (this.fadeDuration * 1.333).toInt();
		}		
	},
	
	/**
	 * Error checks what we were given for the story duration.  If we can convert what they gave us to an integer, we set the internal
	 * story duration storage container (this.storyDuration).  If there is an error, we set the error notifier to true, and add a 
	 * message to the error array.
	 * 
	 * @param {Integer} intStoryDuration
	 */
	SetStoryDuration:function(intStoryDuration){
		var strCantDetermineStoryDuration = 'I am unable to determine how long you want the Story Duration to be. Please double-check the value you have provided.  Remember, Story Duration is in milliseconds.';
		switch($type(intStoryDuration)){
			case 'number':
				this.storyDuration = intStoryDuration;
				break;
			case 'string':
				this.storyDuration = intStoryDuration.toInt();
				break;
			default:
				this.error = true;
				this.errMsgs.include(strCantDetermineStoryDuration);
				break;
		}	
	},
	
	/**
	 * Grabs the element that was given to us on initialization, empties it, builds the elements we need for the gallery, and sets 
	 * the story to the initialindex.
	 */
	buildGallery:function(){
		objCurrentStory = this.datasource[this.initialindex];
		var galGallery = $(this.galleryID);
		
		//we'll empty out the gallery container
		galGallery.empty();
		
		//now we'll need a link for our header
		var galHeaderLink = new Element('a',{
			href:objCurrentStory.href
		});
		galHeaderLink.setHTML(objCurrentStory.headline);
		//and the header
		var galHeader = new Element('h2',{
			id:'gal-headline'
		});
		//we'll insert our link for the header into the header
		galHeader.appendChild(galHeaderLink);
		//and insert the header into our gallery div
		galGallery.appendChild(galHeader);

		

		//now we'll rebuild the whole thing piece by piece
		//we need a container div for the image so we can set the background color to be the same as the controler
		var galImageContainer = new Element('div',{
			id:'gal-img-contain'
		});
		
		//insert the div into our gallery
		galGallery.appendChild(galImageContainer);
		

		//first the main image
		var galMainImg = new Element('img',{
			src:objCurrentStory.image,
			alt:objCurrentStory.headline,
			id:'gal-main-img'
		});
		
		
		//next the link that goes around our main image
		var galMainImageLink = new Element('a',{
			href:objCurrentStory.href,
			id:'gal-main-img-link'
		});
		
		//we'll insert our image into our link
		galMainImageLink.appendChild(galMainImg);
		//and our image into our gallery
		galImageContainer.appendChild(galMainImageLink);
			
		//now the div for our controls
		var galControl = new Element('div',{
			id:'gal-controls'
		});
		
		galGallery.appendChild(galControl);
		
	
		
		
		
		
		//and now we need our readmore stuff
		var galReadMoreLink = new Element('a',{
			id:'gal-readmore-link',
			href:objCurrentStory.href		
		});
		galReadMoreLink.setHTML('Read more about ' + objCurrentStory.headline);
		
		//and the readmore paragraph
		galReadMore = new Element('p',{
			id:'gal-readmore',
			'class':'read-more'
		});
		
		//insert the link into our paragraph
		galReadMore.appendChild(galReadMoreLink);
		//and insert the paragraph into our gallery
		galGallery.appendChild(galReadMore);			
	},
	
	/**
	 * Updates the story to the index that is passed to us
	 * 
	 * @param {Integer} intUpdateTo the index we want to update the story to
	 */
	updateStory:function(intUpdateTo){
		this.imgEffect = new Fx.Style('gal-main-img','opacity',{duration:this.fadeDuration,transition: Fx.Transitions.Quart.easeInOut});
		this.imgEffect.start(1,0);
		var galHeadline		= $('gal-headline');

		var galMainImageLink= $('gal-main-img-link');
		var galMainImage	= $('gal-main-img');
		var galControl		= $('gal-controls');
		var galReadMorelink = $('gal-readmore-link');
		var objStory		= this.datasource[intUpdateTo];
		var lengthDataSource= this.datasource.length;
		
		//we need to set a delay on this so we'll set it as an anonymous function and append the delay		
		(function(){
			galMainImage.src = objStory.image;
			galMainImage.alt = objStory.headline;
			//now lets set the link on the image to the actual story
			galMainImageLink.href = objStory.href;
			//let's update the header
			if(galHeadline.hasChild()){
				var headlineLink = galHeadline.getChildren();
				headlineLink.href = objStory.href;
				headlineLink.setText(objStory.headline);	
			} else {
				galHeadline.empty();
				var headlineLink = new Element('a',{
					href:objStory.href	
				});
				
				headlineLink.setHTML(objStory.headline);
				galHeadline.appendChild(headlineLink);	
			}

			
			
		}).delay(this.storyDelay);	
		
		this.imgEffect.start.pass([0,1],this.imgEffect).delay(this.storyDelay);
	},
	
	/**
	 * Displays any error messages we have encountered
	 */
	buildErrors:function(){
			var errBody = $E('body');
			errBody.empty();
			
			var errHeader = new Element('h2',{
				id:'gal-error-header'
			});
			errHeader.setText(this.errMsgHeaderText);
			var errMsgIntro = new Element('p',{id:'gal-error-intro'});
			errMsgIntro.setText(this.errMsgIntroText);
			errBody.appendChild(errHeader);
			errBody.appendChild(errMsgIntro);
			var errList = new Element('ul',{id:'gal-error-list'});
			
			var intErrMsgIterate = 1;
			
			this.errMsgs.each(function(errMsg){
				var newErrMsg = new Element('li',{id:'gal-error-message-' + intErrMsgIterate});
				newErrMsg.setHTML(errMsg);
				errList.appendChild(newErrMsg);
				intErrMsgIterate++;			
			});
			
			errBody.appendChild(errList);			
	},

	/**
	 * If everything passes our error checks in the start function, we will then fire our buildgallery function, create our
	 * rotator, and sets the rotator to cycle to the amount of time given to us by intStoryDuration
	 * 
	 * @param {Object} objGal reference to our class
	 */	
	beginGallery:function(){
			this.buildGallery();
			
			this.rotator = (function(){
				
				if(this.currentindex == (this.datasource.length - 1)){
					this.currentindex = 0;
				} else {
					this.currentindex = this.currentindex + 1;
				}

				this.updateStory(this.currentindex);
					
			}.bind(this)).periodical(this.storyDuration);	
	}
	
}); 

/**
 * CHANGE LOG
 * 2008.03.10 - realized that I cant check for the existance of an element until after the DOM is loaded, so I have rearranged
 *   everything.  initialize now adds the start function (which was the initialize) to the domready state.  What was the 
 *   start function is now the beginGallery function.  I also updated the builderror function to work with -this- instead of
 *   passing it to the function as a parameter.
 * 2008.03.06 - finished the buildErrors function
 * 2008.02.14 - added a check in the initialization for fade duration that only sets it to the passed in parameter if the value given
 * is greater than 0, or is not empty ('').  Also added a setOpacity to the thumbnail in the buildGallery function.
 * 
 */
