function initGallery()
{
	var imageNode = createNode("img","galleryImage","",g_contentNode,"src",g_galleryEmptySrc);
	var imageTitle = createNode("div","galleryTitleNode","metadataTitle",g_dockImg2Node);
	var imageTitleImg = createNode("img","galleryTitleImage","",imageTitle,"src",g_galleryEmptySrc);
	var metadataFrame = createNode("div","metadataFrame","",g_sidebarNode);
	initMetadataNode("metadataNode1","title");
	initMetadataNode("metadataNode2","category");
	initMetadataNode("metadataNode3","client");
	var metadataFrame = document.getElementById("metadataFrame");
	var captionNode = createNode("div","captionNode","metadataCaption",metadataFrame);
	//initCaptionNode();
	//initLinkNode();
	initSort();
}

function initDock(linkIndex)
{
	var dockNavFrame = createNode("div","dockNavFrame","",g_galleryItemNode);
	initNavIcon(dockNavFrame, "prev", "dockArrowIcon");
	initNavIcon(dockNavFrame, "next", "dockArrowIcon");
}

function initMetadataNode(nodeID, label)
{
	var metadataFrame = document.getElementById("metadataFrame");
	var metadataNode = createNode("div",nodeID,"metadata",metadataFrame);
	var headerNode = createNode("div",nodeID,"metadataHeaderText",metadataNode);
	var headerText = createNode("text",label,headerNode);
	var bodyTextNode = createNode("div",label,"metadataLabelText",metadataNode);
	var bodyText = createNode("text","bodyText",bodyTextNode);
}

function initCaptionNode()
{
	var captionNode =  document.getElementById("captionNode");
	var itemDateNode = createNode("div","itemDate","metadataText",captionNode);
	var itemDateText = createNode("text","*",itemDateNode);
	var itemDescriptionNode = createNode("div","itemDescription","metadataText",captionNode);
	var itemDescriptionText = createNode("text","*",itemDescriptionNode);	
}

function initLinkNode()
{
	var captionNode = document.getElementById("captionNode");
	var captionLinkNode = createNode("div","captionLinkNode","captionLinkNode",captionNode);
	
	var menu = g_menuSystem[g_currentBranchIndex];
	var presentationMode = getPresentationMode(g_currentBranchIndex);
	var selectionIndex = getSelected(g_currentBranchIndex);
	
	var itemTitle = menu.itemTitle[selectionIndex];
	var itemCategory = menu.itemCategory[selectionIndex];
	var itemSize = menu.itemSize[selectionIndex];	
	var itemMedia = menu.itemMedia[selectionIndex];
	
	debugPrint(itemMedia);

	captionLinkNode.className = "captionFileLinkNode"
	createFileDescriptor(itemMedia, itemTitle, itemCategory, itemSize, captionLinkNode);
}

function getSelected()
{
	var menu = g_menuSystem[g_currentBranchIndex];
	
	for(var i=0;i<menu.isSelected.length;i++)
	{
		if(menu.isSelected[i]) selectionIndex = i;
	}

	return selectionIndex;
}

function getItemSelectState(queryIndex)
{
	var menu = g_menuSystem[g_currentBranchIndex];
	var itemSelectState = menu.isSelected[queryIndex];
	return itemSelectState;
}

function changeSelected(newSelectionIndex)
{
	var menu = g_menuSystem[g_currentBranchIndex];
	menu.isSelected[newSelectionIndex] = true; // update object state
	
	// reset other selection states to false
	for(i=0;i<menu.isSelected.length;i++)
	{
		if(i==newSelectionIndex) continue; // skip new selection index
		menu.isSelected[i] = false;
	}
}

