var numberOfParcelRows = -1;
var parcelAdded = false;
var defaultRowStatus = '- Select Insurance -';
var selectServiceOptionText = 'Please Select a Service...';
var prebookErrorOccured = false;
var allowedDates = new Array();
var shipmentDetails = new Array();
var parcelTooltipContent = '<div class="parcelTooltip"><div class="parcelTooltipImg"><img src="/custom/images/addparcel.gif" /></div> Click this icon to <strong>send another parcel to the same address</strong>.</div><div class="parcelTooltip"><div class="parcelTooltipImg"><img src="/custom/images/removeparcel.gif" /></div> Click this icon to <strong>remove this parcel from this shipment</strong>.</div>';
var shipmentTooltipContent = '<div class="shipmentTooltip"><div class="shipmentTooltipImg"><img src="/custom/images/addshipmenticon.gif" /></div> Click this icon to <strong>send parcels to another address</strong>.</div><div class="shipmentTooltip"><div class="parcelTooltipImg"><img src="/custom/images/removeshipment.gif" /></div> Click this icon to <strong>remove this shipment entirely</strong>.</div>';
var lastRemoveParcelIconId = '';

function completeShippingAddresses() {
	shipmentDetails[ currentQuoteRowId ].from = new Object();
	shipmentDetails[ currentQuoteRowId ].from.name = document.getElementById('cmsServicesShipping_shipFrom_contact_name').value;
	shipmentDetails[ currentQuoteRowId ].from.houseNumber = document.getElementById('cmsServicesShipping_shipFrom_house_number').value;
	shipmentDetails[ currentQuoteRowId ].from.address1 = document.getElementById('cmsServicesShipping_shipFrom_address_1').value;
	shipmentDetails[ currentQuoteRowId ].from.address2 = document.getElementById('cmsServicesShipping_shipFrom_address_2').value;
	shipmentDetails[ currentQuoteRowId ].from.town = document.getElementById('cmsServicesShipping_shipFrom_address_3').value;
	shipmentDetails[ currentQuoteRowId ].from.county = document.getElementById('cmsServicesShipping_shipFrom_city').value;
	shipmentDetails[ currentQuoteRowId ].from.postcode = document.getElementById('cmsServicesShipping_shipFrom_postcode').value;
	shipmentDetails[ currentQuoteRowId ].from.country = 'GB';
	shipmentDetails[ currentQuoteRowId ].from.residential = document.getElementById('cmsServicesShipping_shipFrom_residential_address').value;
	shipmentDetails[ currentQuoteRowId ].from.company = document.getElementById('cmsServicesShipping_shipFrom_company').value;
	shipmentDetails[ currentQuoteRowId ].from.telephone = document.getElementById('cmsServicesShipping_shipFrom_phone_number').value;
	shipmentDetails[ currentQuoteRowId ].from.email = document.getElementById('cmsServicesShipping_shipFrom_email_address').value;
	
	shipmentDetails[ currentQuoteRowId ].to = new Object();
	shipmentDetails[ currentQuoteRowId ].to.name = document.getElementById('cmsServicesShipping_shipTo_contact_name').value;
	shipmentDetails[ currentQuoteRowId ].to.houseNumber = document.getElementById('cmsServicesShipping_shipTo_house_number').value;
	shipmentDetails[ currentQuoteRowId ].to.address1 = document.getElementById('cmsServicesShipping_shipTo_address_1').value;
	shipmentDetails[ currentQuoteRowId ].to.address2 = document.getElementById('cmsServicesShipping_shipTo_address_2').value;
	shipmentDetails[ currentQuoteRowId ].to.town = document.getElementById('cmsServicesShipping_shipTo_address_3').value;
	shipmentDetails[ currentQuoteRowId ].to.county = document.getElementById('cmsServicesShipping_shipTo_city').value;
	shipmentDetails[ currentQuoteRowId ].to.postcode = document.getElementById('cmsServicesShipping_shipTo_postcode').value;
	shipmentDetails[ currentQuoteRowId ].to.country = document.getElementById('cmsServicesShipping_shipTo_country').value;
	shipmentDetails[ currentQuoteRowId ].to.residential = document.getElementById('cmsServicesShipping_shipTo_residential_address').value;
	shipmentDetails[ currentQuoteRowId ].to.company = document.getElementById('cmsServicesShipping_shipTo_company').value;
	shipmentDetails[ currentQuoteRowId ].to.telephone = document.getElementById('cmsServicesShipping_shipTo_phone_number').value;
	shipmentDetails[ currentQuoteRowId ].to.email = document.getElementById('cmsServicesShipping_shipTo_email_address').value;
	
	if ( validateShippingAddresses( currentQuoteRowId, false ) ) {
		hideShippingAddressPopup();
		$('#cmsServicesShipping_collection_date_icon_' + currentQuoteRowId ).trigger('openCalendar');
	}
	updateStatus( currentQuoteRowId );
}

function validateShippingAddresses( rowId, surpressErrors ) {
	populateCollectionAddresses( rowId );
	var selects = new Array( 'shipTo', 'shipFrom' )
	for ( i = 0; i < selects.length; i++ ) {
		if ( document.getElementById( 'cmsServicesShipping_' + selects[i] + '_residential_address' ).value == 1 ) {
			document.getElementById( 'cmsServicesShipping_' + selects[i] + '_company' ).value = document.getElementById( 'cmsServicesShipping_' + selects[i] + '_contact_name' ).value
		}
	}
	var validatorTo = checkAddressStatus( 'To', true );
	var validatorFrom = checkAddressStatus( 'From', true );
	if ( validatorFrom.numberOfErrors() > 0 ) {
		if ( !surpressErrors ) {
			changeShippingAddressTab('from');
			validatorFrom.displayErrors();
		}
		return false;
	} else if ( validatorTo.numberOfErrors() > 0 ) {
		if ( !surpressErrors ) {
			changeShippingAddressTab('to');
			validatorTo.displayErrors();
		}
		return false;
	} else {
		return true;
	}
}

function validateShippingAddress( direction ) {
	var validator = checkAddressStatus( direction, false );
	if ( validator.numberOfErrors() > 0 ) {
		// there were errors, set the tab color to red to indicate this
		var classToAdd = 'addressError';
		var classToRemove = 'addressValid';
	} else {
		// no errors, set the tab color to green to indicate this
		var classToAdd = 'addressValid';
		var classToRemove = 'addressError';
	}
	var elId = 'addressTab_' + direction.toLowerCase();
	YAHOO.util.Dom.removeClass( elId, classToRemove );
	YAHOO.util.Dom.addClass( elId, classToAdd );
}

function highlightAddressField( fieldId ) {
	YAHOO.util.Dom.addClass( fieldId, 'addressInputError' );
}
function lowlightAddressField( fieldId ) {
	YAHOO.util.Dom.removeClass( fieldId, 'addressInputError' );
}

