// Initialize general application variables.
msMenuList.currentPane = msMenuList.initialView;
msMenuList.currentItem = -1;
msMenuList.camWindowName = 'wcwin';
msMenuList.camWindowOpts = 'width=480,height=360,resizable=no,scrollbars=no,toolbar=no,location=no,directories=no,status=no,menubar=no,copyhistory=no,screenX=200,screenY=250,left=200,top=250';

// Construct interface widgets.
msGutter = $("<div id='ms_gutter'></div>")
	.appendTo(msMenuList.parentNode)
	.get(0);
msHandle = $("<div id='ms_handle' title='Drag left and right to scroll.'></div>")
	.appendTo(msGutter)
	.get(0);

// This will be called using Flash's ExternalInterface class.
// It uses an pseudo-delay (timer is set to zero) to break the connection from the
// calling Flash plugin.  This averts a bug in the Flash plugin under Firefox which
// causes the browser to crash if the object is unloaded after viewing full-screen
// and without losing focus in the mean time.
function msCloseFlash(closeNow) {
	if (closeNow) {	
		var flashDiv = document.getElementById('ms_flash_wrap');
		while (flashDiv.childNodes.length)	flashDiv.removeChild(flashDiv.lastChild);
		flashDiv.style.display = 'none';
		msMenuList.currentItem = -1;
	} else {
		window.setTimeout('msCloseFlash(true)', 0);
	}
}

// Fetch galleries from XML source.
addEvent (window, 'load', function () {
	createAjaxObject ();
	
	// Request the XML containing the options and then parse it when it is received.
	xmlHTTP.sendRequestXML (msMenuList.xmlLocation, function (root) {
		// Function to switch to a different panel.
		function swapPanel (paneKey) {
			// Switch new list items into view.
			msMenuList.currentPane = paneKey;
			msMenuList.currentItem = -1;
			while (msMenuList.lastChild)
				msMenuList.removeChild (msMenuList.lastChild);
			for (var i = 0; i < msMenuList.panes[paneKey].length; ++i)
				msMenuList.appendChild (msMenuList.panes[paneKey][i]);
			
			// Highlight the selected pane title.
			var header = document.getElementById('ms_header');
			for (var i = 0; i < header.childNodes.length; ++i)
				header.childNodes[i].className = header.childNodes[i].className.replace(/selected/, '');
			document.getElementById('ms_' + paneKey + '_link').className += 'selected';
			
			// Prevent the scrollbar from appearing if there is nothing to scroll.
			if (msMenuList.childNodes.length < msMenuList.minToScroll) {
				msGutter.style.display = 'none';
			} else {
				msGutter.style.display = 'block';
			}
		};
		
		// Click handler to select a media item.
		// Must be called as handler or member function of media item's <a> object.
		function selectItem () {
			msMenuList.currentItem = this.itemID;
			
			if (msMenuList.currentPane == 'webcam') {
				// Create pop-up.
				var popup = overlayPopup('webcamPopup', function () {
					var holder = document.createElement('div');
					holder.appendChild(document.createElement('img'));
					holder.appendChild(document.createElement('div'));
					holder.lastChild.appendChild(document.createElement('span'));
					holder.lastChild.lastChild.appendChild(document.createTextNode('New Window'));
					holder.lastChild.lastChild.className = 'new_window';
					addEvent(holder.lastChild.lastChild, 'click', function() {
						window.open(
							this.parentNode.parentNode.parentNode.extPage,
							msMenuList.camWindowName,
							msMenuList.camWindowOpts);
					});
					holder.lastChild.appendChild(document.createElement('span'));
					holder.lastChild.lastChild.appendChild(document.createTextNode('Close'));
					return holder;
				});
				popup.extPage = this.extPage;
				
				// Set up webcam image.
				var camImg = popup.firstChild.firstChild;
				camImg.style.visibility = 'hidden';
				camImg.src = camImg.rootSrc = this.dataSrc;
				addEvent(camImg, 'load', function () {
					this.style.visibility = 'visible';
				});
				
				// Set up auto-refresh.
				var camRefresher = window.setInterval(function () {
					camImg.src = camImg.rootSrc + '?refresh=' + (new Date()).getTime();
				}, msMenuList.camRefreshMsec);
				
				// Close pop-up if it's clicked anywhere.
				addEvent(popup, 'click', function () {
					clearInterval(camRefresher);
					closeOverlayPopup('webcamPopup');
				});
			} else {
				var flashWrapper = document.getElementById('ms_flash_wrap');
				var placeholder = document.createElement('div');
				placeholder.id = 'ms_flash';
				flashWrapper.appendChild (placeholder);
				
				var flashLocation = msMenuList.flashLocation[msMenuList.currentPane];
				var flashWidth = msMenuList.flashSize[msMenuList.currentPane].w;
				var flashHeight = msMenuList.flashSize[msMenuList.currentPane].h;
				
				if (msMenuList.currentPane == 'photo') {
					var flashVars = { xml : this.dataSrc };
					var flashParams = { allowfullscreen : 'true', wmode: 'opaque' }
				} else if (msMenuList.currentPane == 'video') {
					var flashVars = {
						'file' : this.dataSrc,
						'link' : this.extPage,
						'playlist' : 'none',
						'abouttext' : 'Bob Jones University',
						'aboutlink' : 'http://www.bju.edu/',
						'streamscript' : 'lighttpd',
						'autostart' : 'true',
						'controlbar' : 'over',
						'stretching' : 'exactfit',
						'plugins' : 'gapro-1',
						'gapro.accountid' : 'UA-4219663-1',
						'debug' : 'trace'
					};
					var flashParams = {
						'allowfullscreen' : 'true',
						'allowscriptaccess' : 'always'
					};
				}
				
				swfobject.embedSWF(
					flashLocation,
					'ms_flash',
					flashWidth,
					flashHeight,
					msMenuList.flashVersion,
					msMenuList.flashInstaller,
					flashVars,
					flashParams);
				
				document.getElementById('ms_flash').className = msMenuList.currentPane;
				
				if (msMenuList.currentPane == 'video') {
					flashWrapper.appendChild(document.createElement('span'));
					flashWrapper.lastChild.id = 'ms_close_media';
					addEvent(flashWrapper.lastChild, 'click', msCloseFlash);
				}
				
				flashWrapper.style.display = 'block';
			}
			
			return false;
		}
		
		// Remove all white space nodes from the XML document tree.
		cleanDOMTree (root);
		
		// Parse through the three panes.
		msMenuList.panes = {};
		for (var paneID = 0; paneID < root.childNodes.length; ++paneID) {
			var paneKey = root.childNodes[paneID].tagName;
			var paneData = root.childNodes[paneID];
			msMenuList.panes[paneKey] = [];
			// Construct a LI for each media option (but do not yet add to document tree).
			for (var itemID = 0; itemID < paneData.childNodes.length; ++itemID) {
				var myLI = document.createElement('li');
				var itemData = paneData.childNodes[itemID];
				msMenuList.panes[paneKey].push(myLI);
				myLI.appendChild (document.createElement('img'));
				myLI.lastChild.src = itemData.getElementsByTagName('thumb')[0].firstChild.nodeValue;
				myLI.appendChild (document.createElement('a'));
				myLI.lastChild.href = '#';
				myLI.lastChild.dataSrc = itemData.getElementsByTagName('data')[0].firstChild.nodeValue;
				var pageTag = itemData.getElementsByTagName('page');
				if (pageTag.length) {
					myLI.lastChild.extPage = pageTag[0].firstChild.nodeValue;
				}
				myLI.lastChild.itemID = itemID;
				myLI.lastChild.appendChild (document.createElement('span'));
				myLI.lastChild.lastChild.appendChild (document.createTextNode(itemData.getElementsByTagName('title')[0].firstChild.nodeValue));
				
				// Add event handler to display the media item when an option is selected.
				addEvent (myLI.lastChild, 'click', selectItem);
			}
		}
		
		// Dynamically add event handlers to pane title links.
		var header = document.getElementById('ms_header');
		cleanDOMTree (header);
		for (var i = 0; i < header.childNodes.length; ++i) {
			addEvent (header.childNodes[i], 'click', function () {
				// Parse the pane hash key out of its XHTML id.
				var paneKey = this.id.replace(/(^ms_)|(_link$)/g, '');
				
				msCloseFlash();
				msHandle.style.left = '0';
				msMenuList.style.left = '0';
				swapPanel (paneKey);
				return false;
			});
		}
		
		// Start display with the correct initial view.
		document.getElementById('ms_loader').style.display = 'none';
		swapPanel (msMenuList.initialView);
	});
});

