/*Name:Checkout Validation*/
/*Order:5*/

/* 	
	----------------------------------------------------------------------
	GLOBAL VARIABLES
	Global variables for reuse throughout the scripting as well
	as some variables used for configuration.
	---------------------------------------------------------------------- 
*/


/* 	
	----------------------------------------------------------------------
	LOAD FUNCTION
	For scripts that need to be initalised, we can use have multiples
	run on page load. Yaaaa booo.
	---------------------------------------------------------------------- 
*/
window.onload.actions['checkoutValidation'] = initCheckout;
function initCheckout() {
	if (document.getElementById('selectForm')) {
		insertCarton('../../_assets/images/carton.swf')
		initBoxen('selectForm');
	}
	else if (document.getElementById('purchaseForm')) {
		insertCarton('../_assets/images/carton.swf')
		initBoxen('purchaseForm');
	}
	else if (document.getElementById('shippingForm')) {
		initValidation('shippingForm');
		shippingInit('totals');
	}
	else if (document.getElementById('billingForm')) {
		initValidation('billingForm');
		initSwitch('payment'); //INTERNET EXPLORER SUCKS */
		var copyDetails = document.getElementById('copyDetails');
		copyDetails.onchange = insertAddress;
		copyDetails.onclick = insertAddress;
		if (copyDetails.checked == true) {
			copyDetails.checked = false;
		}
	}
}


/* BOXEN */
/* 	
	----------------------------------------------------------------------
	GLOBAL VARIABLES AND CONFIG
	Some variables that we reuse in our functions, and some config stuff
	for the various IDed elements in the order system.
	---------------------------------------------------------------------- 
*/
var totalContainerID = 'totals';
/* Global variables. Do not touch these! */
var elBoxen;
var elTotalBottles;
var elTotalCartons;
var elTotalPrice;
var wines = new Array(); // This will be an array of literal objects.

/* 	
	----------------------------------------------------------------------
	INSERT CARTON 
	Swaps out the contents of an element with a flash file
	---------------------------------------------------------------------- 
*/
function insertCarton(url) {
	var fo = new FlashObject(url, "boxen", "220", "100", 6, "#FBF9E4");
	fo.write('cartons');
	elBoxen = document.getElementById('boxen');
}

/* 	
	----------------------------------------------------------------------
	INITALISE 
	Lets grab all our controls and assign the event handlers to them. Yay.
	---------------------------------------------------------------------- 
*/
function initBoxen(formID) {
	// Set up the events and totals and stuff
	var form = document.getElementById(formID);
	var inputs = form.getElementsByTagName('input');
	// Collect the elements for displaying the totals
	var totals = document.getElementById(totalContainerID);
	var dd = totals.getElementsByTagName('dd');
	for (var h = 0; h < dd.length; h++) {
		switch(dd[h].className) {
			case 'totalBottles':
				elTotalBottles =  dd[h];
			break;
			case 'totalCartons':
				elTotalCartons =  dd[h];
			break;
			case 'price':
				elTotalPrice =  dd[h];
			break;						
		}
	}
	// Set up our array and attach the events
	for (var i = 0; i < inputs.length; i++) {
		if (hasClass(inputs[i], 'quantity') == true) {
			// Attach the update event
			inputs[i].onkeyup = userUpdate;
			// Get the parent row and set up our literal object
			var parent = inputs[i];
			do {
				parent = parent.parentNode;
			} while(parent.nodeName != 'TR');
			wines[parent.id] = {quantity:inputs[i].value, pricePerBottle:null, pricePerDozen:null, totalPrice:null, elTotal:null, purchaseLimit:null};
			// Loop through the parents children to collect price and location of the total
			for (var j = 0; j < parent.childNodes.length; j++) {
				var child = parent.childNodes[j];
				if (child.nodeName == 'TD' && child.className == 'name') {
					// A span may contain a purchase limit:
					for (var k = 0; k < child.childNodes.length; k++) {
						var grandChild = child.childNodes[k];
						if (grandChild.nodeName == 'LABEL') {
							for (var l = 0; l < grandChild.childNodes.length; l++) {
								var greatGrandChild = grandChild.childNodes[l];
								if (greatGrandChild.nodeName == 'SPAN') {
									wines[parent.id].purchaseLimit = greatGrandChild.innerHTML;
								}
							}
						}
					}
				}
				if (child.nodeName == 'TD' && child.className == 'pricePerBottle') {
					// crude use of split to remove the dollar symbol
					var price = child.innerHTML;
					price = price.split('$');
					price = price[1];
					wines[parent.id].pricePerBottle = price;
				}
				if (child.nodeName == 'TD' && child.className == 'pricePerDozen') {
					// crude use of split to remove the dollar symbol
					var price = child.innerHTML;
					price = price.split('$');
					price = price[1];
					wines[parent.id].pricePerDozen = price;
				}
				else if (child.nodeName == 'TD' && child.className == 'total') {
					wines[parent.id].elTotal = child;
				}
			}
			// now initalise the input total
			updateItem(inputs[i]);
		}
	}
	// initalise the totals at the bottom
	updateTotals();
}

