var xmlHttp = new Array();
var CurrentOptions = new Array();
var CurrentTotal = 0;

/* Adds event handlers to all cart items triggering price updates whenever items
 * are changed or selected */
function shopinit()
{
	var allFormElements = getAllFormElements();
	
	for (var i = 0; i < allFormElements.length; i++) {
		if (allFormElements[i].id.indexOf("s_") == 0) {
			addHandler(allFormElements[i], 'change', updatePrice, allFormElements[i]);
			addHandler(allFormElements[i], 'click', updatePrice, allFormElements[i]);
		} else {
			addHandler(allFormElements[i], 'change', updateOptions, allFormElements[i]);
			addHandler(allFormElements[i], 'click', updateOptions, allFormElements[i]);
		}
	}
	
	updatePrice();
}

/* Cross browser function for attaching event handlers */
function addHandler(target, eventName, handlerName, arg)
{
    if (target.addEventListener) {
      target.addEventListener(eventName, bindArguments(handlerName, arg), false);
    } else if (target.attachEvent) {
      target.attachEvent("on" + eventName, bindArguments(handlerName, arg));
    } else {
      target["on" + eventName] = bindArguments(handlerName, arg);
	}
}

/* The bindArguments function is used to bind arguments to anonymous functions
 * which otherwise cannot receive parameters. We're using it here to make
 * function calls bound to event handlers return a reference to that object */
function bindArguments(fn)
{
	var args = [];
	for (var n = 1; n < arguments.length; n++)
		args.push(arguments[n]);
	
	return function () { return fn.apply(this, args); };
}

/* Loops through all form objects on the page returning the value and description.
 * The value is totted up and becomes the CurrentTotal and the description is pushed
 * onto the CurrentOptions array */
function updatePrice()
{
	var allFormElements = getAllFormElements();
	var elTotalPrice = document.getElementById('TotalPrice');
	var arrItemData;
	var ItemCost = 0;
	CurrentTotal = 0;
	CurrentOptions = new Array();
	
	if (document.getElementById('s_splashback')) calculateSplashBackPrice();
	
    for (var i = 0; i < allFormElements.length; i++) {
		if (allFormElements[i].id.indexOf('s_') == 0) {
			arrItemData = allFormElements[i].value.split('|');
			
			if (allFormElements[i].type == "radio" || allFormElements[i].type == "checkbox") {
				if (allFormElements[i].checked == true) {
					(isNaN(parseInt(arrItemData[0]))) ? ItemCost = 0 : ItemCost = parseInt(arrItemData[0]);
					CurrentTotal += ItemCost;
					CurrentOptions.push(arrItemData[1]);
				}
			} else {
				(isNaN(parseInt(arrItemData[0]))) ? ItemCost = 0 : ItemCost = parseInt(arrItemData[0]);
				CurrentTotal += ItemCost;
				CurrentOptions.push(arrItemData[1]);
			}
		}
	}

	CurrentTotal = Math.round(CurrentTotal*100)/100;
	elTotalPrice.innerHTML = CurrentTotal.toFixed(2);
}

/* Calculates cost based on a manual length input */
function customLength(ItemLength)
{
	var elLength = document.getElementById('s_length');
	var arOptions = elLength.options;
	var CustomPrice = 0;
	var CustomLength = parseInt(ItemLength.value);
	var UpperLength = 0;
	
	for (var i = 0; i < arOptions.length; i++) {
		if (parseInt(arOptions[i].value.split('|')[2]) >= CustomLength) {
			if (parseInt(arOptions[i].value.split('|')[2]) >  UpperLength) UpperLength = parseInt(arOptions[i].value.split('|')[2]);
			CustomPrice = arOptions[i].value.split('|')[0];
			break;
		}
	}
	
	if (CustomLength > UpperLength) {
		alert('Sorry we cannot quote online for this size. Please contact us for further information.');
		ItemLength.value = '';
		return false;
	}
	
	if (CustomPrice > 0) {
		var elOptNew = document.createElement('option');
		elOptNew.text = CustomLength + 'mm - £' + CustomPrice;
		elOptNew.value = CustomPrice + '|Length ' + CustomLength + 'mm|' + CustomLength;
		
		try {
			elLength.add(elOptNew, null); // standards compliant; doesn't work in IE
		} catch(ex) {
			elLength.add(elOptNew); // IE only
		}
		
		elLength.selectedIndex = arOptions.length-1;
		updatePrice();
	}
}

/* Loops through all form objects on the page adding non-calculating items to the
 * CurrentOptions array */