function initSort()
{
	var presentationMode = getPresentationMode(g_currentBranchIndex);
	var categoryArray = new Array();
	var menu = g_menuSystem[g_currentBranchIndex];
	var node;
	
	switch(presentationMode)
	{
		case "images":
			categoryArray[0] = "date";
			break;
			
		case "design":
			categoryArray[0] = "date";
			break;
			
		case "motion":
			categoryArray[0] = "date";
			break;
	}
	
	if(categoryArray.length<1) return; // nothing further to do here

	var thumbFooterFrame = document.getElementById("thumbFooterFrame");
	
	// create sort control
	var header = createNode("div","sortHeader","sortHeaderHidden",thumbFooterFrame);
	var headerText = createNode("text","",header);
	var headerLineBreak = createNode("br","","",header);
	var headerText = createNode("text","",header);
	var catFrame = createNode("div","sortCategoryFrame","sortCategoryFrame",thumbFooterFrame);
	
	// create sort category items
	for(i=0;i<categoryArray.length;i++)
	{
		var sortIcon = createNode("div","sortIcon"+i,"sortIconInactive",catFrame);
		var sortCatNode = createNode("a","sortCategory"+i,"sortCategory",sortIcon,"href","javascript:void(0)");
		var sortCatText = createNode("text",categoryArray[i],sortCatNode);
		sortCatNode.onclick = sortHandler;
	}

	// deactivate all menu properties
	for(i in menu.sortLinkActive)
	{
		menu.sortLinkActive[i] = false;	
	}
	
	// first available category is activated by default
	var activeCategoryIndex = 0;
	var activeCategory = categoryArray[activeCategoryIndex];
	var activeIconNode = document.getElementById("sortIcon"+activeCategoryIndex);
	var identifier = getSortProperty(activeCategory);
		
	menu.sortLinkActive[identifier] = true; // activate initial menu property
	sortDirection = menu.sortDirection[identifier]; // get stored sort direction
	
	// update display state of selected
	switch(sortDirection)
	{
		case -1: activeIconNode.className = "sortIconDescend"; break;
		case 0: activeIconNode.className = "sortIconInactive"; break;
		case 1: activeIconNode.className = "sortIconAscend"; break;
	}

	sortMenu(sortDirection, identifier);
	
	// set selected index to index[0] of sorted list
	changeSelected(0);
}

function getSortProperty(category)
{
	switch(category)
	{
		case "category": identifier = "itemCategory"; break;
		case "client": identifier = "itemClient"; break;
		case "date": identifier = "itemDate"; break;
		case "magick": identifier = "magick"; break;
		case "title": identifier = "itemTitle"; break;
	}
	
	return identifier;
}

function updateSortHeader(identifier, sortDirection, menuCategory)
{
	var sortHeaderLabel = document.getElementById("sortHeader");
	var label1 = menuCategory[0];
	var label2 = menuCategory[menuCategory.length-1];
	var outputString = label1 +" \n " + label2;
	
	sortHeaderLabel.childNodes[0].data = label1+" -";
	sortHeaderLabel.childNodes[2].data = label2;		
	
	showSortHeader();
	
	// dim sort header after a delay
	g_sortTimer = setTimeout("hideSortHeader()", 3000);
}

function showSortHeader()
{
	var sortHeaderLabel = document.getElementById("sortHeader");
	sortHeaderLabel.className = "sortHeaderBright";
	clearTimeout(g_sortTimer); // in case it is still running
}

function hideSortHeader()
{
	var sortHeaderLabel = document.getElementById("sortHeader");
	sortHeaderLabel.className = "sortHeaderDim";
	clearTimeout(g_sortTimer);
}

function sortHandler()
{
	this.blur(); // get rid of mozilla link focus outline

	var selectedCategory = this.childNodes[0].data;
	var menu = g_menuSystem[g_currentBranchIndex];
	var numMenuItems = menu.itemName.length;
	var identifier = getSortProperty(selectedCategory);
	var sortDirection = menu.sortDirection[identifier];
	var sortLinkActive = menu.sortLinkActive[identifier];
	
	if(sortLinkActive)
	{
		// toggle menu property sortDirection and store updated value
		var sortDirection = -1*menu.sortDirection[identifier];
		menu.sortDirection[identifier] = sortDirection;
	}
	else
	{
		// activate selected menu property & deactivate the others
		for(i in menu.sortLinkActive)
		{
			menu.sortLinkActive[i]=(i==identifier)?true:false;
		}
	}

	var sortCategoryLink = this.parentNode;
	var sortCategoryFrame = document.getElementById("sortCategoryFrame");
	
	// reset display state of all links
	var numLinks = sortCategoryFrame.childNodes.length;
	for(i=0;i<numLinks;i++)
	{
		sortCategoryFrame.childNodes[i].className = "sortIconInactive";
	}
	
	// update display state of selected
	switch(sortDirection)
	{
		case -1: sortCategoryLink.className = "sortIconDescend"; break;
		case 0: sortCategoryLink.className = "sortIconInactive"; break;
		case 1: sortCategoryLink.className = "sortIconAscend"; break;
	}

	sortMenu(sortDirection, identifier);
}