/* 	
	----------------------------------------------------------------------
	USER UPDATE
	This function gets called when the user does something to an item
	---------------------------------------------------------------------- 
*/
function userUpdate() {
	updateItem(this);
	updateTotals();
}

/* 	
	----------------------------------------------------------------------
	UPDATE ITEM 
	This updates a single item
	---------------------------------------------------------------------- 
*/
function updateItem(input) {
	// SIMPLE VALIDATION
	// Is this a number or alpha-numeric?
	if (isNaN(input.value) == true && input.value != '') {
		errorDisplay('Please Enter numbers only', input); // Spit the dummy
		var resetValue = parseInt(input.value); // see if we can extract a real value
		if (isNaN(resetValue)) {
			input.value = 0;
		}
		else {
			input.value = resetValue;
		}
		updateItem(input);
	}
	// has some spoobie typed in a decimal?
	else if (Math.round(input.value) != input.value) {
		errorDisplay('Please use whole numbers only', input); // Spit the dummy
		input.value = Math.round(input.value); // Reset it to a nicer value
		wines[parent.id].quantity = input.value;
	}
	else {
		// UPDATE ITEM TOTAL
		var parent = input;
		do {
			parent = parent.parentNode;
		} while(parent.nodeName != 'TR');
		// Store the quantity
		if (input.value == '') {
			wines[parent.id].quantity = 0;
		}
		else {
			//Check for a purchase limit on this product:
				if (wines[parent.id].purchaseLimit != null && input.value > parseInt(wines[parent.id].purchaseLimit)) {
					errorDisplay('This product is limited to ' + wines[parent.id].purchaseLimit + ' bottles per customer.', input); // Spit the dummy
					input.value = wines[parent.id].purchaseLimit; // Reset it to a nicer value
					wines[parent.id].quantity = wines[parent.id].purchaseLimit;
				} else {
					wines[parent.id].quantity = input.value;
				}
		}
		// Update the total 
		if (wines[parent.id].quantity == 0) {
			wines[parent.id].elTotal.innerHTML = '';
			wines[parent.id].totalPrice = 0;
		}
		else {
			var value = input.value;
			var newTotal;
			// Check for dozen pricing.
			if (value >= 12) {
				var remainder = input.value % 12;
				var dozens = (value - remainder) / 12;
				newTotal = (dozens * wines[parent.id].pricePerDozen) + (remainder * wines[parent.id].pricePerBottle);
			}
			else {
				newTotal = value * wines[parent.id].pricePerBottle;
			}
			wines[parent.id].totalPrice = newTotal;
			wines[parent.id].elTotal.innerHTML = '$' + currencyFormatter(newTotal);
		}
	}
}

/* 	
	----------------------------------------------------------------------
	UPDATE TOTALS 
	This function updates the totals for a particular item and then 
	works out the total for the whole order.
	
	We need to work some validation into this as well.
	---------------------------------------------------------------------- 
*/
function updateTotals() {
	// TOTAL BOTTLES & TOTAL PRICE
	var totalBottles = 0;
	var totalPrice = 0;
	for (var i in wines) {
		totalBottles += parseInt(wines[i].quantity);
		totalPrice += wines[i].totalPrice
	}
	elTotalBottles.innerHTML = totalBottles;
	elTotalPrice.innerHTML = '$' + currencyFormatter(totalPrice); // need to do some currency formatting
	// TOTAL CARTONS
	// Totally hacky way of doing this, will improve it in the future.
	var totalCartons = totalBottles / 12;
	var rounded = Math.round(totalCartons);
	if (rounded < totalCartons) {
		totalCartons =  rounded + 1;
	}
	else {
		totalCartons = rounded;
	}
	elTotalCartons.innerHTML = totalCartons;	
	// UPDATE FLASH DISPLAY
	updateCartons(totalBottles);
}

