/** simpleCarousel (requires jquery)
 * use to build an interactive carousel
 * expects a div with other child divs each containing thier own content
 * each div needs an id and the "carouselPanel" class
 * the panel nav is generated dynamically
 * other optional features include deferred image loading via js
 * and calling init and complete callbacks on slide in and slide out
 *
 * @param settings (a settings object see below)
 *
 * the settings object defines two requred and other optional values eg.
 *
 * var settings = {
 * 		// [required] targetId is the id of the carousel container
 * 		targetId: "myCarousel",
 *
 * 		// [required] slideTimeout is how long in ms until the next as slides in
 * 		slideTimeout: 8000,
 *
 * 		panels: {
 * 			// optionally add javascript features to a panel by creating a panel object with a key matching its id
 * 			sometargetId: {
 *
 * 				// optionally load images with javascript to manage loading, images will be loaded in
 * 				// it is recomended that you code the image into the html for the first panel, this will provide a visual and its alt text for non js enabled sessions
 * 				images: [
 * 					// this is an array of n number of image objects as below, they get turned into img tags and appended to the panel in the order presented
 * 					{img:"path/img.gif"(required), alt:"alt text"(optional), id: "someIdForTheImage"(optional)}
 * 				],
 *
 * 				// optionally provide init and complete callbacks for a given panel
 * 				init: function() {
 * 					// this code will be called when the panel slides into view
 * 				},
 * 				complete: funciton() {
 * 					// this code will be called when the panel slides out of view
 * 				}
 * 			},
 * 		}
 * };
 * usage: simpleCarousel.init(settings);
 */