function checkAddressStatus( direction, doHighlight ) {
	var validator = new validateForm();
	if ( document.getElementById( 'cmsServicesShipping_ship' + direction + '_residential_address' ).value == 0 ) {
		if ( !validator.checkText( 'cmsServicesShipping_ship' + direction + '_company', 'Ship ' + direction + ': Company Name' ) ) {
			if ( doHighlight ) {
				highlightAddressField( 'cmsServicesShipping_ship' + direction + '_company' );
			}
		} else {
			lowlightAddressField( 'cmsServicesShipping_ship' + direction + '_company' );
		}
	}
	
	if ( !validator.checkText( 'cmsServicesShipping_ship' + direction + '_contact_name', 'Ship ' + direction + ': Contact Name' ) ) {
		if ( doHighlight ) {
			highlightAddressField( 'cmsServicesShipping_ship' + direction + '_contact_name' );
		}
	} else {
		lowlightAddressField( 'cmsServicesShipping_ship' + direction + '_contact_name' );
	}
	
	if ( direction == 'From' ) {
		if ( !validator.validatePostCode( 'cmsServicesShipping_ship' + direction + '_postcode', 'Ship ' + direction + ': Post Code' ) ) {
			if ( doHighlight ) {
				highlightAddressField( 'cmsServicesShipping_ship' + direction + '_postcode' );
			}
		} else {
			lowlightAddressField( 'cmsServicesShipping_ship' + direction + '_postcode' );
		}
	} else if ( direction == 'To' ) {
		var country = $( '#cmsServicesShipping_ship' + direction + '_country option:selected' ).text();
		if ( country.indexOf('*') > -1 ) {
			if ( $( '#cmsServicesShipping_ship' + direction + '_country' ).val() == 'GB' ) {
				var isValid = validator.validatePostCode( 'cmsServicesShipping_ship' + direction + '_postcode', 'Ship ' + direction + ': Post Code' );
			} else {
				var isValid = validator.checkText( 'cmsServicesShipping_ship' + direction + '_postcode', 'Ship ' + direction + ': Post Code' );
			}
			if ( !isValid ) {
				if ( doHighlight ) {
					highlightAddressField( 'cmsServicesShipping_ship' + direction + '_postcode' );
				}
			} else {
				lowlightAddressField( 'cmsServicesShipping_ship' + direction + '_postcode' );
			}
		}
	}
	
	if ( !validator.validateEmailAddress( 'cmsServicesShipping_ship' + direction + '_email_address', 'Ship ' + direction + ': Email Address' ) ) {
		if ( doHighlight ) {
			highlightAddressField( 'cmsServicesShipping_ship' + direction + '_email_address' );
		}
	} else {
		lowlightAddressField( 'cmsServicesShipping_ship' + direction + '_email_address' );
	}
	
	if ( !validator.checkText( 'cmsServicesShipping_ship' + direction + '_phone_number', 'Ship ' + direction + ': Telephone Number' ) ) {
		if ( doHighlight ) {
			highlightAddressField( 'cmsServicesShipping_ship' + direction + '_phone_number' );
		}
	} else {
		lowlightAddressField( 'cmsServicesShipping_ship' + direction + '_phone_number' );
	}
	
	if ( !validator.checkText( 'cmsServicesShipping_ship' + direction + '_address_1', 'Ship ' + direction + ': Address 1' ) ) {
		if ( doHighlight ) {
			highlightAddressField( 'cmsServicesShipping_ship' + direction + '_address_1' );
		}
	} else {
		lowlightAddressField( 'cmsServicesShipping_ship' + direction + '_address_1' );
	}
	
	if ( !validator.checkText( 'cmsServicesShipping_ship' + direction + '_address_3', 'Ship ' + direction + ': Town' ) ) {
		if ( doHighlight ) {
			highlightAddressField( 'cmsServicesShipping_ship' + direction + '_address_3' );
		}
	} else {
		lowlightAddressField( 'cmsServicesShipping_ship' + direction + '_address_3' );
	}
	
	if ( !validator.checkText( 'cmsServicesShipping_ship' + direction + '_city', 'Ship ' + direction + ': County' ) ) {
		if ( doHighlight ) {
			highlightAddressField( 'cmsServicesShipping_ship' + direction + '_city' );
		}
	} else {
		lowlightAddressField( 'cmsServicesShipping_ship' + direction + '_city' );
	}
	
	return validator;
}

function dump(arr,level) {
	var dumped_text = "";
	if(!level) level = 0;
	//The padding given at the beginning of the line.
	var level_padding = "";
	for(var j=0;j<level+1;j++) level_padding += "    ";
	if(typeof(arr) == 'object') { //Array/Hashes/Objects
		for(var item in arr) {
			var value = arr[item];
			if(typeof(value) == 'object') { //If it is an array,
				dumped_text += level_padding + "'" + item + "' ...\n";
				dumped_text += dump(value,level+1);
			} else {
				dumped_text += level_padding + "'" + item + "' => \"" + value + "\"\n";
			}
		}
	} else { //Stings/Chars/Numbers etc.
		dumped_text = "===>"+arr+"<===("+typeof(arr)+")";
	}
	return dumped_text;
}

function removeAllOptions( slct ) {
	slct.options.length = 0;
}

function addOptionToSelect( slct, opt ) {
	slct.options[ slct.options.length ] = opt;
}

function addToSurchargeInfo( rowId, html ) {
	if ( html != '' ) {
		html = 'The following surcharges have been applied to these services:<br /><br />' + html;
	} else {
		html = 'No surcharges apply to these services';
	}
	document.getElementById('infoIcon_' + rowId).title = html;
	addToolTipToElement( '#infoIcon_' + rowId );
}

function getFormattedSurchargeInfo( surcharges, serviceName ) {
	var infoHTML = ''
	if ( surcharges.length > 0 ) {
		infoHTML += '<p><strong>' + serviceName + '</strong></p><ul>';
	}
	for ( var surcharge in surcharges ) {
		infoHTML += '<li>' + surcharges[ surcharge ]['description'] + ' - £' + parseFloat( surcharges[ surcharge ]['price'] ).toFixed(2) + '</li>';
	}
	if ( surcharges.length > 0 ) {
		infoHTML += '</ul>';
	}
	return infoHTML;
}

function searchForQuotes( rowId ) {
	var handleSuccess = function(o){
		eval( 'var services = ' + o.responseText );
		if ( typeof services['errors'] != 'undefined' ) {
			// error occured, inform the user
			eval( 'var errors = ' + o.responseText );
			msg = "The following errors occured:\n\n";
			for ( var e in errors ) {
				msg += " - " + errors[e] + "\n";
			}
			alert( msg );
		} else if ( ( typeof services['availableServices'] != 'undefined' ) && ( services['availableServices'].length > 0 ) ) {
			// we have some services to display...
			var slct = document.getElementById('cmsServicesShipping_service_' + rowId );
			removeAllOptions( slct );
			slct.disabled = false;
			var opt = new Option( selectServiceOptionText, '' );
			addOptionToSelect( slct, opt );
			var infoHTML = '';
			for ( var i in services['availableServices'] ) {
				var opt = new Option( services['availableServices'][i]['wpsService']['name'] + ' - £' + services['availableServices'][i]['filteredTotalIncInsuranceIncVAT'], i );
				addOptionToSelect( slct, opt );
				infoHTML += getFormattedSurchargeInfo( services['availableServices'][i]['surcharges'], services['availableServices'][i]['wpsService']['name'] );
			}
			addToSurchargeInfo( rowId, infoHTML );
		} else {
			// errr, hopefully it will never get here...
			alert('Sorry, an error has occured.  Please try again.');
		}
	};
	var handleFailure = function(o){
		if ( o.responseText != '' ) {
			eval( 'var services = ' + o.responseText );
			if ( typeof services['errors'] != 'undefined' ) {
				// error occured, inform the user
				eval( 'var errors = ' + o.responseText );
				msg = "The following errors occured:\n\n";
				for ( var e in errors ) {
					msg += "\t- " + errors[e] + "\n";
				}
				alert( msg );
			} else {
				// errr, hopefully it will never get here either...
				alert('Sorry, an error has occured.  Please try again.');
			}
		} else {
			// errr, hopefully it will never get here either...
			alert('Sorry, an error has occured.  Please try again.');
		}
	};
	var callback =
	{
		success:handleSuccess,
		failure:handleFailure
	};
	makeAjaxShipmentRequest( rowId, 'service=customService&customService=getAvailableServices&quoteId=' + rowId, callback );
}