/* 	
	----------------------------------------------------------------------
	FLASH UPDATE
	Simple function that updates the display of the flash file to show
	the correct number of bottles and cartons. 
	
	We also include a little bit of code that checks to see if it has been
	totally loaded.
	---------------------------------------------------------------------- 
*/
function updateCartons(intTotalBottles) {
	//if (elBoxen.PercentLoaded) {	
		//if (elBoxen.PercentLoaded() == 100) {
			//elBoxen.GotoFrame(totalBottles);
		//}
		//else {
			//alert(intTotalBottles);
			//window.setTimeout('elBoxen.GotoFrame(' + totalBottles + ')', 500);
			elBoxen.GotoFrame(intTotalBottles);
		//}
	//}
}

/* FORM VALIDATION */
/* 	
	----------------------------------------------------------------------
	GLOBAL VARIABLES AND CONFIG
	Global variables reused throughout the scripts. Some variables used
	for configuration stuffies.
	---------------------------------------------------------------------- 
*/
/* Global variables. Do not touch these! */
var cardType = 0;
var payByCredit = true;
var required = new Array();
var requiredselect = new Array();
var submitButton;

/* 	
	----------------------------------------------------------------------
	INIALISE VALIDATION
	Grab the form, check the class of the inputs and attach the 
	appropriate events.
	---------------------------------------------------------------------- 
*/
function initValidation(formID) {
	var form = document.getElementById(formID);
	var inputs = form.getElementsByTagName('input');
	var selects = form.getElementsByTagName('select')
	for (var i = 0; i < inputs.length; i++) {
		// This is gonna have to be a heap of if statements
		// which ain't too nice... Heavy CPU usage here... need to do something like a regex
		// INPUTS TO VALIDATE
		if (hasClass(inputs[i], 'integer') == true) {
			inputs[i].onkeyup = validInteger;
		}
		if (hasClass(inputs[i], 'creditCardNumber') == true) {
			inputs[i].onkeyup = validCredit;
		}
		if (hasClass(inputs[i], 'dateMonth') == true) {
			inputs[i].onkeyup = validMonth;
		}
		if (hasClass(inputs[i], 'dateYear') == true) {
			inputs[i].onkeyup = validYear;
		}
		if (hasClass(inputs[i], 'phone') == true) {
			inputs[i].onchange = validPhone;	// Note onchange
		}
		if (hasClass(inputs[i], 'email') == true) {
			inputs[i].onchange = validEmail;	// Note onchange
		}
		// REQUIRED FIELDS
		if (hasClass(inputs[i], 'required') == true) {
			required[inputs[i].name] = inputs[i];
		}
		// SHIPPING DESTINATION SWITCH
		if (hasClass(inputs[i], 'shippingDestination') == true) {
			inputs[i].onchange = shippingUpdate;
			inputs[i].onclick = shippingUpdate;
			//inputs[i].onkeyup = shippingUpdate;
		}
}

for (var i = 0; i < selects.length; i++) {
    if (hasClass(selects[i], 'requiredselect') == true) {
        requiredselect[selects[i].name] = selects[i];
    }
        }
	// SUBMIT BUTTON 
	var buttons = form.getElementsByTagName('button');
	for (var k = 0; k < buttons.length; k++) {
		if (hasClass(buttons[k], 'checkFields') == true) {
			buttons[k].onclick = checkFields;
			submitButton = buttons[k];			
		}
	}
	// Grab the select box. we need to see the type of card selected
	var selects = form.getElementsByTagName('select');
	for (var j = 0; j < selects.length; j++) {
		if (hasClass(selects[j], 'creditCardType') == true) {
			selects[j].onchange = storeCardType;
			cardType = parseInt(selects[j].value);
		}
	}
}

