Array.prototype.inArray = function (value) {
	var i;
	for (i=0; i < this.length; i++) {
		if (this[i] === value) {
			return true;
		}
	}
	return false;
};

/* This is the name of the form on the page and will be used throught the script with the
	checheck_form_completed function. This happens in the script so that ajax functions will finish before
	the form is set to completed. */

formID = 'form_edit_cart';
fakeButtonID = 'greyCheckoutButton';
realButtonID = 'cart_checkout_button';

//AJAX oriented Functions.
function GetXmlHttpObject() {
	var xmlHttp=null;
	try {
		// Firefox, Opera 8.0+, Safari
		xmlHttp=new XMLHttpRequest();
	}
	catch (e) {
		//Internet Explorer, those bastards!
		try {
			xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");
		}
		catch (e) {
			xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
		}
	}
return xmlHttp;
}


/*
	Because of a lack of foresight, each different type of AJAX action (mul calculation, removing an item,
	and changing the format), all have seperate functions and onstatechange handling functions.
	This isn't two terrible because they do different things to the page, but all of AJAX requests should
	probably be rolled into on function.
*/
//globalRequestQuestQue is used to stager requests so that they don't all happen at once. When ever an
//ajax function is about to execute, it is told to delay x*globalRequestQuestQue, which makes it so there
//is a delay between all of the requests. When a request stats, 1 is added to globalRequestQuestQue, and
// when a request is completed 1 is subtracted from globalRequestQuestQue
globalRequestQuestQue = 0;
xmlHttp = new Array();
globalProdIDs = new Array();
globalCurrencyIDs = new Array();

//AJAX for MUL CALCULATION____
//The function timedUpdateHandler() wraps this functions so that a seperate function handles the timing
//of a user pushing keys

/* timedUpdateHandler() handles the timing aspects of updating the cart. In the first version, ajaxMulCalc
	was an onblur event for each form field, but now it's a going to be an onkeyup event, and it will wait
	untill 	the user has noy pressed keys for a second or so. */

keyPressTimers = new Array();
hasAddedtoRequestQue = new Array();
function timedUpdateHandler( inputObj, manuCode, price, purchPrice, payableWeights, currencyID, maxLicense, e) {

	if(window.event) { // IE
		keynum = e.keyCode;
	}
	else if(e.which) { // Netscape/Firefox/Opera
		keynum = e.which;
	}

	if ( (47 < keynum && keynum < 58 ) || (95 < keynum && keynum < 106 ) || keynum == 8 || keynum == 46) {
		var prodID = inputObj.id.replace('qty_','');
		clearTimeout(keyPressTimers[prodID]) ;
		if (!hasAddedtoRequestQue[prodID]) {
			globalRequestQuestQue = globalRequestQuestQue + 1;
			hasAddedtoRequestQue[prodID] = true ;
		}
		extraWait = globalRequestQuestQue * 500 + (globalRequestQuestQue^2 * 70)/2;
		keyPressTimers[prodID] = setTimeout('ajaxMulCalc("' + prodID + '","'
			+ manuCode + '",'
			+ price + ','
			+ purchPrice + ',"'
			+ payableWeights + '",'
			+ currencyID + ','
			+ maxLicense + ')',200 + extraWait) ;


	} else if( keynum == 13) {
		showMissingData('form_edit_cart');
	}
}

var gMaxLicense=1000;
function ajaxMulCalc( prodID, manuCode, price, purchPrice, payableWeights, currencyID, maxLicense) {

		if (maxLicense > 0) gMaxLicense = maxLicense;

		//This condition will prevent multiple updates running for the same product
		saveOldValue(prodID,currencyID);
		if (!globalProdIDs.inArray(prodID)){
			globalProdIDs.push(prodID);
			xmlHttp[prodID] = GetXmlHttpObject();
			if (xmlHttp[prodID]==null) {
				alert ("Browser does not support HTTP Request")
			return
			}

			//The old value of the product is saved so that the sub-total can be updated appropriately.
			var qtyObjGlobal = document.getElementById('qty_' + prodID);
			url = '/api/cart_recalculate/mul_cart_calculator.php?manuCode=' + manuCode + '&price=' +
				price + '&purchPrice=' + purchPrice + '&currencyID='
				+ currencyID + '&qty=' + make_value_integer(qtyObjGlobal.value)
				+ '&pid=' + prodID
				+ '&payableWeights=' + payableWeights;

			globalCurrencyIDs[prodID] = currencyID ;

			xmlHttp[prodID].onreadystatechange = stateChanged ;
			xmlHttp[prodID].open("GET",url,true) ;
			xmlHttp[prodID].send(null) ;
		}
}