function makeAjaxShipmentRequest( rowId, params, callback ) {
	// loop round all dimension, contents and value inputs, dynamically adding them to the quote form that gets submitted
	var parcelContainer = document.getElementById('quoteFormParcelContainer');
	parcelContainer.innerHTML = '';
	var table = document.getElementById( 'cmsServicesShipping_parcelDimensions_' + rowId ).getElementsByTagName('TABLE')[0];
	var rows = table.getElementsByTagName('TR');
	for ( var r = 0; r < rows.length; r++ ) {
		var inputs = rows[r].getElementsByTagName('INPUT');
		for ( var i = 0; i < inputs.length; i++ ) {
			var newInput = document.createElement('INPUT');
			var elementId = inputs[i].id;
			var idSplit = elementId.split('_');
			var elementName = idSplit[ idSplit.length - 1 ];
			newInput.type = 'hidden';
			newInput.value = inputs[i].value;
			newInput.name = 'cmsServicesShipping[packages][' + r + '][' + elementName + ']';
			parcelContainer.appendChild( newInput );
		}
	}
	document.getElementById('queryForm_insurance').value = document.getElementById('cmsServicesShipping_insurance_' + rowId ).value;
	document.getElementById('queryForm_selected_service').value = document.getElementById('cmsServicesShipping_service_' + rowId ).value;
	document.getElementById('queryForm_collection_date').value = document.getElementById('cmsServicesShipping_collection_date_' + rowId).value;
	// update the delivery country name for display purposes later
	selectTo = document.getElementById( 'cmsServicesShipping_shipTo_country' );
	var countryTo = selectTo.options[ selectTo.selectedIndex ].text;
	document.getElementById( 'cmsServicesShipping_shipTo_country_long' ).value = countryTo.replace('*','');
	// requestarama
	YAHOO.util.Connect.setForm( document.getElementById( 'quoteForm' ) );
	var cObj = YAHOO.util.Connect.asyncRequest( 'POST', '/xmlservice.php?' + params, callback );
}

function checkDimensions( rowId, type ) {
	var table = document.getElementById( 'cmsServicesShipping_parcelDimensions_' + rowId ).getElementsByTagName('TABLE')[0];
	var rows = table.getElementsByTagName('TR');
	var ret = true;
	var thisType = '';
	var inputId = '';
	var thisRowId = '';
	for ( var r = 0; r < rows.length; r++ ) {
		var inputs = rows[r].getElementsByTagName('INPUT');
		for ( var i = 0; i < inputs.length; i++ ) {
			inputId = inputs[i].id;
			thisTypeSplit = inputId.split('_');
			thisType = thisTypeSplit[ thisTypeSplit.length - 1 ];
			// get the 1_3 part from the current input where the id = cmsServicesShipping_packages_1_3_height
			thisRowId = inputId.replace('cmsServicesShipping_packages_','');
			thisRowId = thisRowId.replace('_' + thisType,'');
			if ( thisType == type ) {
				// this is the type (ie width, length etc) we are checking
				if ( inputs[i].value == '' ) {
					updateSectionStatus( thisRowId, type, false );
					ret = false;
				} else {
					updateSectionStatus( thisRowId, type, true );
				}
			} else {
				// not the section we are checking, but update it's status anyway
				if ( inputs[i].value == '' ) {
					updateSectionStatus( thisRowId, thisType, false );
				} else {
					updateSectionStatus( thisRowId, thisType, true );
				}
			}
		}
	}
	return ret;
}

function checkParcelValues( rowId ) {
	
	var table = document.getElementById( 'cmsServicesShipping_parcelDimensions_' + rowId ).getElementsByTagName('TABLE')[0];
	var rows = table.getElementsByTagName('TR');
	var totalValue = 0;
	// get the combined values of all parcels
	for ( var r = 0; r < rows.length; r++ ) {
		var inputs = rows[r].getElementsByTagName('INPUT');
		for ( var i = 0; i < inputs.length; i++ ) {
			var inputId = inputs[i].id;
			if ( inputId.substring( inputId.length - 5 ) == 'value' ) {
				if ( inputs[i].value == '' ) {
					return false;
				} else {
					totalValue += parseInt( inputs[i].value );
				}
			}
		}
	}
	// get insurance value
	var insuranceValue = parseInt( document.getElementById( 'cmsServicesShipping_insurance_' + rowId ).value );
	
	var ret = false;
	
	if ( totalValue <= insuranceValue ) {
		// combined parcel value is less than the selected insurance amount
		ret = true;
	} else {
		// combined parcel value is greater than the selected insurance amount
		ret = false;
	}
	
	// update the status of all value fields in this shipment
	for ( var r = 0; r < rows.length; r++ ) {
		var inputs = rows[r].getElementsByTagName('INPUT');
		for ( var i = 0; i < inputs.length; i++ ) {
			var inputId = inputs[i].id;
			if ( inputId.substring( inputId.length - 5 ) == 'value' ) {
				var thisRowId = inputId.replace('cmsServicesShipping_packages_','');
				thisRowId = thisRowId.replace('_value','');
				updateSectionStatus( thisRowId, 'value', ret );
			}
		}
	}
	
	return ret;
}

function updateSectionStatus( rowId, section, complete ) {
	YAHOO.util.Dom.removeClass( 'row_section_' + rowId + '_' + section, 'rowStatusComplete' );
	YAHOO.util.Dom.removeClass( 'row_section_' + rowId + '_' + section, 'rowStatusError' );
	YAHOO.util.Dom.addClass( 'row_section_' + rowId + '_' + section, ( complete ) ? 'rowStatusComplete' : 'rowStatusError' );
}

function updateStatus( rowId ) {
	var rowStatus = defaultRowStatus;
	if ( document.getElementById('cmsServicesShipping_insurance_' + rowId ).selectedIndex > 0 ) {
		if ( checkDimensions( rowId, 'width' ) ) {
			if ( checkDimensions( rowId, 'length' ) ) {
				if ( checkDimensions( rowId, 'height' ) ) {
					// user has entered all required dimensions
					if ( checkDimensions( rowId, 'weight' ) ) {
						// user has entered parcel weight
						if ( checkDimensions( rowId, 'description' ) ) {
							// user has entered parcel contents
							updateSectionStatus( rowId, 'description', true );
							if ( checkDimensions( rowId, 'value' ) ) {
								// user has entered parcel value
								updateSectionStatus( rowId, 'value', true );
								if ( checkParcelValues( rowId ) ) {
									// the parcel value does not exceed the insurance cover
									updateSectionStatus( rowId, 'insurance', true );
									updateSectionStatus( rowId, 'value', true );
									if ( validateShippingAddresses( rowId, true ) ) {
										// all shipping address details have been entered
										updateSectionStatus( rowId, 'address', true );
										if ( document.getElementById('cmsServicesShipping_collection_date_' + rowId ).value != '' ) {
											updateSectionStatus( rowId, 'date', true );
											// user has selected a collection date and everything is valid!
											rowStatus = 'Searching for quotes...';
											// kick off the quote search
											searchForQuotes( rowId );
										} else {
											updateSectionStatus( rowId, 'date', false );
											rowStatus = '- Select Collection Date -';
										}
									} else {
										updateSectionStatus( rowId, 'address', false );
										rowStatus = '- Enter All Address Information -';
									}
								} else {
									rowStatus = '- Parcel value must not exceed insurance value -';
									showOverValuePopup();
								}
							} else {
								rowStatus = '- Enter Parcel Value -';
							}
						} else {
							rowStatus = '- Enter Parcel Contents -';
						}
					} else {
						rowStatus = '- Enter Parcel Weight -';
					}
				} else {
					rowStatus = '- Enter Parcel Height -';
				}
			} else {
				rowStatus = '- Enter Parcel Length -';
			}
		} else {
			rowStatus = '- Enter Parcel Dimensions -';
		}
	} else {
		rowStatus = defaultRowStatus;
	}
	var slct = document.getElementById('cmsServicesShipping_service_' + rowId );
	removeAllOptions( slct );
	var opt = new Option( rowStatus, 0 );
	addOptionToSelect( slct, opt );
	slct.disabled = true;
}

function checkDisabledDates( date ) {
	return !( Calendar.dateToInt( date ) in allowedDates );
}