function sortMenu(sortDirection, identifier)
{
	var menu = g_menuSystem[g_currentBranchIndex];
	var tempArray = new Array();
	var sortedArray = new Array();
	var counter = 0;
	var sortKey;

	// convert rows to columns 
	for(i in menu)
	{
		if(i=="menuItem"||i=="numItems") continue; // ignore these non-gallery related properties
		if(i==identifier) sortKey = counter; // determine index of identifier in tempArray
		tempArray.push(menu[i]);
		counter++
	}
	
	sortedArray = bubbleSort(tempArray,sortKey,sortDirection);
	updateSortHeader(identifier, sortDirection, sortedArray[sortKey]);
	refreshThumbnails();
}

function bubbleSort(theArray,sortKey,sortDirection)
{
	var i, j, sortOffset;
	var numCategories = theArray.length;
	var uniqueKey = 0; // index that contains filenames (which will always be unique per item)

	for (i=theArray[sortKey].length-1; i>0; i--)
	{
		for (j=0; j<=i; j++)
		{
			var cmpForward = (theArray[sortKey][j+1] < theArray[sortKey][j]);
			var cmpEqual = (theArray[sortKey][j+1] == theArray[sortKey][j]);
			var cmpReverse = (theArray[sortKey][j+1] > theArray[sortKey][j]);
			var cmpIdentifier = (sortDirection==1)?cmpForward:cmpReverse;
			
			// sort on sortKey
			if (cmpIdentifier)
			{
				translateSortKey(j,sortKey);
				translateOtherKeys(sortKey);
			}
			else
			// use uniqueKey to determine index of identical entries 
			if (cmpEqual)
			{
				var cmpForward = (theArray[uniqueKey][j+1] < theArray[uniqueKey][j]);
				var cmpReverse = (theArray[uniqueKey][j+1] > theArray[uniqueKey][j]);
				uniqueIndexCompare = (sortDirection==1)?cmpForward:cmpReverse;
				
				// sort on uniqueKey
				if (uniqueIndexCompare)
				{
					translateSortKey(j,uniqueKey);
					translateOtherKeys(uniqueKey);					
				}
			}
		}
	}		
	
	return theArray;
	
	function translateSortKey(index, sortKey)
	{
		var temp = theArray[sortKey][index];
		theArray[sortKey][index] = theArray[sortKey][index+1];
		theArray[sortKey][index+1] = temp;
	}
	
	function translateOtherKeys(sortKey)
	{
		for(otherCategory=0; otherCategory<numCategories; otherCategory++)
		{
			if(otherCategory==sortKey) continue; // don't process sortKey index
			translateSortKey(j, otherCategory);
		}		
	}
}

function refreshThumbnails()
{
	var imageName = g_menuSystem[g_currentBranchIndex].itemName;
	var numItems = imageName.length;

	for(i=0;i<numItems;i++)
	{
		var thumbImageNode = document.getElementById("thumbImage"+i);
		var thumbImageSrc = g_thumbImageDir + imageName[i];
		thumbImageNode.setAttribute("src",thumbImageSrc);		
	}

	redrawSelectedThumbnail();
	
	var selectionIndex = getSelected();
	changeSelected(selectionIndex);
}

function createFileDescriptor(itemMedia, assetName, assetType, assetSize, parentNode)
{
	var branchIndex = g_currentBranchIndex;
	var selectionIndex = getSelected();
	var command = "javascript:openWindow("+branchIndex+","+selectionIndex+")";
	var iconSrc = g_imageDir + itemMedia + "icon.gif";
	
	var fileNode = createNode("div","fileNode","calloutImageFrame colProportional",parentNode);
		var fileIconNode = createNode("a","fileIconLink","",fileNode,"href",command);
			var fileIcon = createNode("img","fileIcon","calloutImage",fileIconNode,"src",iconSrc,"alt",itemMedia + "asset");
		var textFrame = createNode("div","","calloutTextFrame",fileNode);
			var fileHeader = createNode("a","fileHeader","calloutHeader",textFrame,"href",command);
				var fileHeaderText = createNode("text",assetName,fileHeader);
			var fileCategory = createNode("p","fileCategory","calloutCategory",textFrame);
				var fileHeaderText = createNode("text",assetType,fileCategory);
			var fileBody = createNode("p","fileBody","calloutBody",textFrame);
				var fileBodyText = createNode("text",assetSize,fileBody);
}

