(function($) {
	$.fn.models = function() {
		/*
		WHAT IT DOES: formats & provides funtionality for the chapter viewer in "model.aspx".  Singleton class as the model browser should only appear once per page.
		HOW IT WORKS: $jQueryObject.models();
		*/

		var $controller = $(this);
		var $chapters = $controller.children("section");
		var $window = $(window);
		var limit = $chapters.length - 1;
		var currChapter = -1;
		var points = {
			// set start & end points for animating chapters in & out
			outRight: $window.width() - $controller.offset().left + 20,
			outLeft: -20 - $controller.offset().left - $controller.width()
		};
		var duration = 1000;
		var easing = "easeInOutExpo";
		var btnsFrag = '<a href="" class="btn-chapter btn-next"></a><a href="" class="btn-chapter btn-prev"></a><span id="hover-txt"><em>Next:</em> <strong>Title</strong></span>';
		var $next = null;
		var $prev = null;
		var $hoverTxt = null;
		var $hoverDir = null;
		var $hoverLabel = null;
		var navFrag = '<div id="model-nav"><ul class="clearfix"></ul><div>';
		var $nav = null;
		var $navItems = null;
		var $techList = $("#technology");
		var $techListUl = $techList.find("ul");
		var $techListToggle = $techList.find("h4");
		var $techItems = $("#technology a");
		//var $techPlayer = $("#technology-video-holder");
		//var $techTitle = $techPlayer.find("h2 strong");
		//var $closeTech = $("#close-tech");
		var techOut = -900;
		var techShown = false;

		$(this).addClass("active")
			.height($chapters.eq(0).height())
			.append(btnsFrag)
			.before(navFrag);

		// next / previous arrows --------------------------------
		$next = $(".btn-next");
		$prev = $(".btn-prev");
		$hoverTxt = $("#hover-txt");
		$hoverDir = $hoverTxt.find("em");
		$hoverLabel = $hoverTxt.find("strong");

		$next.data({
			increment: 1,
			dir: "Next:",
			posProp: "right"
		}).hover(arrowHover, arrowOut)
			.click(arrowClick)

		$prev.data({
			increment: -1,
			dir: "Last:",
			posProp: "left"
		}).hover(arrowHover, arrowOut)
			.click(arrowClick)

		function arrowHover() {
			// work out which side to show the popup on
			var me = $(this);
			var prop = me.data().posProp;
			var val = parseInt(me.css(me.data().posProp)) + 40;

			$hoverTxt.stop(true, true)
			//.hide()
				.css({
					left: "auto",
					right: "auto",
					width: "auto"
				}).css(prop, val);

			// get & apply text
			$hoverDir.text(me.data().dir);
			$hoverLabel.text($chapters.eq(currChapter + me.data().increment).find("h2:first").text());

			var gotoWidth = $hoverTxt.width();
			$hoverTxt.css("width", 0)
				.show()
				.animate({ width: gotoWidth }, duration / 2, "easeOutExpo");
		}

		function arrowOut() {
			$hoverTxt.fadeOut(duration / 2, "easeOutExpo");
		}

		function arrowClick() {
			var me = $(this);
			me.trigger("mouseout");
			$controller.trigger("newChapter", [me.data().increment]);
			return false;
		}

		// chapter navigation --------------------------------

		$nav = $("#model-nav ul");
		var frag = "";
		var w = 0; 	// width of menu pre-resizing
		var r = 0; 	// remainder
		var adjust = 0; // amount to add to the width of each item

		$chapters.each(function(i) {
			frag += '<li><a href="">' + $(this).find("h2:first").text() + "</a>";
		});

		$nav.append(frag);

		// attach behaviours to the chapter nav items
		$navItems = $nav.children("li");
		$navItems.each(function(i) {
			var me = $(this);

			w += me.width();

			me/*.hover(
					function() {
						//$(this).stop().animate({ top: 6 }, duration / 2, "easeOutExpo")
					}, function() {
						//$(this).stop().animate({ top: 0 }, duration / 2, "easeOutExpo")
					}
			)*/.click(function(e) {
				e.preventDefault();
				var count = i - currChapter;
				$controller.trigger("newChapter", [count]);
			});
		}).append("<span></span>")
			.filter(":last").addClass("last");

		// distribute remaining space evenly between items
		r = $controller.width() - w - 2;
		adjust = r / $navItems.length;
		$navItems.each(function(i) {
			var me = $(this);
			me.width(me.width() + adjust);

			if (me.height() > 34) {
				me.addClass("fix-line-height");
			}
		});

		// position chapters offscreen
		$chapters.css("left", points.outRight);

		// technology vid player & nav --------------------------------
		/*
		// position technology vid player off top of screen
		$techPlayer.data("inity", parseInt($techPlayer.css("top")))
		.css("top", techOut);
		
		// attach behaviours to the technology icons
		$techItems.click(function() {
		$techItems.removeClass("selected");
		var me = $(this);
		me.addClass("selected");
		$techTitle.text(me.attr("title"));
		$controller.trigger("showTech");
		return false;
		});
		
		if($techList.length) {
		// setup expand / collapse behaviours on tech list
		$techList.data({
		expY: parseInt($techList.css("top")) + 15,
		conY: parseInt($techList.css("top")) + $techListUl.outerHeight(true)
		});
		$techList.css("top", $techList.data().conY);

			$techListToggle.toggle(
		function() {
		$(this).addClass("open");
		$techListUl.slideDown(duration / 2, "easeOutExpo");
		$techList.animate({ top: $techList.data().expY }, duration / 2, "easeOutExpo");
		},
		function() {
		$(this).removeClass("open");
		$techListUl.slideUp(duration/2, "easeOutExpo");
		$techList.animate({ top: $techList.data().conY }, duration / 2, "easeOutExpo");
		}
		);

			// attach behaviour to tech vid player "hide" button
		$closeTech.click(function() {
		$controller.trigger("hideTech");
		return false;
		});
		}
		*/

		// BEHAVIOURS ================================================

		this.bind("newChapter", function(event, options) {
			var outgoing = currChapter;

			pauseAllVideos();

			// increment / decrement currChapter to constraints
			currChapter += options;
			if (currChapter > limit) {
				currChapter = limit;
			} else if (currChapter < 0) {
				currChapter = 0;
			}

			// animate chapters to correct position
			$chapters.each(function(i) {
				var x = 0;
				var anim = false;
				var contiguous = false;
				var me = $(this);

				if (i < currChapter) {
					x = points.outLeft;
				} else if (i > currChapter) {
					x = points.outRight;
				}

				// is this a next / prev or is it a jump from the menu?
				if (i > (currChapter - 1) && i < (currChapter + 1)) {
					contiguous = true;
				}

				// only animate if contiguous or incoming / outgoing
				if (contiguous || (i === outgoing) || (i === currChapter)) {
					me.stop().animate({ left: x }, duration, easing);
				} else {
					me.stop().css("left", x);
				}

			});

			window.location.hash = '#' + sanitiseName(
				$navItems.eq(currChapter)
					.find('a')
						.text()
			);

			$controller.trigger("checkDisable");

			// show the selected item in the nav
			$navItems.removeClass("selected")
				.stop().animate({ top: 0 }, duration / 2, "easeOutExpo")
				.eq(currChapter)
					.find("span")
						.css("bottom", 0)
						.end()
					.addClass("selected")
					.stop()
						.animate({ top: 4 }, duration / 4, "easeInExpo")
						.delay(500)
						.animate({ top: 0 }, duration / 4, "easeOutExpo");

			$navItems.eq(currChapter)
				.find("span")
					.delay((duration / 4) + 500)
					.animate({ bottom: -4 }, duration / 4, "easeOutExpo");
		});

		this.bind("checkDisable", function(event, options) {
			// check whether we need to disable one of the buttons
			if ($(".ie7, .ie8").length) {
				(currChapter == 0)
					? $prev.hide()
					: $prev.show();
				(currChapter == limit)
					? $next.hide()
					: $next.show();
			} else {
				(currChapter == 0)
					? $prev.fadeOut(duration / 1, easing)
					: $prev.fadeIn(duration / 1, easing);
				(currChapter == limit)
					? $next.fadeOut(duration / 1, easing)
					: $next.fadeIn(duration / 1, easing);
			}

		});

		this.bind("showTech", function(event, options) {
			if (!techShown) {
				$("#model-nav").animate({ "margin-top": $controller.height() + 108 }, duration, "easeOutExpo");
				$techList.animate({ "margin-top": -72 }, duration, "easeOutExpo");
				$techPlayer.animate({ top: $techPlayer.data("inity") }, duration, "easeOutExpo");
				techShown = true;
			}
		});

		this.bind("hideTech", function(event, options) {
			if (techShown) {
				$("#model-nav").animate({ "margin-top": 0 }, duration, "easeInOutExpo");
				$techList.animate({ "margin-top": 0 }, duration, "easeInOutExpo");
				$techPlayer.animate({ top: techOut }, duration, "easeInOutExpo");
				$techItems.removeClass("selected");
				techShown = false;
			}
		});

		// INIT ================================================
		if (window.location.hash != "") {	// if we have a hash path
			var foundChapterIndex = -1;

			$("#model-nav").find('a').each(function(i, e) {
				if (sanitiseName($(e).text()) == window.location.hash.substr(1)) {
					foundChapterIndex = i;
				}
			});

			if (foundChapterIndex != -1) {			// try find the chapter from the hash path
				$controller.trigger("newChapter", [foundChapterIndex + 1]);
			} else {						// call first chapter
				$controller.trigger("newChapter", [1]);
			}
		} else {							// call first chapter
			$controller.trigger("newChapter", [1]);
		}

	}

	function sanitiseName(name) {
		return name.replace(/[^A-Z0-9]/gi, "");
	}

})(jQuery);