//State change handler for MUL CALCULATION
function stateChanged() {
	for (var i=0;i<globalProdIDs.length;i++) {
		var prodID = globalProdIDs[i] ;
		var qtyObjGlobal = document.getElementById('qty_' + prodID);
		var priceObjGlobal = document.getElementById('price_' + prodID);

		if (xmlHttp[prodID].readyState== 4 || xmlHttp[prodID].readyState=="complete") {
			//Here's where all of the ajax action happens. When the response text is received, a bunch
			//of different information on the page gets updated

			if (globalCurrencyIDs[prodID] == '1') {
				currency = '&#8364;' ;
			} else if (globalCurrencyIDs[prodID] == '2') {
				currency = '$';
			} else {
				currency = 'AU$';
			}

			var qtyObjGlobal = document.getElementById('qty_' + prodID);
			var priceObjGlobal = document.getElementById('price_' + prodID);
			//	xmlHttp.responseText == priceOfMUL_-_MULceiling_-_basePrice
			var resultText =  xmlHttp[prodID].responseText ;
			resultText = resultText.split('_-_');
			var newPriceInterger= new Number(resultText[0]) ;
			var newPrice = new Number(resultText[0]);

			var pricePerUser = new Number( resultText[0]/resultText[1]);
			pricePerUser = pricePerUser.toFixed(2) ;
			pricePerUser = pricePerUser.toString() ;

			newPrice = newPrice.toFixed(2) ;
			newPrice = newPrice.toString() ;

			if (resultText[1] !=0) {
				priceObjGlobal.innerHTML = currency + add_commas_to_number(newPrice) ;
			} else {
				qtyObjGlobal.value = '';
				priceObjGlobal.innerHTML = '';
			}

			mulMessage ='';
			var mulMessageSpan = document.getElementById('mulMess_' + prodID) ;
			if (prodID.charAt(0) != 'T' && prodID.charAt(0) != 'K') {
				var mulMessage = '<span style="color:green; font-size:1em">&nbsp;&nbsp;&#9654;</span>&nbsp;up to<b> '
					+ resultText[1] + '</b> user license | ' + currency + pricePerUser + ' per user' ;


				if(qtyObjGlobal.value  >= gMaxLicense) {
					qtyObjGlobal.value = resultText[1] ;
					mulMessage = mulMessage + '<div class="bigMUL">Interested in licensing for more than ' + gMaxLicense
						+ ' users? <a href="/about/contact_us.php">Contact us directly</a> </div>'
				}
			}

			if(resultText[1] == '0') {
				mulMessage =  '<span style="color:red; font-size:1em">&nbsp;&nbsp;&#9664;</span>&nbsp;Enter the # of users for this license';
			}

			mulMessageSpan.innerHTML = mulMessage ;

			if (resultText[1] == '0') {
				redFade(mulMessageSpan);
			} else {
				greenFade(mulMessageSpan);
			}
			updateSubTotal('subTotalValue', newPriceInterger, globalCurrencyIDs[prodID], 0, prodID);

			//This will remove the product id from the global array of product ids. That way the
			//same xmlHTTP request won't be sent over and over.
			globalProdIDs.splice(i,1);

			//This function will then check to see if the entire form has been completed
			check_form_completed(formID,fakeButtonID, realButtonID);
			globalRequestQuestQue = globalRequestQuestQue - 1;
			hasAddedtoRequestQue[prodID] = false;

		} else {
			priceObjGlobal.innerHTML = 'calculating...' ;
		}
	}

}


//AJAX for CHANGING FORMAT__________
function saveCurrentSelection(selectObj) {
	lastSelectedFormat = selectObj.id.replace('format_','') ;
}

//	ajaxChangeFormat is actually a wrapper function for handling the timing and delays of sending ajax requests
function ajaxChangeFormat( formatSelectObj) {
	var formatXmlHttp = GetXmlHttpObject()
	var newFormatID = formatSelectObj.options[formatSelectObj.selectedIndex].value ;

	url = '/api/cart_recalculate/mul_cart_calculator.php?action=swap_format' + '&newFormatID=' +
		newFormatID + '&oldFormatID=' + lastSelectedFormat;

	//All of the ids of the format need to be changed so that any further quantity updates will
	//go to the newly selected format.

	globalRequestQuestQue = globalRequestQuestQue +1
	setTimeout('formatSwapAjax("' + newFormatID + '","' + url + '","' + lastSelectedFormat +'")', globalRequestQuestQue*500 );

}