/* 	
	----------------------------------------------------------------------
	VALID INTEGER
	Check to see that this is a valid, whole number. No digits.
	---------------------------------------------------------------------- 
*/
function validInteger() {
	var value = this.value;
	if (isNaN(value) == true) {
		errorDisplay('Please use numbers only', this);
		// replace it with something decent
		value = parseInt(value);
		if (isNaN(value) == true) {
			this.value = ''; // Firefox errors be DAMNED!!
		}
		else {
			this.value = value;
		}
	}
}

/* 	
	----------------------------------------------------------------------
	VALID PHONE
	Check to see that the phone number is a valid length and that it
	includes an area code
	---------------------------------------------------------------------- 
*/
function validPhone() {
	var filter  = /^(\(?\+?[0-9]*\)?)?[0-9_\- \(\)]*$/;
	if (!filter.test(this.value.toString())) {
		errorDisplay('Please use numbers only for your phone or fax number.', this);
	} else {
	}
}
// This takes any number with spaces in it, an uh, removes them.
// At least that's the idea, but, IS BROKENS! Bahahar.
function stripSpaces(inputString) {
	inputString = inputString.toString();
	var newString = '';
	for (var i = 0; i < inputString.length; i++) {
		if (isNaN(inputString[i]) == false ) {
			newString += inputString[i];
			//alert(inputString[i]);
		} else if
			(	inputString[i] != ' ' && 
				inputString[i] != '+' && 
				inputString[i] != '(' && 
				inputString[i] != ')') {
			newString += inputString[i];
				alert(inputString[i]);
		}
	}

	return newString;
}

/* 	
	----------------------------------------------------------------------
	VALID EMAIL
	Is this an email? It needs to begin with a string, an @ and finish
	with a TLD.
	---------------------------------------------------------------------- 
*/
function validEmail() {
	var x = this.value;
	var filter  = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
	if (!filter.test(x)) {
		errorDisplay('This is not a valid email address.', this);
	}
}

/* 	
	----------------------------------------------------------------------
	VALID CREDIT CARD NUMBER
	This checks to see that it is a number (no letters), then that it
	starts with the right numbers and is the correct length based on the
	type of card (visa, mastercard etc).
	---------------------------------------------------------------------- 
*/
function validCredit() {
	if (isNaN(this.value) == true) {
		errorDisplay('Please use numbers only (no spaces)', this);
	}
	else {
		// Check the card type and do the checks based on that
		var cardNumber = this.value.toString();
		var startTest;
		switch(cardType) {
			case 1:
				// VISA
				startTest = parseInt(cardNumber.slice(0, 1));
				if (startTest != 4) {
					errorDisplay('This is not a valid Visa number', this);
				}
			break;
			case 2:
				// MASTERCARD
				startTest = parseInt(cardNumber.slice(0, 1));
				if (startTest != 5) {
					errorDisplay('This is not a valid Mastercard number', this);
				}
			break;
			case 3:
				// AMERICAN EXPRESS
				if (cardNumber.length > 1) { // Make sure it's longer than 2 digits
					startTest = parseInt(cardNumber.slice(0, 2));
					if (startTest != 37) {
						errorDisplay('This is not a valid American Express number', this);
					}
				}
			break;
		}
	}
}
function correctCreditLength() {
	
}

// 1 = Visa
// 2 = Mastercard
// 3 = American Express
function storeCardType() {
	cardType = parseInt(this.value);
}

/* 	
	----------------------------------------------------------------------
	VALID MONTH AND YEAR
	Firstly check to see that the month value isn't 0 or more than 12
	---------------------------------------------------------------------- 
*/
function validMonth() {
	// check to see if this is a single digit
	if (this.value.length > 1) {
		if (this.value > 12 || isNaN(this.value) == true) {
			errorDisplay('Please use a value between 1 and 12', this);
			this.value = 0;
		}
	}
}
function validYear() {
	if (this.value.length > 1) {
		// turn the test value into an oughtie number
		var testValue = this.value.toString();
		testValue = parseInt(20 + testValue);
		// Now lets check it out
		if (testValue <= Date.getFullYear() - 1) {
			errorDisplay('This expiry date is invalid', this);
		}
	}
}