function updateOptions()
{
	var allFormElements = getAllFormElements();
	CurrentOptions = new Array();
	
    for (var i = 0; i < allFormElements.length; i++) {
		arrItemData = allFormElements[i].value.split('|');
		
        if (allFormElements[i].type == "radio" || allFormElements[i].type == "checkbox") {
            if (allFormElements[i].checked == true) {
				if (arrItemData[1]) {
					CurrentOptions.push(arrItemData[1]);
				} else {
					CurrentOptions.push(arrItemData[0]);
				}
			}
        } else {
			if (arrItemData[1]) {
				CurrentOptions.push(arrItemData[1]);
			} else {
				CurrentOptions.push(arrItemData[0]);
			}
        }
	}
}

function dispatchOrder(UID)
{
	createXMLHttpRequest();
	var url = '../inc/shopping.php?action=dispatchOrder';
	var TrackID = document.getElementById(UID).value;
	var QueryString = 'UID=' + UID + '&TrackID=' + TrackID;
	
	xmlHttp.open("POST", url, true);
	xmlHttp.onreadystatechange = handleDispatchOrderStateChange;
	xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
	xmlHttp.send(QueryString);
}

/* Calculates price of SplashBack based on the currently selected length of unit */
function calculateSplashBackPrice()
{
	var elLength = document.getElementById('s_length');
	var elSplashBack = document.getElementById('s_splashback');
	var elSplashBackPrice = document.getElementById('SplashBackPrice');
	var arrLength = elLength.value.split('|');
	var length = arrLength[2];
	var SplashBackCost = length / 10 * 0.3;
	
	if (elSplashBack.checked) {
		elSplashBack.value = SplashBackCost + '|Loose splash back';
	} else {
		elSplashBack.value = '0|Loose splash back';
	}
	
	elSplashBackPrice.innerHTML = SplashBackCost;
}

/* Makes an AJAX call to the database sending the options list, cost and product code
 * to be added to the basket. TODO: we should only be sending product and option codes
 * to prevent risk of tampering - the server can re-calculate the correct price */
function addToBasket()
{
	createXMLHttpRequest();
	var url = 'inc/shopping.php?action=addToBasket';
	
	var elProductID = document.getElementById('ProductID');
	var ProductID = elProductID.innerHTML;
	var SelectedOptions = CurrentOptions.join(', ');
	var ItemCost = CurrentTotal.toFixed(2);
	var QueryString = 'pid=' + ProductID + '&cost=' + ItemCost + '&options=' + SelectedOptions;
	
	xmlHttp.open("POST", url, true);
	xmlHttp.onreadystatechange = handleAddToBasketStateChange;
	xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
	xmlHttp.send(QueryString);
}

/* Stores user data (name, address, etc) prior to sending the cart data to PayPal */
function saveUserDetails()
{
	createXMLHttpRequest();
	var url = 'inc/shopping.php?action=addUser';

	var UserName = document.getElementById('fullname').value;
	var UserEmail = document.getElementById('email').value;
	var UserAddress = document.getElementById('address1').value;
	var UserCity = document.getElementById('city').value;
	var UserPostcode = document.getElementById('postcode').value;
	var UserTelephone = document.getElementById('telephone').value;
	var ShipName = document.getElementById('shipfullname').value;
	var ShipEmail = document.getElementById('shipemail').value;
	var ShipAddress = document.getElementById('shipaddress1').value;
	var ShipCity = document.getElementById('shipcity').value;
	var ShipPostcode = document.getElementById('shippostcode').value;
	var ShipTelephone = document.getElementById('shiptelephone').value;
	
	if (ShipName.length == 0) ShipName = UserName;
	if (ShipEmail.length == 0) ShipEmail = UserEmail;
	if (ShipAddress.length == 0) ShipAddress = UserAddress;
	if (ShipCity.length == 0) ShipCity = UserCity;
	if (ShipPostcode.length == 0) ShipPostcode = UserPostcode;
	if (ShipTelephone.length == 0) ShipTelephone = UserTelephone;
	
	var QueryString = 'UserName=' + UserName + '&UserEmail=' + UserEmail + '&UserAddress=' + UserAddress + '&UserCity=' + UserCity + '&UserPostcode=' + UserPostcode + '&UserTelephone=' + UserTelephone;
	QueryString += '&ShipName=' + ShipName + '&ShipEmail=' + ShipEmail + '&ShipAddress=' + ShipAddress + '&ShipCity=' + ShipCity + '&ShipPostcode=' + ShipPostcode + '&ShipTelephone=' + ShipTelephone;

	xmlHttp.open("POST", url, false);
	xmlHttp.onreadystatechange = handleSaveUserDetailsStateChange;
	xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
	xmlHttp.send(QueryString);
}

