var fadeInSpeed = .3;
var fadeOutSpeed = .15;

/* Functions for getting the next sibling, the first child, or the node value of an element
	Helpful because IE and Firefox do it differently
*/
function getNextSibling( whichElem ) {
	return document.all ? whichElem.nextSibling : whichElem.nextSibling.nextSibling;
}

function getFirstChild( whichElem ) {
	return document.all ? whichElem.firstChild : whichElem.firstChild.nextSibling;
}

/* Get and set node value for elements that can change text in their firstChild */
function getNodeValue( whichElem ) {
	return whichElem.firstChild.nodeValue;
}

function setNodeValue( whichElem, whichVal ) {
	whichElem.firstChild.nodeValue = whichVal;
}

/* Called when page is loaded.  Starts the whole dropdown process by opening
	a new XML connection and loading project1data into it
*/
function initDropdown( whichElem ) {
	var dropdownConn = new xmlConn();
	var whichValue = 'init';
	
	dropdownConn.getXML( 'project1data.xml', function() {
		loadDropdown( dropdownConn.getConn(), whichValue, whichElem );
	} );
}

/* Creates a dropdown by first removing all elements (in this case, DIVs)
	from the product holder, then all DIVs with dropdowns in them, until we
	arrive at the spot we want to begin creating new ones
*/
function createDropdown( whichElem, whichDropdown ) {
	var productHolder = getNextSibling( whichElem );
	
	if( ( document.all && productHolder.hasChildNodes() ) ||
				productHolder.childNodes.length > 1 ) {
		/* Remove elements, when it's fully faded out, call createDropdown again */
		removeProduct( productHolder.lastChild, function() {
			removeFromElement( productHolder, productHolder.lastChild );
			createDropdown( whichElem, whichDropdown );
		} );
	}
	else if( whichElem.lastChild != whichDropdown ) {
		/* Remove elements, when it's fully faded out, call createDropdown again */
		removeDropdown( whichElem.lastChild, function() {
			removeFromElement( whichElem, whichElem.lastChild );
			createDropdown( whichElem, whichDropdown );
		} );
	}
	else {
		var whichValue = getCurrentValue( whichDropdown ); // current selected value
		
		var dropdownConn = new xmlConn(); // load XML data
		dropdownConn.getXML( 'project1data.xml', function() {
			loadDropdown( dropdownConn.getConn(), whichValue, whichElem );
		} );
	}				
}

/* Fills in our select menus with data from the XML file */
function loadDropdown( conn, checkValue, whichElem ) {
	if( conn.readyState == 4 ) {
		if( conn.status == 200 ) {
			var combos = conn.responseXML.getElementsByTagName( 'combo' ); // XML file
			
			var foundCombo = false;
			
			for( var i = 0; i < combos.length; i++ ) {
				if( ( combos[ i ].getAttribute( 'parent' ) == checkValue ) ||
						( !combos[ i ].getAttribute( 'parent' ) && checkValue == 'init' ) ) {
					var newText = combos[ i ].getAttribute( 'question' );
					var newHeader = combos[ i ].getAttribute( 'title' );
					var newClass = "box" + ( document.all ? "_ie" : "" );
					
					// Create new dropdown DIV and select menu
					var newDropdown = addDropdown( whichElem, combos[ i ].getAttribute( 'name' ), newClass, newText, newHeader );
					
					// Add new options with data from XML
					addOption( newDropdown, '--Select One--', '-1' );
					
					for( var j = 0; j < combos[ i ].childNodes.length; j++ ) {
						var currNode = combos[ i ].childNodes[ j ];
						
						if( currNode.hasChildNodes() ) {
							addOption( newDropdown, currNode.childNodes[ 0 ].nodeValue, currNode.getAttribute( 'value' ) );
						}
					}
					
					// Fade the dropdown in and let it know that it's NOT the last element
					showDropdown( whichElem, newDropdown );
					foundCombo = true;
					break;
				}
			}
		}
		
		// If no dropdown was created, then it must have been the last element, so create a new product
		if( !foundCombo && checkValue != '-1' && checkValue != 'init' ) {
			var productConn = new xmlConn(); // load product info from XML
			productConn.getXML( 'product_data.xml', function() {
				loadProduct( productConn.getConn(), checkValue, ( document.all ? whichElem.nextSibling : whichElem.nextSibling.nextSibling ) );
			} );
		}
	}
}