msHandle.updateScrollPos = function (newPos, animate) {
	var maxScroll = msMenuList.maxScroll = $(msGutter).width() - msHandle.offsetWidth;
	
	// Reality-check the new scrollbar handle position.
	if (newPos < 0) newPos = 0;
	else if (newPos > maxScroll) newPos = maxScroll;
	
	// Calculate the new offset of the media option list.
	var menuWidth
		= msMenuList.lastChild.offsetLeft
		+ msMenuList.lastChild.offsetWidth
		- msMenuList.parentNode.offsetWidth
		+ msMenuList.firstChild.offsetLeft;
	var scrollRatio = newPos / maxScroll;
	var newMenuOffset = 0 - (scrollRatio * menuWidth);
	
	if (animate) {
		$(msHandle).animate({left: newPos + 'px'}, 'fast', 'swing');
		$(msMenuList).animate({left: newMenuOffset + 'px'}, 'fast', 'swing');
	} else {
		msHandle.style.left = newPos + 'px';
		msMenuList.style.left = newMenuOffset + 'px';
	}
};

// Set up scroll bar handling.
$(msHandle).mousedown(function (e) {
	function msMouseMove (e) {
		msHandle.updateScrollPos(msHandle.startPos + (e.pageX - msHandle.startMouse));
		return false;
	}
	
	// When the user lets go of the mouse button, stop tracking movement.
	function msMouseUp (e) {
		$(document).unbind('mousemove', msMouseMove);
		$(document).unbind('mouseup', msMouseUp);
	}
	
	msHandle.startMouse = e.pageX;
	msHandle.startPos = msHandle.offsetLeft;
	
	$(document).mouseup(msMouseUp);
	$(document).mousemove(msMouseMove);
	
	return false;
});

// Set up gutter to enable jump-clicking.
$(msGutter).click(function (e) {
	// If the click was on the handle, don't jump.
	if (e.target != this) return;
	
	// If the click was above or below the handle, don't jump.
	if (e.pageY < $(msHandle).offset().top || e.pageY > $(msHandle).offset().top + msHandle.offsetHeight) return false;
	
	var newPos = e.pageX - $(msGutter).offset().left - parseInt($(msGutter).css('padding-left')) - (msHandle.offsetWidth / 2);
	msHandle.updateScrollPos(newPos, true);
});