/* 	
	----------------------------------------------------------------------
	INIALISE SWITCH
	Dead simple bit of scripting to switch some inputs on or off depending
	on the users selection.
	
	ATTENTION
	We need to add some code in here to deal with switching required fields
	on and off.
	---------------------------------------------------------------------- 
*/
var blocks = new Array();
var reqStorage = new Array(); // This is where we keep a reference to required elements that are disabled

function initSwitch(blockID) {
	var block = document.getElementById(blockID);
	var divs = block.getElementsByTagName('div');
	for (var i = 0; i < divs.length; i++) {
		if (hasClass(divs[i], 'option') == true) {
			// Check and see which payment option has been selected
			if (hasClass(divs[i], 'payByCredit') == true) {
				payByCredit = true;
			}
			else if (hasClass(divs[i], 'payByCheque') == true) {
				payByCredit = false;
			}
			blocks[divs[i].id] = {id:divs[i].id, block:divs[i], input:null, enabled:null}; // Store the divs ID
			// find which inputs to attach the events to
			for (var j = 0; j < divs[i].childNodes.length; j++) {
				var child = divs[i].childNodes[j];
				if (child.nodeName == 'INPUT') {
					if (hasClass(child, 'switch') ==  true) {
						child.onclick = userSwitch;
						child.onchange = userSwitch;
						blocks[divs[i].id].enabled = child.checked; 
						blocks[divs[i].id].input = child;
					}
				}
			}
		}
	}
	// INIALISE THE STATE
	for (var i in blocks) {
		if (blocks[i].enabled == true) {
			switchBlock(blocks[i].input);
		}
	}
}

function userSwitch() {
	switchBlock(this);
}

function switchBlock(option) {
	// Get the parent
	var parent = option;
	do {
		parent = parent.parentNode;
	} while(hasClass(parent, 'option') != true);
	// Store the state
	blocks[parent.id].enabled = option.checked;
	// Modify the state of the other based on this
	if (blocks[parent.id].enabled == true) {
		for (var i in blocks) {
			if (blocks[i].id != parent.id) {
				// disable all these inputs
				blocks[i].enabled = false;
				blocks[i].input.checked = false;
				toggleInputs(blocks[i].block, false);
			}
			else {
				toggleInputs(blocks[i].block, true);
			}
		}
	}
}

function toggleInputs(parent, state) {
	var inputs = parent.getElementsByTagName('input');
	var selects = parent.getElementsByTagName('select');
	// DISABLE THE INPUTS
	if (state == false) {
		// Change the class on the parent
		addClass(parent, 'disabled')
		// disable the child elements
		for (var i = 0; i < inputs.length; i++) {
			if (hasClass(inputs[i], 'switch') != true) {
				// Disable the field
				inputs[i].disabled = true;
				// see if it is a required field. 
				// Remove it from the required array and store a reference to it...
				if (hasClass(inputs[i], 'required') == true) {
					required = removeHashedArrayEntry(required, inputs[i]);
					dimField(inputs[i]); // Make sure it's dimmed
				}
			}
		}
		for (var j = 0; j < selects.length; j++) {
			selects[j].disabled = true;
		}
	} 
	// ENABLE THE INPUTS
	else if (state = true) {
		// Change the class on the parent
		removeClass(parent, 'disabled')
		// enable the child elements
		for (var i = 0; i < inputs.length; i++) {
			if (hasClass(inputs[i], 'switch') != true) {
				// enable the field
				inputs[i].disabled = false;
				// see if it is a required field. 
				// if it is, add it to the required array
				if (hasClass(inputs[i], 'required') == true) {
					required[inputs[i].name] = inputs[i];
				}
			}
		for (var j = 0; j < selects.length; j++) {
			selects[j].disabled = false;
		}
		}
	}
}

/* 	
	----------------------------------------------------------------------
	SHIPPING INITALISE
	We just need to collect some elements for the sake of updates.
	
	Parts of this could actually be rolled into a common function for
	the boxen... on my todo list
	---------------------------------------------------------------------- 
*/
/* Global variables. Do not touch these! */
var elTotalShipping;
var totalPrice = 0;
function shippingInit(totalContainerID) {
	var totals = document.getElementById(totalContainerID);
	var dd = totals.getElementsByTagName('dd');
	for (var i = 0; i < dd.length; i++) {
		switch(dd[i].className) {
			case 'totalShipping':
				elTotalShipping =  dd[i];
			break;
			case 'price':
				elTotalPrice = dd[i];
				// collect the price
				totalPrice = elTotalPrice.innerHTML;
				totalPrice = totalPrice.split('$');
				totalPrice = parseFloat(totalPrice[1]);
			break;
		}
	}
}