/* Loads product information (name, price, image, etc.)
	from an XML document, then appends it below all current dropdowns.
*/
function loadProduct( conn, productName, whichElem ) {
	if( conn.readyState == 4 ) {
		if( conn.status == 200 ) {
			var products = conn.responseXML.getElementsByTagName( 'product' );
			
			for( var i = 0; i < products.length; i++ ) {
				if( products[ i ].getAttribute( 'name' ) == productName ) {
					var currNode = products[ i ];
					
					var prodId = currNode.getAttribute( 'id' );
					var prodTitle = currNode.getAttribute( 'title' );
					var prodPrice = currNode.getAttribute( 'price' );
					var prodImage = currNode.getAttribute( 'image' );
					var prodText = getNodeValue( getFirstChild( currNode ) );
					
					// Organize divs to get product image and text to look right
					var myDiv = createDiv();
					var myLeftDiv = createDiv( 'left' );
					var myRightDiv = createDiv( 'right' );
					var myBottomDiv = createDiv( 'bottom' );
					
					var myTitle = createHeader( 'h2', prodTitle );
					var myPrice = createHeader( 'h3', '$' + prodPrice );
					
					// Add 'Add to Cart' image
					var myCart = createImage( 'images/add_to_cart.gif' + ( document.all ? '?' + Math.random() : '' ) );
					
					// Create a link on the cart image
					myCart.onload = function() {
						setFakeLink( this );
					
						this.onclick = function() {
							updateCart( prodId, prodPrice );							
						}
					}
					
					var myImage = createImage( prodImage );
					var myText = createParagraph( prodText );
					
					myDiv.setAttribute( 'id', productName );
					setElementClass( myDiv, ( document.all ? 'product_ie' : 'product' ) );
					
					myDiv.appendChild( myTitle );
					
					myRightDiv.appendChild( myPrice );
					myRightDiv.appendChild( myCart );
					myLeftDiv.appendChild( myImage );
					myBottomDiv.appendChild( myText );
					
					myDiv.appendChild( myLeftDiv );
					myDiv.appendChild( myRightDiv );
					myDiv.appendChild( myBottomDiv );
					
					// Fade the product in
					setOpacity( myDiv, 0 );
					whichElem.appendChild( myDiv );
					fadeElement( myDiv, 0, 100, fadeInSpeed );
				}
			}
		}
	}
}

/* Adds a new dropdown element by creating a div and positioning
	any text and info from XML and any new selects inside that div
*/
function addDropdown( whichElem, whichId, whichClass, whichText, whichHeaderText ) {					
	var myDiv = createDiv( whichId, whichClass );
	
	if( whichHeaderText ) {
		var myH = createHeader( 'h2', whichHeaderText );
		myDiv.appendChild( myH );
	}
	
	if( whichText ) {
		var myP = createParagraph( whichText );
		myDiv.appendChild( myP );
	}
		
	var mySelect = document.createElement( 'select' );
	myDiv.appendChild( mySelect );
	
	mySelect.setAttribute( "name", whichId );
	
	/*
	if( document.all ) { // IE
		mySelect.setAttribute( 'onchange', function() {
			changeFunc( this );
		} );
	}
	else { // Gecko
		mySelect.setAttribute( 'onchange', 'changeFunc( this )' );
	}
	*/
	
	mySelect.onchange = function() {
		createDropdown( whichElem, myDiv );		
	}
	
	return myDiv;
}

/* Fades in a dropdown */
function showDropdown( whichElem, whichDropdown ) {
	setOpacity( whichDropdown, 0 );
	
	// Hide select boxes since they appear over everything when fading
	if( document.all ) {
		whichDropdown.lastChild.style.visibility = 'hidden';
	}
	
	whichElem.appendChild( whichDropdown );
	fadeElement( whichDropdown, 0, 100, fadeInSpeed, function() {
		if( document.all ) {
			whichDropdown.lastChild.style.visibility = 'visible';
		}	
	} );
}

/* Fades out a dropdown */
function removeDropdown( whichDropdown, removeFunc ) {										
	// Show all the selects again
	if( document.all ) {
		whichDropdown.lastChild.style.visibility = 'hidden';
	}
	
	fadeElement( whichDropdown, 100, 0, fadeOutSpeed, removeFunc );
}

/* Fades out a product */
function removeProduct( whichElem, removeFunc ) {
	fadeElement( whichElem, 100, 0, fadeOutSpeed, removeFunc );
}

/* Add an option to a select menu within a div */
function addOption( whichDiv, optionValue, optionText ) {
	addNewOption( whichDiv.lastChild, optionValue, optionText );
}

function getCurrentValue( mySelectDiv ) {
	return mySelectDiv.lastChild.value;
}				