function initNavIcon(containerNode, navIconName, navIconClass)
{
	var navIconImage = document.createElement("img");
	var navImageSrc = g_navImageDir + navIconName + "_out.gif";
	
	navIconNode = document.createElement("div");
	navIconNode.setAttribute("id",navIconName);
	navIconImage.setAttribute("src",navImageSrc); 
	navIconImage.className = navIconClass;
	
	navIconImage.onmouseover = navEventHandler;
	navIconImage.onmouseout = navEventHandler;
	navIconImage.onmouseup = navEventHandler;	
	navIconImage.onmousedown = navEventHandler;	
	
	containerNode.appendChild(navIconNode);
		navIconNode.appendChild(navIconImage);
}

function refreshThumbnails()
{
	var thumbItem, thumbImage, thumbImageSrc;
	var selectionIndex = getSelected();
	var imageArray = g_menuSystem[g_currentBranchIndex].itemName;
	var thumbGallery = document.getElementById("thumbGallery");

	for(i=0;i<imageArray.length;i++)
	{
		thumbItem = thumbGallery.childNodes[i];
		thumbImage = thumbItem.childNodes[0];
		thumbImageSrc = getThumbImageSrc(imageArray,i);
		thumbImage.setAttribute("src",thumbImageSrc);
		
		if(i!=selectionIndex)
		{
			thumbItem.style.backgroundColor = "";
			thumbItem.style.border = "1px solid #CCCCCC";
		}
		else
		{
			thumbItem.style.backgroundColor = "#FFFFFF";
			thumbItem.style.border = "1px solid #CB4F0C";
		}
	}
}

function redrawSelectedThumbnail()
{
	var selectionIndex = getSelected(); // get index of current selection
	
	// get target node corresponding to selection
	var targetNode = document.getElementById("thumbItem"+selectionIndex);
	
	// get thumbnail image for select state
	var menu = g_menuSystem[g_currentBranchIndex];
	var imageArray = menu.itemName;
	var thumbImage = getThumbImageSrc(imageArray,selectionIndex);
	targetNode.childNodes[0].setAttribute("src",thumbImage );
	
	// node styling
	targetNode.style.backgroundColor = "#FFFFFF";
	targetNode.style.border = "1px solid #CB4F0C";
}

function updateGallery(selectionIndex)
{
	var menu = g_menuSystem[g_currentBranchIndex];
	var imageWidth 	= menu.itemWidth[selectionIndex];
	var imageHeight = menu.itemHeight[selectionIndex];
	var imageSrc = g_galleryImageDir + menu.itemName[selectionIndex];
	/*var selectionIndex = getSelected();*/
	var command = "javascript:openWindow("+g_currentBranchIndex+","+selectionIndex+")";

	refreshThumbnails(); // update thumbnail gallery item selection state
	clearChildNodes(g_contentNode); // remove gallery image node prior to update
	
	// preload new image into browser cache
	var cacheImageObject = new Image(imageWidth,imageHeight);
	cacheImageObject.onLoad = cacheLoaded(imageSrc,selectionIndex); // call event handler when loaded
	cacheImageObject.src = imageSrc;	
	
	var captionNode =  document.getElementById("captionNode");
	clearChildNodes(captionNode); // remove gallery image node prior to update
	initCaptionNode();
	initLinkNode();
	


	//update item title gfx
	/*var galleryTitleImage = document.getElementById("galleryTitleImage");
	
	var titleImgSrc = g_galleryTitleDir + menu.mitemName[selectionIndex]
	galleryTitleImage.setAttribute("src",titleImgSrc);	
	galleryTitleImage.setAttribute("width",358); // hardcoded based on layout
	galleryTitleImage.setAttribute("height",24); // hardcoded based on layout	*/
	
	//update item metadata
	var itemTitle = document.getElementById("title");
	var itemCategory = document.getElementById("category");
	var itemClient = document.getElementById("client");
	textFormat(itemTitle, menu.itemTitle[selectionIndex]);
	textFormat(itemCategory, menu.itemCategory[selectionIndex]);
	textFormat(itemClient, menu.itemClient[selectionIndex]);

	//update item description
	var itemDate = document.getElementById("itemDate");
	var itemDescription = document.getElementById("itemDescription");
	textFormat(itemDate, menu.itemDate[selectionIndex]);
	textFormat(itemDescription, menu.itemDescription[selectionIndex]);
	
	// update sidebar link to asset
	var fileHeader = document.getElementById("fileHeader");
	var fileCategory = document.getElementById("fileCategory");
	var fileBody = document.getElementById("fileBody");
	//fileHeader.setAttribute("href",command);
	fileHeader.childNodes[0].data = menu.itemTitle[selectionIndex];
	fileCategory.childNodes[0].data = menu.itemCategory[selectionIndex];
	fileBody.childNodes[0].data = menu.itemSize[selectionIndex];
	


/*	// update file icon gfx
	//var itemMedia = menu.itemMedia[selectionIndex];
	//var iconSrc = g_imageDir + itemMedia + "icon.gif";
	//var fileIcon = document.getElementById("fileIcon");
	//fileIcon.setAttribute("src",iconSrc);
	
	// update file icon link
	//fileIconLink = document.getElementById("fileIconLink");
	//fileIconLink.setAttribute("href",command);*/
	

	
	

}