function populateCollectionAddress( addressType, address ) {
	document.getElementById('cmsServicesShipping_ship' + addressType + '_contact_name').value = address.name;
	document.getElementById('cmsServicesShipping_ship' + addressType + '_house_number').value = address.houseNumber;
	document.getElementById('cmsServicesShipping_ship' + addressType + '_address_1').value = address.address1;
	document.getElementById('cmsServicesShipping_ship' + addressType + '_address_2').value = address.address2;
	document.getElementById('cmsServicesShipping_ship' + addressType + '_address_3').value = address.town;
	document.getElementById('cmsServicesShipping_ship' + addressType + '_city').value = address.county;
	document.getElementById('cmsServicesShipping_ship' + addressType + '_postcode').value = address.postcode;
	document.getElementById('cmsServicesShipping_ship' + addressType + '_company').value = address.company;
	document.getElementById('cmsServicesShipping_ship' + addressType + '_email_address').value = address.email;
	document.getElementById('cmsServicesShipping_ship' + addressType + '_phone_number').value = address.telephone;
	document.getElementById('cmsServicesShipping_ship' + addressType + '_residential_address').value = address.residential;
	changeResidential( address.residential, 'ship' + addressType )
	if ( addressType == 'To' ) {
		document.getElementById('cmsServicesShipping_ship' + addressType + '_country').value = address.country;
		checkShipToPostcode( address.country );
	}
}

function getEmptyAddress() {
	var emptyAddress = {
		to	:		{
			name		:	'',
			houseNumber	:	'',
			address1	:	'',
			address2	: 	'',
			town		:	'',
			county		:	'',
			postcode	:	'',
			country		:	'GB',
			residential	:	0,
			company		:	'',
			telephone	:	'',
			email		:	''
		},
		from	:	{
			name		:	'',
			houseNumber	:	'',
			address1	:	'',
			address2	: 	'',
			town		:	'',
			county		:	'',
			postcode	:	'',
			country		:	'GB',
			residential	:	0,
			company		:	'',
			telephone	:	'',
			email		:	''
		}
	};
	return emptyAddress;
}

function resetCollectionAddresses() {
	var emptyAddress = getEmptyAddress();
	populateCollectionAddress( 'From', emptyAddress.from );
	populateCollectionAddress( 'To', emptyAddress.to );
}

function populateCollectionAddresses( num ) {
	if ( typeof shipmentDetails[ num ].from != 'undefined' ) {
		populateCollectionAddress( 'From', shipmentDetails[ num ].from );
		populateCollectionAddress( 'To', shipmentDetails[ num ].to );
	} else {
		resetCollectionAddresses();
	}
}

function removeQuoteRow( tr, rowId ) {
	// remove the row from the UI
	tr.parentNode.removeChild( tr );
	var handleSuccess = function(o) { };
	var handleFailure = function(o) { };
	var callback = {
		success:handleSuccess,
		failure:handleFailure
	};
	// ajax request to remove the item from the session
	var cObj = YAHOO.util.Connect.asyncRequest( 'POST', '/xmlservice.php?service=customService&customService=removePackage&quoteId=' + rowId, callback );
	numberOfParcelRows--;
	delete shipmentDetails[ rowId ];
	if ( numberOfParcelRows == -1 ) {
		// we've removed all rows in the table, add a brand spanking new one
		addQuoteRow();
	}
}

function removeParcelFromShipment( tr, rowId ) {
	// remove the package from the UI
	var parent = tr.parentNode;
	parent.removeChild( tr );
	var rows = parent.getElementsByTagName('TR');
	if ( rows.length == 0 ) {
		// we've just removed the last row, so add a new one
		addParcelToShipment( rowId );
	}
	updateStatus( rowId );
}

function addParcelToShipment( thisId, parcelDetails ) {
	// get or create the table we will append the dimensions to
	var tablesFound = document.getElementById( 'cmsServicesShipping_parcelDimensions_' + thisId ).getElementsByTagName('TABLE');
	if ( tablesFound.length == 1 ) {
		// we've already created a table for this shipment, so use that
		var table = tablesFound[0];
		var tbody = table.getElementsByTagName('TBODY')[0];
		var parcelNumber = tbody.getElementsByTagName('TR').length + 1;
	} else {
		// no table has been created yet, so create it
		var table = document.createElement('TABLE');
		var tbody = document.createElement('TBODY');
		table.appendChild( tbody );
		var parcelNumber = 1;
	}
	var tr = document.createElement('TR');
	// create weight cell
	var td = document.createElement('TD');
		td.className = 'quoteTableDimension';
		td.setAttribute( 'id', 'row_section_' + thisId + '_' + parcelNumber + '_weight' );
	var input4 = document.createElement('INPUT');
		input4.setAttribute( 'type', 'text' );
		input4.setAttribute( 'name', 'cmsServicesShipping[packages][' + thisId + '][' + parcelNumber + '][weight]' );
		input4.setAttribute( 'id', 'cmsServicesShipping_packages_' + thisId + '_' + parcelNumber + '_weight' );
		input4.setAttribute( 'value', ( ( typeof parcelDetails != 'undefined' ) ? parcelDetails.weight : '' ) );
		input4.className = 'formInput dimensionInput';
		YAHOO.util.Event.addListener( input4, 'keyup', function(e) { checkWhole( 'kg', input4 ); updateStatus( thisId ); } );
		td.appendChild( input4 );
		tr.appendChild( td );
	// create length cell
	var td = document.createElement('TD');
		td.className = 'quoteTableDimension';
		td.setAttribute( 'id', 'row_section_' + thisId + '_' + parcelNumber + '_length' );
	var input1 = document.createElement('INPUT');
		input1.setAttribute( 'type', 'text' );
		input1.setAttribute( 'name', 'cmsServicesShipping[packages][' + thisId + '][' + parcelNumber + '][length]' );
		input1.setAttribute( 'id', 'cmsServicesShipping_packages_' + thisId + '_' + parcelNumber + '_length' );
		input1.setAttribute( 'value', ( ( typeof parcelDetails != 'undefined' ) ? parcelDetails.length : '' ) );
		input1.className = 'formInput dimensionInput';
		YAHOO.util.Event.addListener( input1, 'keyup', function(e) { checkWhole( 'cm', input1 ); updateStatus( thisId ); } );
		td.appendChild( input1 );
		tr.appendChild( td );
	// create width cell
	var td = document.createElement('TD');
		td.className = 'quoteTableDimension';
		td.setAttribute( 'id', 'row_section_' + thisId + '_' + parcelNumber + '_width' );
	var input2 = document.createElement('INPUT');
		input2.setAttribute( 'type', 'text' );
		input2.setAttribute( 'name', 'cmsServicesShipping[packages][' + thisId + '][' + parcelNumber + '][width]' );
		input2.setAttribute( 'id', 'cmsServicesShipping_packages_' + thisId + '_' + parcelNumber + '_width' );
		input2.setAttribute( 'value', ( ( typeof parcelDetails != 'undefined' ) ? parcelDetails.width : '' ) );
		input2.className = 'formInput dimensionInput';
		YAHOO.util.Event.addListener( input2, 'keyup', function(e) { checkWhole( 'cm', input2 ); updateStatus( thisId ); } );
		td.appendChild( input2 );
		tr.appendChild( td );
	// create height cell
	var td = document.createElement('TD');
		td.className = 'quoteTableDimension';
		td.setAttribute( 'id', 'row_section_' + thisId + '_' + parcelNumber + '_height' );
	var input3 = document.createElement('INPUT');
		input3.setAttribute( 'type', 'text' );
		input3.setAttribute( 'name', 'cmsServicesShipping[packages][' + thisId + '][' + parcelNumber + '][height]' );
		input3.setAttribute( 'id', 'cmsServicesShipping_packages_' + thisId + '_' + parcelNumber + '_height' );
		input3.setAttribute( 'value', ( ( typeof parcelDetails != 'undefined' ) ? parcelDetails.height : '' ) );
		input3.className = 'formInput dimensionInput';
		YAHOO.util.Event.addListener( input3, 'keyup', function(e) { checkWhole( 'cm', input3 ); updateStatus( thisId ); } );
		td.appendChild( input3 );
		tr.appendChild( td );
	// create the contents cell
	var td = document.createElement('TD');
		td.className = 'quoteTableContents';
		td.setAttribute( 'id', 'row_section_' + thisId + '_' + parcelNumber + '_description' );
	var input5 = document.createElement('INPUT');
		input5.setAttribute( 'type', 'text' );
		input5.setAttribute( 'name', 'cmsServicesShipping[packages][' + thisId + '][' + parcelNumber + '][description]' );
		input5.setAttribute( 'id', 'cmsServicesShipping_packages_' + thisId + '_' + parcelNumber + '_description' );
		input5.setAttribute( 'value', ( ( typeof parcelDetails != 'undefined' ) ? parcelDetails.description : '' ) );
		input5.className = 'formInput contentsInput';
		YAHOO.util.Event.addListener( input5, 'keyup', function(e) { updateStatus( thisId ); } );
		td.appendChild( input5 );
		tr.appendChild( td );
	// create value cell
	var td = document.createElement('TD');
		td.className = 'quoteTableValue';
		td.setAttribute( 'id', 'row_section_' + thisId + '_' + parcelNumber + '_value' );
	var input6 = document.createElement('INPUT');
		input6.setAttribute( 'type', 'text' );
		input6.setAttribute( 'name', 'cmsServicesShipping[packages][' + thisId + '][' + parcelNumber + '][value]' );
		input6.setAttribute( 'id', 'cmsServicesShipping_packages_' + thisId + '_' + parcelNumber + '_value' );
		input6.setAttribute( 'value', ( ( typeof parcelDetails != 'undefined' ) ? parcelDetails.value : '0' ) );
		input6.className = 'formInput valueInput';
		YAHOO.util.Event.addListener( input6, 'keyup', function(e) { updateStatus( thisId ); } );
		td.appendChild( input6 );
		tr.appendChild( td );
	// add the add/remove icons
	var td = document.createElement('TD');
		td.className = 'addRemoveParcelIcon';
	var img = document.createElement('IMG');
		lastRemoveParcelIconId = 'removeParcelIcon_' + thisId + '_' + parcelNumber;
		img.setAttribute( 'id', lastRemoveParcelIconId );
		img.setAttribute( 'src', '/custom/images/removeparcel.gif' );
		//img.setAttribute( 'title', 'Remove this parcel' );
		img.className = 'removeParcelIcon';
		YAHOO.util.Event.addListener( img, 'click', function() { removeParcelFromShipment( tr, thisId ) } );
		td.appendChild( img );
		tr.appendChild( td );
	tbody.appendChild( tr );
	
	// add tooltip to remove parcel icon
	// (note this is done here and in addQuoteRow because when the first package is added to a shipment (in addQuoteRow), 
	// the image hasn't been applied to the page yet and so the tooltip does not get rendered )
	addToolTipToElement( '#' + lastRemoveParcelIconId, parcelTooltipContent );
	
	return table;
}