globalFormatProdIDs = new Array();
globalOldFormatIDs = new Array();
formatXmlHttp = new Array() ;
//Where the AJAX request is sent for CHANGING FORMAT
function formatSwapAjax(prodID,url, oldFormatID) {
	globalFormatProdIDs.push(prodID);
	globalOldFormatIDs[prodID] = oldFormatID;
	formatXmlHttp[prodID] = GetXmlHttpObject();
	formatXmlHttp[prodID].onreadystatechange = formatSwapStateChanged ;
	formatXmlHttp[prodID].open("GET",url,true) ;
	formatXmlHttp[prodID].send(null) ;
}
//The state change hadler for CHANGING FORMAT
function formatSwapStateChanged() {
	for (var i=0;i<globalFormatProdIDs.length;i++) {
		var prodID = globalFormatProdIDs[i] ;
		var newFormatID = prodID;
		var oldFormatID = globalOldFormatIDs[newFormatID] ;
		var formatSelectObj = document.getElementById('format_' + oldFormatID);

		if (formatXmlHttp[prodID].readyState== 4 || formatXmlHttp[prodID].readyState=="complete") {

			globalRequestQuestQue = globalRequestQuestQue - 1;
			globalFormatProdIDs.splice(i,1);

			document.getElementById('x_button_span_' + oldFormatID).id = 'x_button_span_' + newFormatID;
			document.getElementById('qty_' + oldFormatID).name = 'qty_' + newFormatID;
			document.getElementById('qty_' + oldFormatID).id = 'qty_' + newFormatID;
			formatSelectObj.id = 'format_'+ newFormatID;

			document.getElementById('hidden_field_' + oldFormatID).value = newFormatID;
			document.getElementById('hidden_field_' + oldFormatID).id = 'hidden_field_' + newFormatID;
			document.getElementById('mulMess_' + oldFormatID).id = 'mulMess_' + newFormatID;
			document.getElementById('price_' + oldFormatID).id = 'price_' + newFormatID;

			//Firefox treats a \n in some of the table code as a node, and IE doesn't, so it's nessecery
			//to pick out whether we want two or one sibling nodes ahead.
			if(formatSelectObj.parentNode.nextSibling.innerHTML){
				var formatLinkNode = formatSelectObj.parentNode.nextSibling;
			} else {
				formatLinkNode = formatSelectObj.parentNode.nextSibling.nextSibling;
			}
			formatLinkNode.innerHTML = '<a href="/fonts/shopping_cart.php?action=change&products_id=' + newFormatID + '">change format</a><br /><a href="/fonts/shopping_cart.php?action=add_formats&products_id=' + newFormatID + '" id="add_format_' + newFormatID + '">add another format</a>' ;
			formatSelectObj.parentNode.innerHTML = formatSelectObj.options[formatSelectObj.selectedIndex].text + '<input type="hidden" name=format[] value="' + formatSelectObj.options[formatSelectObj.selectedIndex].value + '">'
			check_form_completed(formID,fakeButtonID, realButtonID);
		} else {
			if(formatSelectObj.parentNode.nextSibling.innerHTML){
				var formatLinkNode = formatSelectObj.parentNode.nextSibling;
			} else {
				formatLinkNode = formatSelectObj.parentNode.nextSibling.nextSibling;
			}
			formatLinkNode.innerHTML = '<strong>saving...</strong>';
		}
	}
}


/*
	This function will make a row hidden, and send an ajax request to have it removed from the customers
	cart (which is why the qty is set to zero).
*/
globalRemoveProdIDs = new Array;
function removeItem ( currencyID, spanObj ) {
		var prodID = spanObj.id.replace('x_button_span_','');
		/*
			Now removing an item from the cart is done by sending a request to mul_cart_calculator.php,
			and then removing the item from the form, so when checking out, no weird data gets sent.
		*/

		url = '/api/cart_recalculate/mul_cart_calculator.php?action=removeFromCart' + '&qty=0&pid=' + prodID;
		setTimeout('removeProductAjax("' + prodID + '","' + url + '")', globalRequestQuestQue*500 )
		globalRequestQuestQue = globalRequestQuestQue + 1;

		var price = document.getElementById('price_' + prodID).innerHTML.replace(',','');
		thisRow = spanObj.parentNode.parentNode.parentNode.rowIndex
		spanObj.parentNode.parentNode.parentNode.parentNode.deleteRow(thisRow);

		if (document.getElementById('num_in_cart_top').innerHTML == 2 ){
			document.getElementById("num_in_cart_top_wrapper").innerHTML = '(<span id="num_in_cart_top">1</span>)';
		} else if (document.getElementById('num_in_cart_top').innerHTML == 1 ){
			document.getElementById("num_in_cart_top_wrapper").innerHTML = '<span id="num_in_cart_top"></span>';
		} else {
			document.getElementById('num_in_cart_top').innerHTML -=1;
		}

		if (currencyID == '1' ) {
			price = price.substr(1);
		} else if (currencyID == '2') {
			price = price.replace('$','') ;
		} else {
			price = price.replace('AU$','') ;
		}

		if (isNaN(price) ) {
			price = 0;
		}

		price = price * -1 ;
		updateSubTotal('subTotalValue', price, currencyID, 1, prodID);
}

