
/**
 *  Copyright (c) 2007, Matt Snider, LLC. All rights reserved.
 *  Version: 1.0
 */

/**
 *  The PhotoViewer class manages slide show logic using 3 static references: image, showNext, showPrev; and dynamically added images using the global function 'addPhoto'.
 *  @namespace Core.Widget
 *  @class PhotoViewer
 *  @dependencies library
 */
 
var Core = {}; // create Core namespace
Core.Widget = {}; // create Widget namespace

Core.Widget.PhotoViewer = function() {

	//
	//	Constant variables
	//
	
	var $E = YAHOO.util.Event,
		$ = YAHOO.util.Dom.get;


	//
	//	Module variables
	//

	var self = null, // this value will contain a global reference to 'this' Object
		data = {}, // will contain references to each Image set
		index = 0, // the current index in the desired Image set
		set = []; // the current Image set


	//
	//	Module dom namespace
	//

	var dom = {
		image: 'image', // ID attribute to the 'img' tag to cycle images through
		next: 'showNext', // ID attribute to the 'a' tag to trigger showing the next image
		prev: 'showPrev' // ID attribute to the 'a' tag to trigger showing the prev image
	};


	//
	//	Module event namespace
	//

	var evt = {


		/**
		 *  Callback function for changing a set; the ID of the trigger element is used to determine the set
		 *  @param  e {Event} JavaScript Event triggering this function
		 *  @private
		 */
		onChange: function(e) {
			$E.stopEvent(e); // stops the anchor tag from executing its normal behavior; this way only this action occurs
			var targ = $E.getTarget(e); // get the click on element from the event
			if (! targ.id) {targ = targ.parentNode;} // ensure that the element is the anchor
			self.changeSet(targ.id); // changes the active set to the image group identified by the Attribute ID of triggering anchor tag
		},
		
		
		/**
		 *  Callback function for click next; increases the index by 1; when the index exceeds the greatest position in the set (set.length-1), the index is set to the first position in the set (0)
		 *  @param  e {Event} JavaScript Event triggering this function
		 *  @private
		 */
		onNext: function(e) {
			$E.stopEvent(e); // stops the anchor tag from executing its normal behavior; this way only this action occurs
			index++; // increase the index of set by one
			if (index == set.length) {index = 0;} // if exceeding the maximum length of the set, index should wrap to the first value
			self.changeImage(); // call global Function to actually change the image 
		},

		
		/**
		 *  Callback function for click previous; reduces the index by 1; when index is less than the smallest position in the set (0), the index is set to the last value in the set (set.length-1)
		 *  @param  e {Event} JavaScript Event triggering this function
		 *  @private
		 */
		onPrev: function(e) {
			$E.stopEvent(e); // stops the anchor tag from executing its normal behavior; this way only this action occurs
			index--; // decrement the index of set by one
			if (0 > index) {index = set.length-1;} // if exceeding the minimum length of the set, index should wrap to the last value
			self.changeImage(); // call global Function to actually change the image 
		}
	};


	//
	//	Public methods and constants
	//

	return {
			photoIndex: function(){
			return 'photo ' + index + ' of ' + set.length;
		},


		/**
		 *  function to call when adding an image to a set; the last image added determines the set that is active
		 *  @public
		 */
		addImage: function(group, url) {			
			// is there a data set for group of images; when no, add one to the 'data' Object
			if (! data[group]) {
				data[group] = []; // creates a new Array to fill with Images
			}
			
			set = data[group]; // retrieves the set (Array of Images) for group
			var img = new Image(); // creates a new instance of Image
			img.src = url; // links the Image Object to the image URL
			set.push(img); // appends the Image Object into the set
		},


		/**
		 *  function to change the image to the one in the current set @ index
		 *  @public
		 */
		changeImage: function() {
			var img = set[index]; // grab the Image from active set @ index
			dom.image.src = img.src; // actually change the image
		},


		/**
		 *  function to call when switching from one set to another
		 *  @public
		 */
		changeSet: function(group) {
			var s = data[group];
			
			if ('object' == typeof s && s.constructor == Array) { // verify that 'group' is a valid set
				index = 0; // reset the index
				set = data[group]; // change the set to that of group
				self.changeImage(); // update the image
			}
			else {
				alert('You are trying to change to an image set that is not defined: ' + group);
			}
		},


		/**
		 *  initialize the object, put elements here that use global object elements (like static variables)
		 *  @public
		 */
		init: function() {
			dom.image = $(dom.image);
			dom.next = $(dom.next);
			dom.prev = $(dom.prev);
			
			self = Core.Widget.PhotoViewer; // define global reference to 'this' Object
			
			// attach the next and previous events
			$E.addListener(dom.next, 'click', evt.onNext);
			$E.addListener(dom.prev, 'click', evt.onPrev);
			
			// iterate on through the data sets and attach the 'a' tags to trigger switching sets
			for (var k in data) {
				var chooseLink = $(k); // retrieve the set chooser 'a' tag from DOM				
				
				// ensure that the required 'a' tag exists and attach onChange event
				if (chooseLink) {
					$E.addListener(chooseLink, 'click', evt.onChange);
				}
				else {
					alert('Error: required set chooser link is missing for: ' + s);
				}
			}
			
			// iterate through the data sets to find the Image that is initially visible
			for (var k in data) {
				var s = data[k];
				
				for (var i=s.length-1; 0<=i; i--) {
					if (s[i].src == dom.image.src) {
						index = i;
						set = s;
						return;
					}
				}
			}
			
			alert('Warning: the initial image (' + dom.image.src + ') was not added to the image collection.');
		}
	};
}();

// delays loading of JavaScript until the page has finished
YAHOO.util.Event.onDOMReady(Core.Widget.PhotoViewer.init);

// creates a shortcut Function 'addPhoto' to reference the 'addImage' of management Object
var addPhoto = Core.Widget.PhotoViewer.addImage;
var photoindex = Core.Widget.PhotoViewer.photoIndex;