function getNextRowId() {
	var max = 0;
	for ( var i in shipmentDetails ) {
		if ( i > max ) {
			max = i;
		}
	}
	return max + 1;
}

function addQuoteRow( rowId, collectionDate, parcelDetails, availableServices, insuranceSelected ) {
	// increment the counter
	numberOfParcelRows++;
	// clear the current shipment address information
	resetCollectionAddresses();
	// get the tbody we will append the row to
	var tbody = document.getElementById('quoteRows');
	// get the unique ID for this row
	if ( typeof rowId == 'undefined' ) {
		var thisId = getNextRowId();
	} else {
		var thisId = rowId;
		parcelAdded = true;
	}
	// create new row
	var tr = document.createElement('TR');
	// add the insurance options
	var td = document.createElement('TD');
		td.setAttribute( 'id', 'row_section_' + thisId + '_insurance' );
	var insuranceSelect = document.createElement('SELECT');
		insuranceSelect.setAttribute( 'name', 'cmsServicesShipping[insurance][' + thisId + ']' );
		insuranceSelect.setAttribute( 'id', 'cmsServicesShipping_insurance_' + thisId );
		insuranceSelect.className = 'formInput insuranceInput';
		
		insuranceSelect = addInsuranceOptionsToSelect( insuranceSelect );
		
		if ( typeof insuranceSelected != 'undefined' ) {
			var insuranceValues = { '' : 1, '50' : 1, '100' : 2, '250' : 3, '500' : 4, '750' : 5, '1000' : 6 };
			insuranceSelect.selectedIndex = insuranceValues[ insuranceSelected ];
		}
		YAHOO.util.Event.addListener( insuranceSelect, 'change', function() {
			// update the status of the corresponding value fields
			checkParcelValues( thisId );
			// put the cursor in the next field (weight)
			document.getElementById('cmsServicesShipping_packages_' + thisId + '_1_weight').focus();
			// set the status of the insurance box to green
			updateSectionStatus( thisId, 'insurance', true );
			// updateStatus
			updateStatus( thisId );
		} );
		
		td.appendChild( insuranceSelect );
		tr.appendChild( td );
		
	// create cell to contain parcel dimensions
	var td = document.createElement('TD');
		td.className = 'quoteTableDimensions';
	var dimensionsDiv = document.createElement('DIV');
		dimensionsDiv.setAttribute( 'id', 'cmsServicesShipping_parcelDimensions_' + thisId );
		td.appendChild( dimensionsDiv );
		tr.appendChild( td );
	// add a divider cell
	tr.appendChild( addDividerCell() );
	// add the "add parcel" button
	var td = document.createElement('TD');
	var img = document.createElement('IMG');
		img.setAttribute( 'id', 'addParcelIcon_' + thisId );
		img.setAttribute( 'src', '/custom/images/addparcel.gif' );
		//img.setAttribute( 'title', 'Add another parcel' );
		img.className = 'addParcelIcon';
		YAHOO.util.Event.addListener( img, 'click', function() { addParcelToShipment( thisId ) } );
		td.appendChild( img );
		tr.appendChild( td );
	// create address button cell
	var td = document.createElement('TD');
		td.setAttribute( 'id', 'row_section_' + thisId + '_address' );
	var input7 = document.createElement('INPUT');
		input7.setAttribute( 'type', 'button' );
		input7.setAttribute( 'id', 'cmsServicesShipping_packages_' + thisId + '_addressBtn' );
		input7.setAttribute( 'value', 'Enter Addresses' );
		input7.className = 'button greyBtnOnGrey';
		YAHOO.util.Event.addListener( input7, 'click', function(e) { showShippingAddressPopup( thisId, input7 ) } );
		td.appendChild( input7 );
		tr.appendChild( td );
	// add a divider cell
	tr.appendChild( addDividerCell() );
	// add date selector
	var td = document.createElement('TD');
		td.setAttribute( 'id', 'row_section_' + thisId + '_date' );
	var input8 = document.createElement('INPUT');
		input8.setAttribute( 'type', 'hidden' );
		input8.setAttribute( 'name', 'cmsServicesShipping_collection_date_' + thisId );
		input8.setAttribute( 'id', 'cmsServicesShipping_collection_date_' + thisId );
		if ( ( typeof collectionDate == 'string' ) && ( collectionDate.indexOf('/') > 0 ) ) {
			var collectionDateSplit = collectionDate.split('/');
			collectionDate = collectionDateSplit[2] + '' + collectionDateSplit[1] + '' + collectionDateSplit[0];
		}
		input8.setAttribute( 'value', ( ( typeof collectionDate != 'undefined' ) ? Calendar.dateToInt(collectionDate) : '' ) );
		td.appendChild( input8 );
	var input9 = document.createElement('IMG');
		input9.setAttribute( 'src', '/custom/images/iconcalendar.jpg' );
		input9.setAttribute( 'title', 'Select collection date' );
		input9.setAttribute( 'id', 'cmsServicesShipping_collection_date_icon_' + thisId );
		td.appendChild( input9 );
		tr.appendChild( td );
	// add a divider cell
	tr.appendChild( addDividerCell() );
	// add the service select
	var td = document.createElement('TD');
	var select = document.createElement('SELECT');
		select.setAttribute( 'name', 'cmsServicesShipping[services][' + thisId + ']' );
		select.setAttribute( 'id', 'cmsServicesShipping_service_' + thisId );
		select.className = 'formInput serviceInput';
		var selectedServiceIndex = 0;
		if ( typeof availableServices != 'undefined' ) {
			// we have a list of services to add to the drop down
			var opt = new Option( selectServiceOptionText, '' );
			addOptionToSelect( select, opt );
			for ( var a in availableServices ) {
				opt = new Option( availableServices[a].name + ' - £' + availableServices[a].price, a );
				addOptionToSelect( select, opt );
				if ( availableServices[a].selected ) {
					selectedServiceIndex = parseInt( a ) + 1;
				}
			}
		} else {
			// no services so just add the default option
			var opt = new Option( defaultRowStatus, '' );
			addOptionToSelect( select, opt );
			// and disable the select (for now)
			select.setAttribute( 'disabled', 'disabled' );
		}
		select.selectedIndex = selectedServiceIndex;
		td.appendChild( select );
		tr.appendChild( td );
	// add a divider cell
	tr.appendChild( addDividerCell() );
	// add the add/remove icons
	var td = document.createElement('TD');
		td.className = 'addRemoveParcelIcon';
	var img = document.createElement('IMG');
		img.setAttribute( 'id', 'removeShipmentIcon_' + thisId );
		img.setAttribute( 'src', '/custom/images/removeshipment.gif' );
		img.setAttribute( 'title', 'Remove this shipment' );
		img.className = 'removeShipmentIcon';
		YAHOO.util.Event.addListener( img, 'click', function() { removeQuoteRow( tr, thisId ) } );
		td.appendChild( img );
		tr.appendChild( td );
	// add the info cell
	var td = document.createElement('TD');
		td.className = 'quoteTableLastCell';
	var img = document.createElement('IMG');
		img.setAttribute( 'id', 'infoIcon_' + thisId );
		img.setAttribute( 'src', '/custom/images/infoicon.jpg' );
		img.setAttribute( 'title', 'Surcharge information will appear here when a quote is returned' );
		td.appendChild( img );
		tr.appendChild( td );
	// append the new row
	tbody.appendChild( tr );
	
	if ( typeof availableServices != 'undefined' ) {
		// add any surcharge information
		var infoHTML = '';
		for ( var a in availableServices ) {
			if ( ( typeof availableServices[a].surcharges != 'undefined' ) && ( availableServices[a].surcharges.length > 0 ) ) {
				infoHTML += getFormattedSurchargeInfo( availableServices[a].surcharges, availableServices[a].name );
			}
		}
		addToSurchargeInfo( thisId, infoHTML );
	} else {
		addToolTipToElement( '#infoIcon_' + thisId );
	}
	
	if ( typeof parcelDetails != 'undefined' ) {
		for ( var p in parcelDetails ) {
			var dimensions = addParcelToShipment( thisId, parcelDetails[p] );
			dimensionsDiv.appendChild( dimensions );
		}
	} else {
		var dimensions = addParcelToShipment( thisId );
		dimensionsDiv.appendChild( dimensions );
	}
	
	// add tooltip to remove parcel icon
	addToolTipToElement( '#' + lastRemoveParcelIconId, parcelTooltipContent );
		
	// create the calendar
	var cal = Calendar.setup({
		inputField	: input8.getAttribute('id'),
		dateFormat	: "%Y%m%d",
		trigger		: input9.getAttribute('id'),
        disabled	: checkDisabledDates,
        bottomBar	: false,
		selection	: ( ( typeof collectionDate != 'undefined' ) ? [ collectionDate ] : '' ),
		onSelect	: function() {
			if ( this.selection.get() != this.previousSelection ) {
				// if the date has changed, check the status
				// the 'onSelect' event gets fired on click of the trigger, so we don't
				// want to start searching for services then.
				updateStatus( thisId );
				this.previousSelection = this.selection.get();
				input9.title = Calendar.printDate( Calendar.intToDate( this.selection.get() ), '%d/%m/%Y' );
			}
			this.hide();
		},
		align		: 'Br'
	});
	cal.previousSelection = '';
	$('#' + input9.id ).bind( 'openCalendar', function() {
		// hack in the popup call so we can open it once an address has been entered
		//cal.popup(input9);
		cal.doOnClick(cal.args.trigger, cal.args.inputField, cal.args.dateFormat);
	});
	
	// create a new element in our shipment details array
	if ( typeof shipmentDetails[ thisId ] == 'undefined' ) {
		shipmentDetails[ thisId ] = new Object();
	}
	// add the tool tip for the "add a parcel" icon
	addToolTipToElement( '#addParcelIcon_' + thisId, parcelTooltipContent );
	// add the tool tip for the "remove shipment" icon
	addToolTipToElement( '#removeShipmentIcon_' + thisId, shipmentTooltipContent );
	
	if ( insuranceSelect.selectedIndex == 0 ) {
		// indicate that the insurance is the first thing that needs to be selected
		updateSectionStatus( thisId, 'insurance', false );
	}
}