removeXmlHttp = new Array() ;
function removeProductAjax(prodID,url) {
	globalRemoveProdIDs.push(prodID);
	removeXmlHttp[prodID] = GetXmlHttpObject();
	removeXmlHttp[prodID].onreadystatechange = removStateChanged ;
	removeXmlHttp[prodID].open("GET",url,true) ;
	removeXmlHttp[prodID].send(null) ;
}

function removStateChanged() {
	for (var i=0;i<globalRemoveProdIDs.length;i++) {
		var prodID = globalRemoveProdIDs[i] ;
		if (removeXmlHttp[prodID].readyState== 4 || removeXmlHttp[prodID].readyState=="complete") {
			globalRequestQuestQue = globalRequestQuestQue - 1;
			globalRemoveProdIDs.splice(i,1);
			check_form_completed(formID,fakeButtonID, realButtonID);
		}
	}
}

function add_commas_to_number(string) {
	var arrayofString = string.split('.') ;
	var tensPlaces = arrayofString[0];
	var i = tensPlaces.length -1 ;
	var commaCount = 0;
	var commaString ='';
	while( i>=0) {
		if ( (commaCount%3 ) == 0 && commaCount != 0) {
			commaString = ',' + commaString ;
		}
		commaString = tensPlaces.charAt(i) + commaString ;
		i = i-1;
		commaCount = commaCount + 1 ;
	}

	return (commaString + '.' + arrayofString[1]);
}

/*
	saveOldValue is trigged as an onfocus event in the input fields. This will record the value in
	the field before the user tried to enter something else, so that the it can be correctly subtracted
	from the subtotal.
*/

oldValueGlobalArray = new Array();
function saveOldValue( prodID, currencyID) {
	var price = document.getElementById('price_' + prodID).innerHTML.replace(',','') ;


	if (currencyID == '1' ) {
	/*
		For some reason none of the possible codes for a euro are being recognized, so I'm just going to
		chop off the first character.
	*/
		price = price.substr(1)
	} else if (currencyID == '2') {
		price = price.replace('$','');
	} else {
		price = price.replace('AU$','');
	}

	if (isNaN(price)) {
		price = 0;
	}

	oldValueGlobalArray[prodID] = price;
}

function removeNonDigits(inputObj,e) {
	if(window.event) { // IE
		keynum = e.keyCode;
	}
	else if(e.which) { // Netscape/Firefox/Opera
		keynum = e.which;
	}
	if (keynum > 44) {
		inputObj.value = inputObj.value.replace(/\D/gi, "");
	}
}


function updateSubTotal(subTotalID, newValue, currencyID, removed, prodID) {
	var oldSubtotalTag = document.getElementById(subTotalID) ;
	var oldSubtotalValue = oldSubtotalTag.innerHTML.replace(',','') ;
	if (currencyID == '1' ) {
		//I couldn't get any of the string functions to works with the euro character, so I had to do it
		//the stupid way.
		var i = 0
		var newNum = '';
		var numLength = oldSubtotalValue.length;
		while (i<=numLength) {
			var singleChar = oldSubtotalValue.charAt(i);
			if (!isNaN(Math.round(singleChar)) || singleChar=='.' ) {
				newNum = newNum.concat(singleChar)
			}
			i = i +1;
		}
		currency = '&#8364;' ;
		oldSubtotalValue = newNum;
	} else if (currencyID == '2') {
		oldSubtotalValue = oldSubtotalValue.replace('$','')  ;
		currency = '$';
	} else {
		oldSubtotalValue = oldSubtotalValue.replace('AU$','')  ;
		currency = 'AU$';
	}


	/*
		The last argument is used to distinguish if a customer is clicking 'remove' versus changing a
		value in a field. If 'remove' has been clicked, we simply need to subtract the current value from
		the suntotal, since the oldValue global is captured in an onfocus event.
	*/
	if (removed) {
		oldSubtotalValue = new Number ((oldSubtotalValue - 0 + newValue));
	} else {

		oldSubtotalValue = new Number ((oldSubtotalValue - oldValueGlobalArray[prodID] + newValue));
	}

	oldSubtotalValue = oldSubtotalValue.toFixed(2);
	oldSubtotalValue = oldSubtotalValue.toString();

	oldSubtotalTag.innerHTML = ( '  ' + currency + add_commas_to_number(oldSubtotalValue) );
}

