/*Name:Add to Order*/
/*Order:3*/

/* 	
	----------------------------------------------------------------------
	ORDER ADD
	A script to handle the addition of items to the order using
	xmlhttp.
	---------------------------------------------------------------------- 
*/
/* Config */
var displayID = 'orderDisplay';	// The element used to display summary
var addID = 'addWine';				// Widget for adding to the order
var containerID = 'container';	// Element we insert the status notice into
/* Global Vars*/
var elOrderDisplay;
var elOrderItems;
var elOrderSubTotal;
var elAddInput;
var elAddButton;
var elAddForm;
var elStatus = null;
var elContainer;
var dimTimeout;
var statusTimeout;
var wobbly;

window.onload.actions['orderAdd'] = initOrderAdd;

/* 	
	----------------------------------------------------------------------
	INIIALISE
	Check and see if the browser supports the XMLHTTP object.
	If it does, collect all the elements we need to mainipulate and 
	assign the event handlers.
	---------------------------------------------------------------------- 
*/
function initOrderAdd() {
	// firstly, see if this is the detail page
	if (document.getElementById(addID)) {
		// See if wobbly is supported
		if (window.XMLHttpRequest || window.ActiveXObject) {
			// Set the correct version of the object
			if (window.XMLHttpRequest) {
				wobbly = new XMLHttpRequest();
			}
			else if (window.ActiveXObject) {
				// we need to put in some sort of test for different version of IE
				wobbly = new ActiveXObject('Microsoft.XMLHTTP');
			}
			// Find the various elements and assign events
			// ORDER DISPLAY
			elOrderDisplay = document.getElementById(displayID);
			// MAYBE IE IS GETTING SOME JUNK ENTRIES INTO AN ARRAY. ARGHHHH!
			var orderP =  elOrderDisplay.getElementsByTagName('p');
			for (var i = 0; i < orderP.length; ++i) {
				if (orderP[i].className == 'items') {
					elOrderItems = orderP[i];
				}
				if (orderP[i].className == 'subTotal') {
					for (var j = 0; j < orderP[i].childNodes.length; ++j) {
						// DEBUGGIN IE
						// Some error about requiring an object. is very strange.
						var child = orderP[i].childNodes[j];
						if (child.nodeName == 'STRONG') {
							elOrderSubTotal = child;
						}
					}
				}
			}
			// ADD WIDGET
			elAddForm = document.getElementById(addID);
			for (var i = 0; i < elAddForm.childNodes.length; ++i) {
				if (elAddForm.childNodes[i].nodeName == 'BUTTON') {
					elAddButton = elAddForm.childNodes[i];
					elAddButton.onclick = orderAddItem;
				}
				else if (elAddForm.childNodes[i].nodeName == 'INPUT') {
					elAddInput = elAddForm.childNodes[i];
					// Check to see if DOM event handlers are supported
					if (elAddInput.addEventListener) {
						elAddInput.addEventListener('onkeyup', keyFilter, false);
					}
					else {
						elAddInput.onkeyup = keyFilter;
					}
				}
			}
			// CONTAINER TO INSERT THE STATUS
			elContainer = document.getElementById(containerID);
		}
		else {
			return false;
		}
	}
}

/* 	
	----------------------------------------------------------------------
	KEY FILTER
	Check and see if the user has hit the enter key. If they have,
	we can run our little add item function
	---------------------------------------------------------------------- 
*/
function keyFilter() {
	// test for IE 
	if (window.event) {
		if (window.event.keyCode == 13) {
			orderAddItem();
			return false;
		}
	}
	else {
		if (e.keyCode == 13) {
			orderAddItem();
			return false;
		}
	}
}

/* 	
	----------------------------------------------------------------------
	ADD ITEM
	This function communicates to the remote server and sents the 
	response to another function for processing. It also includes some
	simple validation.
	---------------------------------------------------------------------- 
*/
function orderAddItem() {
	if (isValid(elAddInput.value) == true) {
		// Build the URL
		var url;
		var methodType;
		var query = null;
		// Loop though the attributes so we can get the url and method
		// We are using this here instead of just element.getAttribute() 
		// because IE returns an object instead of the value of the
		// attribute. Is very annoying.
		for (var attr = 0; attr < elAddForm.attributes.length; ++attr) {
			switch(elAddForm.attributes[attr].name) {
				case 'method':
					methodType = elAddForm.attributes[attr].value;
				break;
				case 'action':
					url = elAddForm.attributes[attr].value;
				break;
			}
		}
		// Handle POSTed or GETted forms
		if (methodType == 'post') {
			query = elAddInput.name + '=' + elAddInput.value + '&display=wobbly&action=add';
		} else {
			url += '?' + elAddInput.name + '=' + elAddInput.value + '&display=wobbly&action=add';
		}
		
		// Attach anon-function to the event handler to process the response
		wobbly.onreadystatechange = function() {
			if (wobbly.readyState == 4) {
				// error checking by looking for a header
				var headers = wobbly.getAllResponseHeaders();
				if (checkForHeader(headers, 'success') == true) {
					orderResponseProcess(wobbly.responseText);
					orderStatusDisplay(true, 'Your order has been updated', 'success', 2000);
				}
				//else if (checkForHeader(headers, 'error') == true) {
				else {
					var errorMessage = eval(wobbly.responseText);
					orderStatusDisplay(true, errorMessage.message, 'updateError', 5000);
				}
				/*else {
					orderStatusDisplay(true, 'There was an error updating your order, please try again.', 'updateError', 5000);
					elAddButton.onclick = null;
				}*/
			}
		}
		
		// Prepare the object to send
		wobbly.open(elAddForm.method, url, true);
		// Check to see if this is a post
		if (elAddForm.method == 'post') {
			wobbly.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
		}
		// Send the query
		wobbly.send(query);
		// display the status
		orderStatusDisplay(true, 'Adding to your order', 'loading');
	}
	else {
		errorDisplay('Please use whole numbers and no letters.', elAddInput);
	}
	return false;
}