function getInsurancePriceFromAmount( amount ) {
	switch ( amount ) {
		case '100':
			return 5;
		case '250':
			return 7.5;
		case '500':
			return 12.5;
		case '750':
			return 16;
		case '1000':
			return 20;
		case '50':
		default:
			return 0;
	}
}

function addInsuranceOptionsToSelect( select ) {
	var opt = new Option( '- Select Insurance -', '' );
	addOptionToSelect( select, opt );
	var opt = new Option( 'Upto £50.00 cover (Included)', '50' );
	addOptionToSelect( select, opt );
	var opt = new Option( 'Upto £100.00 cover (£' + getInsurancePriceFromAmount( '100' ).toFixed(2) + ')', '100' );
	addOptionToSelect( select, opt );
	var opt = new Option( 'Upto £250.00 cover (£' + getInsurancePriceFromAmount( '250' ).toFixed(2) + ')', '250' );
	addOptionToSelect( select, opt );
	var opt = new Option( 'Upto £500.00 cover (£' + getInsurancePriceFromAmount( '500' ).toFixed(2) + ')', '500' );
	addOptionToSelect( select, opt );
	var opt = new Option( 'Upto £750.00 cover (£' + getInsurancePriceFromAmount( '750' ).toFixed(2) + ')', '750' );
	addOptionToSelect( select, opt );
	var opt = new Option( 'Upto £1,000.00 cover (£' + getInsurancePriceFromAmount( '1000' ).toFixed(2) + ')', '1000' );
	addOptionToSelect( select, opt );
	return select;
}

function addToolTipToElement( element, content ) {
	var config = {
		position: {
			target: 'mouse'
		},
		adjust : {
			mouse: true
		},
		show : {
			solo: true
		}
	};
	
	if ( typeof content != 'undefined' ) {
		config.content = content
	}

	$( element ).qtip( config );
}

function addDividerCell() {
	var td = document.createElement('TD');
		td.className = 'quoteTableDivider';
	var newTxt = document.createTextNode(' ');
	td.appendChild( newTxt );
	return td;
}