/* Helper function responsible for updating the basket on screen and reporting any errors */
function handleAddToBasketStateChange()
{
	if (xmlHttp.readyState == 4) {
		if (xmlHttp.status == 200) {
			
			var arrResult = xmlHttp.responseText.split('|');
			
			if (parseInt(arrResult[0]) == -1) {
				var elBasket = document.getElementById('Basket');
				var elShowBasket = document.getElementById('ShowBasket');
				var elProductTitle = document.getElementById('ProductTitle');
				var ProductTitle = elProductTitle.innerHTML;
				CurrentTotal = CurrentTotal.toFixed(2);
				
				if (document.getElementById('EmptyBasket')) {
					var elEmpty = document.getElementById('EmptyBasket');
					var elParent = elEmpty.parentNode;
					elParent.removeChild(elEmpty);
					elShowBasket.style.display = 'block';
				}
			
				var NewItem = document.createElement('p');
				NewItem.appendChild(document.createTextNode(ProductTitle + ' - £' + CurrentTotal));
				elBasket.insertBefore(NewItem, elShowBasket);
			} else {
				alert(arrResult[1]);
			}
			
		} else {
			alert('An error occured. HTTP status code ' + xmlHttp.status + ' was returned.');
		}
	}

}

/* Helper function responsible: currently empty */
function handleSaveUserDetailsStateChange()
{
	if (xmlHttp.readyState == 4) {
		if (xmlHttp.status == 200) {
			
			var arrResult = xmlHttp.responseText.split('|');
			
			if (parseInt(arrResult[0]) == -1) {
				return true;
			} else {
				alert(arrResult[1]);
				return false;
			}
			
		} else {
			alert('An error occured. HTTP status code ' + xmlHttp.status + ' was returned.');
			return false;
		}
	}
}

function handleDispatchOrderStateChange()
{
	if (xmlHttp.readyState == 4) {
		if (xmlHttp.status == 200) {
			
			var arrResult = xmlHttp.responseText.split('|');
			
			if (parseInt(arrResult[0]) == -1) {
				alert(arrResult[1]);
				return true;
			} else {
				alert(arrResult[1]);
				return false;
			}
			
		} else {
			alert('An error occured. HTTP status code ' + xmlHttp.status + ' was returned.');
			return false;
		}
	}
}

/* The getAllFormElements function returns an array of objects
 * from the page of types SELECT, INPUT and TEXTAREA */
function getAllFormElements(parent_node)
{
	var out = new Array();

	if (parent_node == undefined) parent_node = document;

	formInputs = parent_node.getElementsByTagName("input");
	for (var i = 0; i < formInputs.length; i++) out.push( formInputs.item(i) );

	formInputs = parent_node.getElementsByTagName("textarea");
	for (var i = 0; i < formInputs.length; i++) out.push( formInputs.item(i) );

	formInputs = parent_node.getElementsByTagName("select");
	for (var i = 0; i < formInputs.length; i++) out.push( formInputs.item(i) );

	return out;
}

/* Cross browser function to create Request object */
function createXMLHttpRequest()
{
   if (window.ActiveXObject) {
      xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
   } else if (window.XMLHttpRequest) {
      xmlHttp = new XMLHttpRequest();
   }
}

/* Multiple instance-safe function to create Request object */
function createXMLHttpHandler()
{
	try {
		// Firefox, Opera 8.0+, Safari
		handler = new XMLHttpRequest();
	} catch (e) {
		// Internet Explorer
		try {
			handler = new ActiveXObject("Msxml2.XMLHTTP");
		} catch (e) {
			try {
				handler = new ActiveXObject("Microsoft.XMLHTTP");
			} catch (e) {
				alert("To use this website you need to update your web browser.");
			}
		}
	}

	var handle = xmlHttp.length;
	xmlHttp[handle] = handler;
	
	return handle;
}

/* Function called to create Request object */
function newXMLHttpRequest(method, action, querystring, callback)
{
	var handle = createXMLHttpHandler();
	
	if (handle >= 0) {
		var handler = xmlHttp[handle];
		var handlerURL = "/classes/handler.php?";
		var url = handlerURL + "action=" + action + "&t=" + new Date().getTime();
		if (method == "GET") url += "&" + querystring;
		
		handler.open(method, url, true);
		
		handler.onreadystatechange = function()
		{
			var response = xmlHttp[handle];
			callback(response);
		}
		
		if (method == "POST") {
			handler.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
			handler.setRequestHeader("Content-length", querystring.length);
			handler.setRequestHeader("Connection", "close");
			handler.send(querystring);
		} else {
			handler.send(null);
		}

	}
}

