if(typeof(fgould) == "undefined") fgould = {};


fgould.createUniqueId = function createUniqueId(prefix, suffix) {
	var id = prefix + (new Date().getTime()) + suffix;
	while(document.getElementById(id) != null) {
		id = prefix + (new Date().getTime()) + suffix;
	}
	return id;
};


fgould.createSlidingPageBanner = function(containerId, config, images) {
	var banner = new fgould.SlidingPageBannerController(containerId, config, images);

	// Hook the banner into the home and navigation links
	var elements = [$E('#global-header a')];
	elements = elements.concat($ES('#global-nav a'));

	var setSelected = function setSelected(index) {
		location.replace('#banner' + index);
		for (var i = 0; i < elements.length; i++) {
			if (i == index) {
				elements[i].addClass('selected');
			} else {
				elements[i].removeClass('selected');
			}
		}
	};
	banner.onbannerchange = function(banner, index) {
		setSelected(index);
	};

	var linkClick = function linkClick(event) {
		event = new Event(event);
		event.preventDefault();
		event.stopPropagation();

		// Identify which link was clicked
		var selectedLink = (event.target || event.srcElement);
		while (selectedLink && selectedLink.tagName != "A") {
			selectedLink = selectedLink.parentNode;
		}

		// Update selected appearance
		var selectedIndex = 0;
		for (var i = 0; i < elements.length; i++) {
			if (elements[i] == selectedLink) {
				selectedIndex = i;
				break;
			}
		}

		// Show the corresponding banner
		banner.setBanner(selectedIndex, true);
	};
	elements.forEach(function(element) {
		element.addEvent('click', linkClick);
	});

	// If a banner is indicated by the fragment, show it
	var hash = location.hash;
	if (hash && hash.match(/^#?banner[0-9]+$/)) {
		if (hash.charAt(0) == '#') {
			hash = hash.substring(1, hash.length);
		}
		var index = parseInt(hash.substring(6, hash.length));
		banner.setBanner(index, false);
	}
	
};


fgould.SlidingPageBannerController = function SlidingPageBannerController(containerId, config, images) {
	if(images.length == 0) return;
	
	this.containerId = containerId;
	this.config = config;
	this.width = images[0].width;
	this.height = images[0].height;
	
	var ready = []; // Banners which are loaded;
	var banners = [];
	
	// Create the banners, and mark each as ready when its images have loaded.
	for(var i = 0; i < images.length; i++) {
		ready[i] = false;
		banners[i] = this.createBanner(
			images[i],
			(function(j) {
				return function() {
					ready[j] = true;
				};
			})(i)
		);
	}

	this.images = images;
	this.ready = ready;
	this.banners = banners;
	this.onbannerchange = null;
	
	// Add all the banners to the container
	var container = document.getElementById(this.containerId);
	if(container) {
		while (container.firstChild) {
			container.removeChild(container.firstChild);
		}
		container.style.overflow = 'hidden';
		var scroller = document.createElement('div');
		scroller.style.position = 'relative';
		scroller.style.width = (this.width * this.banners.length) + 'px';
		scroller.style.height = (this.height) + 'px';
		container.appendChild(scroller);
		container.scrollLeft = 0;
		container.scrollTop = 0;

		for(var i = 0; i < banners.length; i++) {
			banners[i].style.position = 'absolute';
			banners[i].style.left = (this.width * i) + 'px';
			banners[i].style.top = 0 + 'px';
			scroller.appendChild(banners[i]);
		}
	}
	
	this.setBanner(0, false);
};


// Create a banner matching the default markup for
// the given image data. If an `onload` function is
// supplied, it will be attached to the img tag's
// `onload` event.
fgould.SlidingPageBannerController.prototype.createBanner = function createBanner(data, onload) {
	var banner = document.createElement('div');
	banner.className = 'mtbanner';

	var imageMap = null;
	var imgContainer = banner;
	if (data.hotspot_href) {
		if (data.hotspot_shape == '') {
			a = document.createElement('a');
			a.href = data.hotspot_href;
			banner.appendChild(a);
			imgContainer = a;
		} else {
			imageMap = document.createElement('map');
			imageMap.name = fgould.createUniqueId('mtbanner', '-map');
			var area = document.createElement('area');
			area.shape = data.hotspot_shape;
			area.coords = data.hotspot_coords;
			area.href = data.hotspot_href;
			area.alt = data.hotspot_alt;
			imageMap.appendChild(area);
			banner.appendChild(imageMap);
		}
	}
	
	var img = document.createElement('img');
	img.width = data.width;
	img.height = data.height;
	img.className = 'mtbanner-image';
	if(imageMap) {
		img.useMap = '#' + imageMap.name;
	}
	if(onload) {
		if(img.addEventListener) {
			img.addEventListener("load", onload, false);
		} else if(img.attachEvent) {
			img.attachEvent("onload", onload);
		}
	}
	img.src = data.image_url;
	imgContainer.appendChild(img);
	
	if(data.copy) {
		var copy = document.createElement('div');
		copy.className = 'mtbanner-copy';
		copy.innerHTML = data.copy;
		banner.appendChild(copy);
	}
	return banner;
};


fgould.SlidingPageBannerController.prototype.setBanner = function setBanner(index, animate) {
	this.currentIndex = index;
	this.transition(index, animate);
	if (this.onbannerchange) {
		this.onbannerchange(this, index);
	}
};


fgould.SlidingPageBannerController.prototype.transition = function transition(index, animate) {
	var transition;
	if (animate) {
		transition = fgould.SlidingPageBannerController.Transitions.slide;
	} else {
		transition = fgould.SlidingPageBannerController.Transitions.none;
	}
	index = Math.min(Math.max(0, index), this.banners.length - 1);
	transition(this, index);
};


fgould.SlidingPageBannerController.Transitions = {
	none: function replaceTransition(controller, index) {
		var container = document.getElementById(controller.containerId);
		container.scrollLeft = controller.width * index;
	},

	slide: function _genericTransition(controller, index) {
		var container = document.getElementById(controller.containerId);
		var minDuration = 500, maxDuration = 1000;
		
		if (controller.effectInterval) {
			clearInterval(controller.effectInterval);
			delete controller.effectInterval;
		}

		var startScrollLeft = container.scrollLeft;
		var endScrollLeft = controller.width * index;

		if (startScrollLeft == endScrollLeft) {
			return;
		}

		// Calculate how far we're scrolling compared to the maximum scroll
		// distance, as a number 0.0 - 1.0.
		var scrollFraction = (
			(Math.abs(endScrollLeft - startScrollLeft) - controller.width) /
			(controller.width * (controller.banners.length - 2))
		);
		var duration = minDuration + scrollFraction * (maxDuration - minDuration);

		var easeInOut = function(p) {
			var sine = function(p) {
				return 1 - Math.sin((1 - p) * Math.PI / 2);
			};

			if (p <= 0.5) {
				return sine(2 * p) / 2;
			} else {
				return (2 - sine(2 * (1 - p))) / 2;
			}
		};

		var update = function(progress) {
			progress = easeInOut(progress);
			container.scrollLeft = startScrollLeft + progress * (endScrollLeft - startScrollLeft);
		};
			
		update(0);
		var start = new Date().getTime();
		var end = start + duration;
		if (end <= start) {
			update(1);
		} else {
			controller.effectInterval = setInterval(function() {
				var t = new Date().getTime();
				progress = Math.min((t - start) / (end - start), 1);
				update(progress);
				if (progress == 1) {
					clearInterval(controller.effectInterval);
					delete controller.effectInterval;
				}
			}, 30);
		}
	}
};