function isValid(value) {
	if (isNaN(value) == true) {
		return false;
	}
	else if (value == '' || value == ' ') {
		return false;
	}
	else if (value == 0) {
		return false;
	}
	else {
		var string = value.toString();
		for (var i = 0; i < string.length; ++i) {
			if (string[i] == '.') {
				return false;
			}
		}
		return true;
	}
}

/* 	
	----------------------------------------------------------------------
	PROCESS
	This processes the JSON returned by the server.
	---------------------------------------------------------------------- 
*/
function orderResponseProcess(response) {
	// Need to add a bit of error checking here.
	var update = eval(response);
	var itemUpdate;
	var totalUpdate;
	for (var i in update) {
		if (i == 'items') {
			itemUpdate = update[i];
		}
		else if (i == 'subtotal') {
			totalUpdate = update[i];
		}
	}
	orderDisplayUpdate(itemUpdate, totalUpdate)
}

/* 	
	----------------------------------------------------------------------
	DISPLAY
	Updates the various chunks of html with the new information
	---------------------------------------------------------------------- 
*/
function orderDisplayUpdate(newItems, newTotal) {
	elOrderDisplay.className = '';
	elOrderItems.innerHTML = newItems;
	elOrderSubTotal.innerHTML = newTotal;
	// Highlight the box
	elOrderDisplay.className = 'updated';
	dimTimeout = window.setTimeout('orderDim()', 5000);
}


function orderDim() {
	elOrderDisplay.className = '';
	window.clearTimeout(dimTimeout);
}

/* 	
	----------------------------------------------------------------------
	STATUS DISPLAY
	This function is used to show the user a status message while the 
	browser communicates with the server.
	
	IE is having some problems with the positioning of an absolute
	element inside of a relative. I think this is related to the 
	element.appendChild() method. I'm gonna do some test cases
	---------------------------------------------------------------------- 
*/
var addOrderCache = null;
function orderStatusDisplay(enabled, message, newClassName, delay) {
	var p;
	// We want to switch it on, and it's not in use
	if (enabled == true && elStatus == null) {
		elStatus = document.createElement('div');
		elStatus.id = 'status';
		elStatus.className = newClassName;
		p = document.createElement('p');
		p.appendChild(document.createTextNode(message));
		elStatus.appendChild(p);
		elAddForm.style.position = 'relative';
		// replace the form, get the parent
		addOrderCache = elAddForm;
		var parent = elAddForm.parentNode;
		parent.replaceChild(elStatus, elAddForm)
		
	}
	// Display a message, but the status is already open
	else if (enabled == true && elStatus != null) {
		p = document.createElement('p');
		p.appendChild(document.createTextNode(message));
		elStatus.innerHTML = '';
		elStatus.appendChild(p);
		elStatus.className = newClassName;
		statusTimeout = window.setTimeout('orderStatusDim()', delay);
	}
	// Hide the message and set it to null
	else if (enabled == false) {
		var parent = elStatus.parentNode;
		parent.replaceChild(addOrderCache, elStatus);
		elAddForm = addOrderCache;
		addOrderCache = null;
		elStatus = null;
	}
}

function orderStatusDim() {
	orderStatusDisplay(false);
	window.clearTimeout(statusTimeout);
}

// Simple function to test for the existance of a header
function checkForHeader(headers, headerName) {
	headers = headers.split('\n');
	var success = false;
	for (var i = 0; i < headers.length; ++i) {
		var pair = headers[i].split(':');
		if (pair[0] == 'success') {
			success = true;
		}
	}
	return success;
}

/* 	
	----------------------------------------------------------------------
	RESPONSE DEBUGGER
	Bung the wobbly response text in a box so we can see it
	---------------------------------------------------------------------- 
*/
function debugResponse(response) {
	var div = document.createElement('div');
	// insert the response
	div.innerHTML = response;
	// make a button
	elContainer.appendChild(div);
}