function shippingUpdate() {
	if (this.checked == true) {
		// Lets go looking for the price
		var parent = this.parentNode;
		var labels = parent.getElementsByTagName('label');
		var price = '';
		var newPrice = '';
		var forLink;
		for (var i = 0; i < labels.length; ++i) {
			// Look though the attributes to get the for
			var idCheck = labels[i].id.split('_')
			if (idCheck[1] == this.id) {
			//alert(idCheck[1]);
				// Get the strong tag
				for (var j = 0; j < labels[i].childNodes.length; ++j) {
					if (labels[i].childNodes[j].nodeName == 'STRONG') {
						// crude use of split to remove the dollar symbol
						price = labels[i].childNodes[j].innerHTML;
						price = price.split('$');
						price = price[1];
						newPrice = totalPrice + parseFloat(price);
					}
				}
			}
		}
		elTotalPrice.innerHTML = '$' + currencyFormatter(newPrice);
		elTotalShipping.innerHTML = '$' + currencyFormatter(price);
	}
}

/* 	
	----------------------------------------------------------------------
	CHECK FIELDS
	Checks to see that any required fields are actually filled out
	---------------------------------------------------------------------- 
*/
function checkFields() {
	var complete = true;
	for (var i in required) {
		if (required[i].value == '' || required[i].value == ' ') {
			highlightField(required[i])
			complete = false;
		}
}

for (var s in requiredselect) {
    //alert('testcdaa');
    var txt = requiredselect[s].options[requiredselect[s].selectedIndex].value;
   // txt = txt + 'nothing';
    //alert('test' + txt);
    if (txt == '' ) {
      // alert(complete);     
        complete = false;
      // alert(complete);
    }
}
	if (complete == false) {
		errorDisplay('There are required fields you need to fill out', submitButton);
		return false;
	}
}


/* 	
	----------------------------------------------------------------------
	HIGHLIGHT FIELDS
	When a required field hasn't been filled out, this function 
	highlights it. 
	
	We may need an function to dim the highlight once it's been corrected.
	---------------------------------------------------------------------- 
*/
function highlightField(field) {
	field.style.borderColor = 'red';
	field.onfocus = dimThisField;
}
function dimThisField() {
	this.style.borderColor = '';		
}
function dimField(field) {
	field.style.borderColor = '';		
}

/* 	
	----------------------------------------------------------------------
	STORED VALUE
	This just inserts the stored address into some fields
	---------------------------------------------------------------------- 
*/
var isAddressInserted = false;
function insertAddress() {
	if (isAddressInserted == true) {
		isAddressInserted = false;
	}
	else {
		var parent = this;
		do {
			parent = parent.parentNode;
		} while (parent.nodeName != 'FIELDSET');
		var inputs = parent.getElementsByTagName('input');
		for (var i = 0; i < inputs.length; ++i) {
			
			if (inputs[i].type == 'hidden') {
				if (inputs[i].name.lastIndexOf('tored_') == 1) {
					var updateName = inputs[i].name.slice(inputs[i].name.indexOf('_') + 1, inputs[i].name.length);
					// Update the inputs
					for (var j = 0; j < inputs.length; ++j) {
						if (inputs[j].name == updateName) {
							inputs[j].value = inputs[i].value;
						}
					}
					// update the select
					if (updateName == 'Customer_Billing_State') {
						var selects = parent.getElementsByTagName('select');
						for (var h = 0; h < selects.length; ++h) {
							if (updateName == selects[h].name) {
								for (var k = 0; k < selects[h].childNodes.length; ++k) {
									if (selects[h].childNodes[k].value == inputs[i].value) {
										selects[h].childNodes[k].selected = 'selected';
									}
								} 
							}
						}
					}
				}
			}
		}
		isAddressInserted = true;
	}
}