function textFormat(documentNode,textInput)
{
	var newLine = new Array();
	var i;
	
	var subString = textInput.split("%");
	var linebreak = document.createElement("br");
	
	clearChildNodes(documentNode);

	for(i=0;i<subString.length;i++)
	{
		newLine[i] = document.createTextNode(subString[i]);
	}	
	
	for(i=0;i<newLine.length;i++)
	{
		documentNode.appendChild(newLine[i]);

		// append a linebreak except on last iteration of loop
		if((newLine.length>1) && (i<newLine.length-1))
		{
			documentNode.appendChild(document.createElement("br"));
		}
	}
}

function cacheLoaded(imageSrc,selectionIndex)
{
	var menu = g_menuSystem[g_currentBranchIndex];
	var imageWidth 	= menu.itemWidth[selectionIndex];
	var imageHeight = menu.itemHeight[selectionIndex];
	
	//reposition gallery content node
	var xOffset = (g_galleryWidth-imageWidth)/2; // x offset to center selected image width
	var yOffset = 8; // consistent 8 px margin from top of container
	g_contentNode.style.left = xOffset+"px";
	g_contentNode.style.top = yOffset+"px";
	
	this.onload = null;  // reset onload handler for image object that called this function

	var showGalleryImage = function()
	{
		// rebuild gallery image
		var galleryImageNode = document.createElement("img");
		galleryImageNode.setAttribute("src",imageSrc);
		galleryImageNode.setAttribute("width",imageWidth);
		galleryImageNode.setAttribute("height",imageHeight);
		galleryImageNode.setAttribute("id","galleryImageNode");
		g_contentNode.appendChild(galleryImageNode);
	}
	
	window.setTimeout(showGalleryImage, 30); // short delay before showing updated img
}

function assetLinkBehavior()
{
	var presentationMode = getPresentationMode(g_currentBranchIndex);	
	switch(presentationMode)
	{
		case "images":
			openWindow();
			break;
			
		case "design":
			openWindow();
			break;
			
		case "motion":
			openWindow();
			break;
	}
}

function openWindow(branchIndex,selectionIndex)
{
	var menu = g_menuSystem[branchIndex];
	
	// get metadata for currently selected gallery asset
	var itemZoomWidth = menu.itemZoomWidth[selectionIndex];
	var itemZoomHeight = menu.itemZoomHeight[selectionIndex];
	var itemMedia = menu.itemMedia[selectionIndex];
	
	// image assets need 16px added to height to show branding
	if(itemMedia == "image") itemZoomHeight+=25;
	
	// movie assets need 16px added to height so quicktime control panel has adequate room
	if(itemMedia == "movie") itemZoomHeight+=16;
	
	// flash assets need 16px added to height to fit in browser window has adequate room
	if(itemMedia == "flash") itemZoomHeight+=60;
	
	var newURL;
	var parameterList;
	
	var delimitedFileName = menu.itemName[selectionIndex].split(".");// split the string at the filename extension
	
	if( itemMedia == "online" )
	{
		newURL = 'http://www.' + delimitedFileName[0]+".com";
		parameterList = '';
	}
	else
	{
		newURL = g_popupDir + delimitedFileName[0]+".html";
		parameterList = "resizable=yes,scrollbars=no,width="+itemZoomWidth+",height="+itemZoomHeight+",top=40,left=40";
	}
	
	g_popWindow = window.open(newURL,"popup",parameterList);
}