/*
	This function is used to make objects appear on the cart page
*/
	function makeVisible(objId) {
		document.getElementById(objId).style.visibility = 'visible';
	}

	/*
		This will set objects to display:'', which will make them visible if they have been set to
		display: none.
	*/
	function makeDisplay(objId) {
		document.getElementById(objId).style.display = '';
	}

/*
	This function will make a green background flash and then fade
	It's ised to highligh mul information once it's been loaded
*/
	function greenFade(el) {
	  var b = 100;
	  function f() {
	    el.style.background = 'rgb(' + (b+=4) + ',255,' + (b+=4) + ')';
	    if (b < 255) {
	      setTimeout(f, 30);
	    } else {
			el.style.background = '';
		}
	  };
	  f();
	}

/*
	This function will make a red background flash and then fade
	It's used to hightlight information in the form that hasn'y been filled out yet.
*/
	function redFade(el) {
	  var b = 100;
	  function f() {
	    el.style.background = 'rgb(255,' + (b+=4) + ',' + (b+=4) + ')';
	    if (b < 255) {
	      setTimeout(f, 40);
	    } else {
			el.style.background = '';
		}
	  };
	 f();
	}

/*
	showMissingData will higlight which portions of a form are missing data.
	It's activated when a user moves their mouse over the grey checkput button.
*/
	function showMissingData(formID) {
		var formObj = document.getElementById(formID);
		var inputs = new Array;

		for (var i=0;i<formObj.length;i++) {
			var input = formObj.elements[i];
			if (!input.value || input.value==='0') {
				if (input.type == 'select-one') {
					/*
						Errors for if a user hasn't selected a format
					*/

					var errorSpan = document.getElementById('formatMess_' + input.id.slice(7)) ;
					id = errorSpan.id.replace('formatMess_','')
					link = document.getElementById('add_format_' + id);
					errorSpan.innerHTML = '<span style="color:red; font-size:1em; margin-left:-10px">&nbsp;&#9664;</span>&nbsp;Select a font format<br>' + '<a id="' + link.id + '" href="' + link.href + '">add another format</a>'
					redFade(errorSpan);
				} else if (input.type == 'text') {
					/*
						Errors for if a user hasn't entered a number of users.
					*/
					var errorSpan = document.getElementById('mulMess_' + input.id.slice(4)) ;
					errorSpan.innerHTML = '<span style="color:red; font-size:1em">&nbsp;&nbsp;&#9664;</span>&nbsp;Enter the # of users for this license';
					document.getElementById('price_' + input.id.slice(4)).innerHTML = '';
					redFade(errorSpan);
				}
			}
		}

	}

	/*
		This funcion will turn bad input into whole numbers. If someone puts in a decimal, the number will be
		rounded.
	*/
	function make_input_integer(inputObj) {

		var input = Math.round(inputObj.value) ;

		if (isNaN(input)) {
			input = 0;
		}

		inputObj.value = input;
	}

	/*
		This is used in ajaxMULCalc to turn any input values into integers
	*/
	function make_value_integer(value) {
		var input = Math.round(value) ;
		if (isNaN(input)) {
			input = 0;
		}
		return(input)
	}

	/*
		This function checks that all of the appropiate inormation is in a form, and displays
		toggles two different checkout buttons on and off.
	*/
	function check_form_completed(formID,fakeButtonID, realButtonID) {
		var formObj = document.getElementById(formID);
		var inputs = new Array;

		var isFormComplete = true ;
		for (var i=0;i<formObj.length;i++) {
			var input = formObj.elements[i];
			if (!input.value || input.value==='0') {
				isFormComplete = false;
				break;
			}
		}


		if(isFormComplete && formObj.length>0) {
			document.getElementById(fakeButtonID).style.display = 'none';
			document.getElementById(realButtonID).style.display = '';
			return true ;
		} else {
			document.getElementById(fakeButtonID).style.display = '';
			document.getElementById(realButtonID).style.display = 'none';
			return false ;
		}

	}

	function selectText(textObj) {
		textObj.select();
	}

	/*
		This function should be run when the page loads in case the information is already filled in.
	*/
	check_form_completed('form_edit_cart','greyCheckoutButton', 'cart_checkout_button');