/* Gets option cost from server */
function getOptionCost(el)
{
	var id = el.id;
	var value = el.value
	
	if ((el.type == "checkbox" && el.checked == true) || el.type != "checkbox") {
		var querystring = "option_id=" + id + "&value_id=" + value;
		newXMLHttpRequest("GET", "getoptioncost", querystring, handleGetOptionCost);
	} else {
		CurrentOptions[id] = 0;
		calculateCost();
	}
}

function handleGetOptionCost(handler)
{
	if (handler.readyState == 4) {
		if (handler.status == 200) {
			if (handler.responseText) {
				var response = eval("(" + handler.responseText + ")");
				CurrentOptions[response.option_id] = response.cost;
				calculateCost();
			}
		}
	}
}

function calculateCost()
{
	var elTotalPrice = document.getElementById('TotalPrice');
	CurrentTotal = 0;
	
	for (id in CurrentOptions) {
		CurrentTotal += CurrentOptions[id];
	}
	
	CurrentTotal = Math.round(CurrentTotal*100)/100;
	elTotalPrice.innerHTML = CurrentTotal.toFixed(2);

}

function addItem(product_id)
{
	var querystring;
	var optionlist = '';
	var elTotalPrice = document.getElementById("TotalPrice");
	
	for (id in CurrentOptions) {
		optionlist += "&options[]=" + id + "|" + document.getElementById(id).value;
	}
	
	querystring =  "product_id=" + product_id;
	querystring += "&cost=" + elTotalPrice.innerHTML;
	querystring += optionlist;
	newXMLHttpRequest("POST", "additem", querystring, handleAddItem);
}

function handleAddItem(handler)
{
	if (handler.readyState == 4) {
		if (handler.status == 200) {
			if (handler.responseText) {
				var response = eval("(" + handler.responseText + ")");
				if (response.status == -1) {
					var elBasket = document.getElementById('Basket');
					var elShowBasket = document.getElementById('ShowBasket');
					var elProductTitle = document.getElementById('ProductTitle');
					var ProductTitle = elProductTitle.innerHTML;
					CurrentTotal = CurrentTotal.toFixed(2);
					
					if (document.getElementById('EmptyBasket')) {
						var elEmpty = document.getElementById('EmptyBasket');
						var elParent = elEmpty.parentNode;
						elParent.removeChild(elEmpty);
						elShowBasket.style.display = 'block';
					}
				
					var NewItem = document.createElement('p');
					NewItem.appendChild(document.createTextNode(ProductTitle + ' - £' + CurrentTotal));
					elBasket.insertBefore(NewItem, elShowBasket);
				} else {
					alert(response.error);
				}
			}
		}
	}
}

/* Makes an AJAX call to the database sending the basket id to be deleted */
function deleteFromBasket(bid)
{
	if (confirm('Are you sure you want to remove this item?')) {
		var querystring = 'id=' + bid;
		newXMLHttpRequest("POST", "deleteitem", querystring, handleDeleteFromBasket);
		return false;
	} else {
		return false;
	}
}

/* Helper function responsible for updating the basket on screen and reporting any errors */
function handleDeleteFromBasket(handler)
{
	if (handler.readyState == 4) {
		if (handler.status == 200) {
			if (handler.responseText) {
				var response = eval("(" + handler.responseText + ")");
				if (response.status == -1) {
					var elGrandTotal = document.getElementById("GrandTotal");
					var elSubTotal = document.getElementById("SubTotal");
					var elVAT = document.getElementById("VAT");
					var elBasket = document.getElementById('BASKET_' + response.id);
					var elParent = elBasket.parentNode;
					elParent.removeChild(elBasket);
					elSubTotal.innerHTML = response.subtotal;
					elVAT.innerHTML = response.vat;
					elGrandTotal.innerHTML = response.grandtotal;	
				} else {
					alert(response.error);
				}
			}	
		} else {
			alert('An error occured. HTTP status code ' + handler.status + ' was returned.');
		}
	}
}

function initProduct()
{
	var allFormElements = getAllFormElements();
	
	for (var i = 0; i < allFormElements.length; i++) {
		elCurrent = allFormElements[i];
		if (elCurrent.type == "button") continue;
		
		if (elCurrent.type == "checkbox") {
			if (elCurrent.checked == true) getOptionCost(elCurrent);
		} else {
			getOptionCost(elCurrent);
		}
	}
}