function changeShippingAddressTab( dir ) {
	// hide both tab contents
	document.getElementById('shippingAddressTabContent_to').style.display = 'none';
	document.getElementById('shippingAddressTabContent_from').style.display = 'none';
	// neutralize both tabs
	YAHOO.util.Dom.removeClass( 'addressTab_to', 'shippingAddressTabOn' );
	YAHOO.util.Dom.removeClass( 'addressTab_from', 'shippingAddressTabOn' );
	// and re-add the class to the correct tab
	YAHOO.util.Dom.addClass( 'addressTab_' + dir, 'shippingAddressTabOn' );
	// show the correct tab content
	document.getElementById('shippingAddressTabContent_' + dir).style.display = '';
}

function loadFromAddress() {
	loadAddresses( 'From' );
}

function loadToAddress() {
	loadAddresses( 'To' );
}

function loadAddresses( direction ) {
	var postcode = document.getElementById('cmsServicesShipping_ship' + direction + '_postcode').value;
	GetAddressList( direction, postcode );
}

function updatePrebookStatus( status, id, message ) {
	var html = '<div class="prebookStatusTitle">';
	var cssClass = 'prebookRow';
	switch ( status ) {
		case 'pending':
			html += 'Processing';
			cssClass += ' statusPending';
			break;
		case 'confirmed':
			html += 'Completed';
			cssClass += ' statusConfirmed';
			break;
		case 'error':
			html += 'Error';
			cssClass += ' statusError';
			break;
	}
	html += '</div>';
	if ( typeof message != 'undefined' ) {
		document.getElementById('prebook_message_' + id).innerHTML = message;
		document.getElementById('prebook_message_' + id).style.display = 'block';
	}
	document.getElementById('prebook_status_' + id).innerHTML = html;
	document.getElementById('prebook_row_' + id).className = cssClass;
}

function getQuoteRowId( index ) {
	var count = 0;
	for ( var i in shipmentDetails ) {
		if ( count == index ) {
			return i;
		}
		count++;
	}
	return false;
}

function doPrebookShipment( thisId ) {
	var id = getQuoteRowId( thisId );
	if ( id !== false ) {
		populateCollectionAddresses( id );
		var handleSuccess = function(o) {
			eval( 'var returned = ' + o.responseText );
			if ( typeof returned['errors'] != 'undefined' ) {
				// error occured, inform the user
				eval( 'var errors = ' + o.responseText );
				msg = '';
				var i = 1;
				for ( var e in errors ) {
					msg += i + " - " + errors[e] + '<br />';
					i++;
				}
				updatePrebookStatus( 'error', id, msg );
				// update our flag
				prebookErrorOccured = true;
			} else if ( ( typeof returned['status'] != 'undefined' ) && ( returned['status'] == 'confirmed' ) ) {
				// success!
				updatePrebookStatus( 'confirmed', id );
			} else {
				// errr, hopefully it will never get here...
				var msg = '1 - Unspecified error.  Please try again.';
				updatePrebookStatus( 'error', id, msg );
				// update our flag
				prebookErrorOccured = true;
			}
			// attempt the next shipment
			doPrebookShipment( thisId + 1 );
		};
		var handleFailure = function(o) {
			if ( o.responseText != '' ) {
				eval( 'var returned = ' + o.responseText );
				if ( typeof returned['errors'] != 'undefined' ) {
					// error occured, inform the user
					var msg = '';
					var i = 1;
					for ( var e in errors ) {
						msg += i + " - " + errors[e] + '<br />';
						i++;
					}
				} else {
					// errr, hopefully it will never get here either...
					var msg = '1 - Unspecified error.  Please try again.';
				}
			} else {
				// errr, hopefully it will never get here either...
				var msg = '1 - Unspecified error.  Please try again.';
			}
			// update status of this shipment
			updatePrebookStatus( 'error', id, msg );
			// update our flag
			prebookErrorOccured = true;
			// attempt the next shipment
			doPrebookShipment( thisId + 1 );
		};
		var callback = {
			success:handleSuccess,
			failure:handleFailure
		};
		makeAjaxShipmentRequest( id, 'service=customService&customService=prebookShipments&quoteId=' + id, callback );
	} else {
		// no more shipments to process
		if ( prebookErrorOccured ) {
			document.getElementById('prebookButtonAmend').style.display = '';
		} else {
			setTimeout( 'prebookShipmentsComplete()', 1000 );
		}
	}
}

function prebookShipmentsComplete() {
	// see if the customer has selected additional insurance
	var insuranceInputs = YAHOO.util.Dom.getElementsByClassName('insuranceInput');
	hasAdditionalInsurance = false;
	for ( var s = 0; s < insuranceInputs.length; s++ ) {
		if ( insuranceInputs[s].selectedIndex > 1 ) {
			hasAdditionalInsurance = true;
		}
	}
	if ( ( !hasAdditionalInsurance ) || ( hasAdditionalInsurance && confirm( 'Shipments Confirmed!' + "\n\n" + 'As you have purchased additional insurance you MUST NOT tick the insurance box on the waybill as your insurance provided through Worldwide Parcel Services not the carrier. Failure to comply with this will invalidate your claim.' + "\n\n" + 'Click "OK" to agree and proceed to the checkout.') ) ) {
		document.getElementById('prebookCheckoutMessage').style.display = '';
		document.location = '/checkout';
	} else {
		hidePrebookPopup();
	}
}

function getServiceImageByName( name ) {
	var nameSplit = name.split('-');
	var serviceName = trim( nameSplit[0] );
	var src = '/custom/images/services/';
	switch ( serviceName ) {
		case 'WPS 24':
			src += '24-small.png';
			break;
		case 'WPS Diamond':
			src += 'diamond-small.png';
			break;
		case 'WPS European Express (DPD)':
			src += 'europeanexpress-small.png';
			break;
		case 'WPS European Express (DHL)':
			src += 'europeanexpressdhl-small.png';
			break;
		case 'WPS Worldwide Express':
			src += 'worldwideexpress-small.png';
			break;
	}
	return src;
}

function prebookShipments() {
	// make sure all services have been selected
	var serviceInputs = YAHOO.util.Dom.getElementsByClassName('serviceInput');
	prebookErrorOccured = false;
	for ( var s = 0; s < serviceInputs.length; s++ ) {
		if ( serviceInputs[s].selectedIndex == 0 ) {
			alert('Please select all required services.  If a shipment is not required, please remove it by clicking the "Remove Shipment" icon on the right-hand side of the corresponding row.');
			return false;
		}
	}
	// hide the amend button
	document.getElementById('prebookButtonAmend').style.display = 'none';
	document.getElementById('prebookCheckoutMessage').style.display = 'none';
	// get the container we will append all rows to and clear it out
	var container = document.getElementById('prebookContainer');
	container.innerHTML = '';
	// loop through all services creating a placeholder for the various elements
	for ( var i = 0; i <= numberOfParcelRows; i++ ) {
		var id = getQuoteRowId( i );
		var slct = document.getElementById('cmsServicesShipping_service_' + id);
		var serviceName = slct.options[ slct.selectedIndex ].text;
		var rowDiv = document.createElement('DIV');
			rowDiv.className = 'prebookRow';
			rowDiv.setAttribute( 'id', 'prebook_row_' + id );
		var imgDiv = document.createElement('DIV');
			imgDiv.className = 'prebookImage';
			var imgIcon = document.createElement('IMG');
			imgIcon.src = getServiceImageByName( serviceName );
			imgDiv.appendChild( imgIcon );
		var titleDiv = document.createElement('DIV');
			titleDiv.className = 'prebookTitle';
			var slct = document.getElementById('cmsServicesShipping_service_' + id);
			titleDiv.innerHTML = serviceName;
		var statusDiv = document.createElement('DIV');
			statusDiv.className = 'prebookStatus';
			statusDiv.setAttribute( 'id', 'prebook_status_' + id );
		var msgDiv = document.createElement('DIV');
			msgDiv.setAttribute( 'id', 'prebook_message_' + id );
			msgDiv.className = 'prebookMessage';
		var clearerDiv = document.createElement('DIV');
			clearerDiv.className = 'clearer';
		rowDiv.appendChild( imgDiv );
		rowDiv.appendChild( titleDiv );
		rowDiv.appendChild( statusDiv );
		rowDiv.appendChild( msgDiv );
		rowDiv.appendChild( clearerDiv );
		container.appendChild( rowDiv );
		updatePrebookStatus( 'pending', id );
	}
	// show the panel
	showPrebookPopup();
	// kick off the actual request to confirm the shipments (without actually booking them)
	doPrebookShipment(0);		
	// don't submit the form
	return false;
}