simpleCarousel = {
	widgets: {},

	init: function(settings) {
		var targetId = settings.targetId,
			duration = settings.slideTimeout,
			listNav = settings.listNav,
			prevId = settings.prevId,
			nextId = settings.nextId;
			
		// the simpleCarousel interface
		this.widgets[targetId] = {
			targetId: targetId,
			panels: settings.panels || {},
			listNav: settings.listNav,
			prevId: settings.prevId,
			nextId: settings.nextId,
			length: 0,
			panelWidth: $("#"+targetId)[0].clientWidth,
			currentIdx: 0,
			loadedLength: 0,
			panelInterval: false,
			panelTimeout: false,
			manageFocus: true,
			animating: false,
			animDuration: 650, // how long does it take to do the animation

			// set the current panel by its index
			setPanel: function(idx) {
				if(idx > this.length-1) {
					idx = 0;
				} else if(idx < 0) {
					idx = this.length-1;
				}

				var newPanel = $("#"+targetId+" div.carouselPanel:eq("+idx+")");
				var prevPanel = $("#"+targetId+" div.carouselPanel:eq("+this.currentIdx+")");

				// process the custom settings for the panel if there are any
				if(this.loadedLength < this.length) {
					this.initPanel(idx);
				}

				var panelProps = this.panels[newPanel[0].id];
				// if there is special init code associated with this panel, run it
				if(panelProps && panelProps.init) {
					panelProps.init();
				}

				// animation and postioning of panels
				if(idx < this.length && this.currentIdx+idx !== 0) {// no need to animate if bad idx or in the initial case
					
					var direction = 1;
					if(idx < this.currentIdx) {
						direction = -1;
						newPanel[0].style.left = -this.panelWidth+"px";
					}
					
					this.animating = true;
					// new panel: slide in
					newPanel.animate({
						left: 0,
						queue: false
					}, this.animDuration);

					// old panel: slide out
					prevPanel.animate({
						left: -this.panelWidth*direction,
						queue: false
					}, this.animDuration, function() {
						var carouselWidget = simpleCarousel.widgets[targetId];

						// after animation: reposition back to starting point
						carouselWidget.animating = false;
						this.style.left = $("#"+targetId)[0].clientWidth+"px";

						// if there is special init code to run for this panel run it
						var panelProps = carouselWidget.panels[this.id];
						if(panelProps && panelProps.complete) {
							panelProps.complete();
						}
					});
				}


				// update the nav ui
				var currentNav = $("#"+targetId+"Nav a.current");
				if(currentNav[0]) {
					currentNav[0].className = "";
				}

				var link = $("#"+targetId+"Nav a:eq("+idx+")");
				link[0].className = "current";
				// if the user has clicked on the panel nav, manage the focus
				if(this.manageFocus) {
					link.focus().blur();
				} else {
					link.blur();
				}
				
				this.currentIdx = idx;
				return this;
			},

			initPanel: function(idx) {
				var panel = $("#"+targetId+" div.carouselPanel:eq("+idx+")");
				var panelProps = this.panels[panel[0].id];
				// if there are custom settings for this panel proces them
				if(panelProps && !panelProps.added) {
					if(panelProps.images) {
						// given multiple img objects in an array
						for(var i=0, len=panelProps.images.length; i<len; i++) {
							this.addImage(panel, panelProps.images[i], idx);
						}
					}
					panelProps.added = true;
				} else {
					// move on to the next panel
					this.loadedLength++;
					this.initNextPanel(idx);
				}
			},

			addImage: function(panel, image, idx) {
				// construct the image
				if(image.img) {
					var img = document.createElement("img");
					img.alt = image.alt || null;
					img.id = image.id || null;
					img.style.display = "none";
					img.className = "preloaded";
					img.onload = function() {
						// hide the loading indicator
						this.parentNode.className = "carouselPanel";
						// show the image
						this.style.display = "block";
						// init the next panel
						var carouselWidget = simpleCarousel.widgets[targetId];
						carouselWidget.loadedLength++;
						carouselWidget.initNextPanel(idx);
					};
					// add the img to the ad
					panel.append(img);
					// show the loading indicator
					img.parentNode.className = "carouselPanel";
					img.parentNode.style.background = "url("+templateDirectory+"/img/ajax/loader-blue.gif) no-repeat 330px 115px;";
					// start loading the image
					img.src = image.img;
				}
			},

			initNextPanel: function(idx) {
				var nextIdx = idx+1;
				if(nextIdx < this.length) {
					this.initPanel(nextIdx);
				}
			},

			// next panel method
			next: function() {
				if(!this.animating) {
					this.setPanel(this.currentIdx+1);
				}
			},
			
			// next panel method
			prev: function() {
				if(!this.animating) {
					this.setPanel(this.currentIdx-1);
				}
			},

			play: function() {
				var carouselWidget = simpleCarousel.widgets[targetId];
				carouselWidget.stop();
				carouselWidget.panelInterval = setInterval(function() {
					carouselWidget.next();
				}, duration);
			},

			pause: function() {
				this.stop();
				var that = this;
				this.panelTimeout = setTimeout(function() {
					that.play();
				}, duration*2.5);
			},

			stop: function() {
				clearInterval(this.panelInterval);
				clearTimeout(this.panelTimeout);
			}
		};


		var panels = $("#"+targetId+" div.carouselPanel");

		// build the widget ui
		var nav = document.createElement("div");
		nav.id = targetId+"Nav";
		nav.targetId = targetId;
		if(!listNav) {
			nav.style.display = "none";
		}

		// create the nav section with a button for each of the panels
		var constructNavLink = function(targetId, id) {
			var carouselWidget = simpleCarousel.widgets[targetId];
			// pause for a while if the user hovers the panel
			// play agian on mouse out
			$("#"+targetId).unbind().hover(function() {
				carouselWidget.pause();
			}, function() {
				carouselWidget.play();
			});

			// stop animation if the user clicks in a panel
			panels.unbind().click(function() {
				carouselWidget.stop();
			});

			var link = document.createElement("a");
			link.href = "#"+id;
			link.targetId = targetId;
			link.idx = carouselWidget.length++;
			link.onclick = function() {
				var carouselWidget = simpleCarousel.widgets[this.targetId];
				carouselWidget.manageFocus = true;
				if(!carouselWidget.animating) {
					carouselWidget.setPanel(this.idx).pause();
				}
				return false;
			};
			link.onfocus = function() {
				var carouselWidget = simpleCarousel.widgets[this.targetId];
			};
			link.onblur = function() {
				var carouselWidget = simpleCarousel.widgets[this.targetId];
				carouselWidget.manageFocus = false;
			};
			return link;
		};

		panels.each(function(i) {
			// initial postion for panels
			this.targetId = targetId;
			this.style.position = "absolute";
			if(i > 0) {
				this.style.left = simpleCarousel.widgets[this.targetId].panelWidth+"px";
			}
			
			nav.appendChild(constructNavLink(targetId, this.id));
		});
		
		
		$("#"+targetId)[0].appendChild(nav);
		

		// start the carousel
		var carouselWidget = this.widgets[targetId];
		
		if(prevId) {
			$("#"+prevId).click(function() {
				carouselWidget.prev();
				return false;
			});
		}
		if(nextId) {
			$("#"+nextId).click(function() {
				carouselWidget.next();
				return false;
			});
		}
		
	 	carouselWidget.setPanel(0);
		carouselWidget.play();
	}
};



