/*--------------------------------------------------------------------------------
ben.js

--------------------------------------------------------------------------------*/

this.BEN_NICHOLAS = {
	version: 0.3,
	name: "Ben Louis Nicholas"
};

// :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

(function(window, app, environment, $) {
	
	var config = {
		debug: true,
		
		selectedClass: "selected",
		
		carousel: {
			crud:"<div class='scroll-pane'><div class='items'></div></div>",
			controls:
				"<div class='controls'><div>\
					<div class='nav'>\
						<a class='button prev'><span><span> &larr; Previous</span></span></a>\
						<a class='button next'><span><span>Next &rarr;</span></span></a>\
					</div>\
				</div></div>",
			pageCounter:
				"<div class='counter'>\
					<span class='index'></span> of\
					<span class='total'></span>\
				</div>"
		}
	};
	
	if (config.debug && 
			typeof window.console !== "undefined" &&
			typeof window.console.debug !== "undefined") {
		app.log = function(message, level) {
			window.console[level || "info"](message);
		};
		app.dump = function(obj) {
			window.console.log(obj);
		};
	} else {
		app.log = app.dump = function() {};
	}
		
	app.instances = {};
	
	function jqNamespaceCheck(meth) {
		if ($.prototype[meth]) {
			app.log("$.prototype." + meth + " already exists!", "warn");
			return false;
		}
		return true;
	}
	
	jqNamespaceCheck("intersects");
	$.prototype.intersects = function(b) {
		var a, aw, ah, bw, bh, ax, ay, bx, by, p;
		if (!(b instanceof $)) {
			if (typeof b === "string") { b = $(b); }
			else { return false; }
		}
		a = this;
		
		aw = a.outerWidth();
		ah = a.outerHeight();
		bw = b.outerWidth();
		bh = b.outerHeight();
		if (aw <= 0 || ah <= 0 || bw <= 0 || bh <= 0) { 
			return false; 
		}
			
		p = a.offset();
		ax = p.left;
		ay = p.top;
		
		p = b.offset();
		bx = p.left;
		by = p.top;
		
		aw += ax;
		ah += ay;
		bw += bx;
		bh += by;
		
		return ( (aw < ax || aw > bx) &&
		         (ah < ay || ah > by) && 
		         (bw < bx || bw > ax) &&
		         (bh < by || bh > ay) );
	};
	
	app.navMenu = function(options) {
		var $nm, sections, o, pick;
		app.log("app[navMenu]");
		
		o = $.extend({
			selector:".nav",
			slideSpeed: 60,
			accordionToggleAction: "click"
		}, options);
		
		$nm = $(o.selector);
		sections = [];
		
		pick = function(section, shouldToggle) {
			var list, isAlreadyCurrent;
			
			isAlreadyCurrent = section.hasClass(config.selectedClass);
			list = section.getListWrapper();
			
			if (shouldToggle) {
				section.toggleClass(config.selectedClass);
				list.slideToggle(o.slideSpeed);
			} else if (!isAlreadyCurrent) {
				section.addClass(config.selectedClass);
				list.slideDown(o.slideSpeed);
			}
						
			section.siblings().each(function() {
				var sib = $(this),
					sibList = sib.children("ul");
					
				if (sib.hasClass(config.selectedClass)) {
					sib.removeClass(config.selectedClass);
					sibList.slideUp(o.slideSpeed);
				}
			});
		};
		
		$nm.children("ul").children("li").each(function(i) {
			var section, ul, items;
			
			section = $(this);
			ul = section.children("ul");
			items = ul.children("li");
			
			section.children("h2").bind(o.accordionToggleAction, function(e) {
				pick(section, true);
			});
			
			section.pick = function(index, callback) {
				var item;
				if (!index || index < 0) { 
					index = 0; 
				} else if (index > items.length - 1) { 
					index = items.length -1; 
				}
				item = items.eq(index);
				if (item.length === 1) {
					item.addClass(config.selectedClass);
					item.siblings().removeClass(config.selectedClass);
					if ($.isFunction(callback)) {
						callback(item);
					}
				}
				return section;
			};
			
			section.getListWrapper = function() {
				return ul;
			};
			
			section.getItems = function() {
				return items;
			};
			
			sections[i] = section;
		});
		
		$nm.pickByPath = function(path) {
			app.log("app[navMenu][pickByPath](" + path[0] + ", " + path[1] + ")");
			var section = sections[path[0]];
			if (section) {
				pick(section, false);
				section.pick(path[1]);
			}
			return $nm;
		};
		
		$nm.pickByID = function(id) {
			app.log("app[navMenu][pickByID](" + id + ")");
			$.each(sections, function(i) {
				sections[i].getItems().each(function(j) {
					if ($(this).attr("id") === id) {
						return $nm.pickByPath([i, j]);
					}
				});
			});
			return $nm;
		};
					
		return $nm;
	};
	
	jqNamespaceCheck("carousel");
	$.prototype.carousel = function(options) {
		var carousel = this,
			scrollPane,
			scrollable,
			controls,
			pageCounter,
			currentIndex = 0,
			o = $.extend({
				scrollableOptions:{
					circular:false,
					speed:300
				},
				unitSelector:"p",
				galleryMode: true
			}, options),
			updatePageCounter = function(index, total) {
				currentIndex = index - 1;
				pageCounter.find(".index").text(index);
				if (total) {
					pageCounter.find(".total").text(total);
				}
			},
			handleControlsPosition = function() {
				var currentItem, modeClass;
				
				function enterHandler(e) {
					controls.css("opacity", 1.0);
				}
				function leaveHandler(e) {
					controls.css("opacity", 0.0);
				}
				
				currentItem = scrollPane.children("div:first").children(o.unitSelector).eq(currentIndex);
				modeClass = "overlay";
				
				if (controls.intersects(currentItem)) {
					if (!controls.hasClass(modeClass)) {
						controls.css("opacity", 0.0);
					}
					controls.addClass(modeClass);
					currentItem.bind("mouseenter", enterHandler);
					controls.bind("mouseenter", enterHandler);
					currentItem.bind("mouseleave", leaveHandler);
				} else {
					controls.removeClass(modeClass);
					currentItem.unbind("mouseenter", enterHandler);
					controls.unbind("mouseenter", enterHandler);
					currentItem.unbind("mouseleave", leaveHandler);
				}
			},
			width,
			height;
		
		app.log("jQuery[carousel]");	
		
		if (o.galleryMode) {
			height = $(window).height();
			$("body").addClass("scroll-lock");
		}

		carousel.find(o.unitSelector).wrapAll(config.carousel.crud);
		width = carousel.width();
		carousel.width( width );
		carousel.find(o.unitSelector).each(function() {
			var unit = $(this), img;
			unit.width( width );
			if (o.galleryMode) {
				img = unit.find("img").eq(0);
				img.removeAttr("width").removeAttr("height");
			}
		});
		controls = $(config.carousel.controls);
		controls.width( width );
		carousel.append(controls);
		pageCounter = $(config.carousel.pageCounter);
		
		scrollPane = carousel.find("div:first");
		if (o.galleryMode) {
			scrollPane.height( height );
		}
		scrollable = scrollPane.scrollable(o.scrollableOptions).data("scrollable");
		scrollable.onSeek(function() {
			updatePageCounter(scrollable.getIndex() + 1);
			handleControlsPosition();
		});
		
		updatePageCounter( scrollable.getIndex() + 1, scrollable.getSize() );
		controls.find("div:first").append(pageCounter);
		handleControlsPosition();

		carousel.click(function() {
			scrollable.focus();
		});
		
		/**
		 * Returns the scrollabe api handle
		 */
		carousel.getHandle = function() {
			return scrollable;
		};
				
		return carousel;
	};

// :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

	/**
	 * Kick-off
	 */
	$(function() {
		var carousels; 
		
		app.log("document[ready]");

		carousels = $(".carousel");
		if (carousels.length) {
			app.instances.carousels = [];
			carousels.each(function(i) {
				app.instances.carousels[i] = carousels.eq(i).carousel();
			});
			app.instances.carousels[0].getHandle().focus();
		}
		
		app.instances.menu = app.navMenu();
		if (environment && environment.menuID) {
			app.instances.menu.pickByID(environment.menuID);
		}
		
		app.dump(app.instances);
	});
	
	app.log("::::::::::::::::::::::::::::::::::::::::::::::::");
	app.log(app.name + " " + app.version);
	app.log("::::::::::::::::::::::::::::::::::::::::::::::::");
	
}(this, this.BEN_NICHOLAS, this.ENVIRONMENT, this.jQuery));