function initShippingAddressPopup() {
	//document.getElementById('shippingAddressPopup').style.display = '';
	addressBox = new YAHOO.widget.Panel("shippingAddressPopup",  
											{
											  width:"518px", 
											  height:"520px", 
											  fixedcenter:false, 
											  close:false, 
											  draggable:false, 
											  modal:false,
											  visible:false,
											  underlay:"none",
											  effect:{effect:YAHOO.widget.ContainerEffect.FADE, duration:0.5} 
											} 
										);

	addressBox.render(document.body);
	if ( showShippingAddressPopupOnLoad ) {
		doShowShippingAddressPopup();
	}
}

function doShowShippingAddressPopup() {
	document.location.hash = 'quote';
	populateCollectionAddresses( currentQuoteRowId );
	document.getElementById('shippingAddressPopup').style.display = '';
	changeShippingAddressTab('from');
	// reset the postcode "results" drop-down
	var shipToResults = document.getElementById('epcAddressList_ShipTo');
	var shipFromResults = document.getElementById('epcAddressList_ShipFrom');
	removeAllOptions( shipToResults );
	removeAllOptions( shipFromResults );
	var opt1 = new Option( 'Enter Post Code', '' );
	var opt2 = new Option( 'Enter Post Code', '' );
	addOptionToSelect( shipToResults, opt1 );
	addOptionToSelect( shipFromResults, opt2 );
	shipToResults.disabled = true;
	shipFromResults.disabled = true;
	// validate the addresses
	validateShippingAddress('From');
	validateShippingAddress('To');
	addressBox.cfg.setProperty( 'context', [ currentQuoteRowButton, 'tl', 'bl' ] );
	addressBox.show();
}

function showShippingAddressPopup( rowId, el ) {
	currentQuoteRowId = rowId;
	currentQuoteRowButton = el;
	if ( typeof addressBox != "undefined" ) {
		doShowShippingAddressPopup();
	} else {
		showShippingAddressPopupOnLoad = true;
	}
}

function hideShippingAddressPopup() {
	if( typeof addressBox != "undefined" ) {
		addressBox.hide();
	}
}

function checkShipToPostcode( countryCode ) {
	if ( countryCode == 'GB' ) {
		document.getElementById('shipTo_findAddressBtn').style.display = '';
		document.getElementById('addressListContainer_To').style.display = '';
	} else {
		document.getElementById('shipTo_findAddressBtn').style.display = 'none';
		document.getElementById('addressListContainer_To').style.display = 'none';
	}
}

function changeCountry( countryCode, countryPrefix ) {
	if ( ( countryCode == 'NO' ) || ( countryCode == 'CH' ) || ( countryCode == 'TR' ) || ( countryCode == 'RU' ) ) {
		alert( 'For deliveries to Turkey, Norway, Switzerland and Russia please email details to sales@worldwide-parcelservices.co.uk and we\'ll reply with a quote as soon as possible. All other countries can be booked online.' );
		document.getElementById( countryPrefix + '_shipTo_country' ).value = 'GB';
	} else {
		shipToCountry = countryCode;
		document.getElementById( 'cmsServicesShipping_shipTo_state' ).selectedIndex = 0;
		document.getElementById( 'cmsServicesShipping_shipTo_state_other' ).value = '';
		if ( ( countryCode == 'IE' ) || ( countryCode == 'CA' ) || ( countryCode == 'US' ) ) {
			// state is required, so display it
			document.getElementById( 'shippingAddressStateContainer' ).style.display = '';
		} else {
			// state not required, hide it
			document.getElementById( 'shippingAddressStateContainer' ).style.display = 'none';
		}
		if ( countryPrefix == 'qq' ) {
			var selectTo = document.getElementById( 'qq_shipTo_country' );
			var countryTo = selectTo.options[ selectTo.selectedIndex ].text;
			document.getElementById( 'qq_shipTo_country_long' ).value = countryTo.replace('*','');
			if ( selectTo.value == 'IE' ) {
				document.getElementById('qq_postcode').value = 'BT 1';
			} else {
				document.getElementById('qq_postcode').value = 'M 1';
			}
		}
	}
}

function changeState( val ) {
	document.getElementById( 'shippingAddressStateOtherContainer' ).style.display = ( val == 'other' ) ? '' : 'none';
}

function changeResidential( val, section ) {
	var p = document.getElementById( section + '_company_section' );
	if ( val == 1 ) {
		p.style.display = 'none';
	} else {
		p.style.display = '';
	}
}


function checkPostcode( postcode, addressType ) {
	if ( ( addressType == 'shipTo' && shipToCountry == 'US' ) || ( addressType == 'shipFrom' && shipFromCountry == 'US' ) ) {
		first2Characters = postcode.substr(0,2);
		if ( isNaN( first2Characters ) ) {
			// they've entered a postcode like FL30091
			document.getElementById('cmsServicesShipping_'+addressType+'_state').value = first2Characters;
			if ( document.getElementById('cmsServicesShipping_'+addressType+'_state').selectedIndex > 0 ) {
				postcode = trim(postcode.substr(2,(postcode.length - 2)));
				document.getElementById('cmsServicesShipping_'+addressType+'_postcode').value = postcode;
				alert( 'Please only enter the numeric part of a US zip code.  The state has been automatically selected for you.' );
			} else {
				document.getElementById('cmsServicesShipping_'+addressType+'_state').selectedIndex = 0;
			}
		}
	}
}


function initPrebookPopup() {
	document.getElementById('prebookPopup').style.display = '';
	prebookBox = new YAHOO.widget.Panel("prebookPopup",  
											{
											  width:"560px", 
											  height:"296px", 
											  fixedcenter:true, 
											  close:false, 
											  draggable:false, 
											  modal:true,
											  visible:false,
											  underlay:"none",
											  effect:{effect:YAHOO.widget.ContainerEffect.FADE, duration:0.5} 
											} 
										);

	prebookBox.render(document.body);
}

function showPrebookPopup() {
	if( typeof prebookBox != "undefined" ) {
		prebookBox.show();
	}
}

function hidePrebookPopup() {
	if( typeof prebookBox != "undefined" ) {
		prebookBox.hide();
	}
}

function initQuoteTable() {
	initShippingAddressPopup();
	initPrebookPopup();
	addToolTipToElement( '#addShipmentIcon', shipmentTooltipContent );
}

function selectPreviousFromAddress( addressId ) {
	var address = previousFromAddresses[0][addressId];
	populateCollectionAddress( 'From', address );
}

function selectPreviousToAddress( addressId ) {
	var address = previousToAddresses[0][addressId];
	populateCollectionAddress( 'To', address );
}


function initOverValuePopup() {
	document.getElementById('overValuePopup').style.display = '';
	overValueBox = 
			new YAHOO.widget.Panel("overValuePopup",  
											{
											  width:"250px",
											  height:"200px",
											  fixedcenter:true, 
											  close:false, 
											  draggable:false, 
											  modal:true,
											  visible:false,
											  underlay:"none",
											  effect:{effect:YAHOO.widget.ContainerEffect.FADE, duration:0.5} 
											} 
										);

	overValueBox.render(document.body);
}

function hideOverValuePopup() {
	if( typeof overValueBox != "undefined" )
		overValueBox.hide();
}

function showOverValuePopup() {
	if( typeof overValueBox != "undefined" ) {
		overValueBox.show();
	}
}

YAHOO.util.Event.addListener( window, "load", initOverValuePopup );