var lb_loggingEnabled = false;
var lb_currentControlFocus = null;
var lb_formDataSessionId = null;
//var lb_testing = true;
var lb_sessionStartUrlBase = "forms.leadbay.co.uk/FormData/SessionStart.aspx";
var lb_sessionStepUrlBase = "forms.leadbay.co.uk/FormData/SessionStep.aspx";
var lb_sessionStartUrlBase_Test = "testforms.leadbay.co.uk/FormData/SessionStart.aspx";
var lb_sessionStepUrlBase_Test = "testforms.leadbay.co.uk/FormData/SessionStep.aspx";
var mfp_getBrokerUrl = "www.mortgagesforprofessionals.com/formData/getBroker";
var mfp_submitUrl = "www.mortgagesforprofessionals.com/formData/submit";

/* ==================================================================================
   UTILITY FUNCTIONS
   ================================================================================== */

function sessionStartCallback( callbackData ){
	if( callbackData.sessionId )
	{
		lb_formDataSessionId = callbackData.sessionId;
	}
}

function sessionStartPing( formTypeRc, leadTypeRc )
{
		var lb_sessionStartUrl = (lb_testing ? lb_sessionStartUrlBase_Test : lb_sessionStartUrlBase);
		lb_sessionStartUrl += "?r=" + base64Encode(document.referrer);
		lb_sessionStartUrl += "&p=" + window.location.href;
		lb_sessionStartUrl += "&ft=" + formTypeRc;
		lb_sessionStartUrl += "&lt=" + leadTypeRc;
		lb_sessionStartUrl += "&ai=" + (lb_testing ? lb_testAffiliateId : lb_affiliateId);
		lb_sessionStartUrl += "&s=STEP1";
		lb_sessionStartUrl += "&w=" + screen.width;
		lb_sessionStartUrl += "&h=" + screen.height;
		lb_sessionStartUrl += "&bw=" + document.body.clientWidth;
		lb_sessionStartUrl += "&bh=" + document.body.clientHeight;
//		log(lb_sessionStartUrl);
		remoteJson({"uri": getPageProtocol() + lb_sessionStartUrl});
}

function sessionStepPing( stepRc, converted, additionalParameters )
{
	if( lb_formDataSessionId )
	{
		var lb_sessionStepUrl = (lb_testing ? lb_sessionStepUrlBase_Test : lb_sessionStepUrlBase);
		lb_sessionStepUrl += "?id=" + lb_formDataSessionId;
		lb_sessionStepUrl += "&s=" + stepRc;
		lb_sessionStepUrl += "&c=" + converted;

		if( additionalParameters )
		{
			lb_sessionStepUrl += additionalParameters;
		}

//		log(lb_sessionStepUrl);
		remoteJson({"uri": getPageProtocol() + lb_sessionStepUrl});
	}
}

// Adds commas into a number string
function addCommas( numberString )
{
	numberString += '';
	x = numberString.replace(/[^0-9.\-]*/g, "").split('.');
	x1 = x[0];
	x2 = x.length > 1 ? '.' + x[1] : '';
	var rgx = /(\d+)(\d{3})/;
	while (rgx.test(x1))
	{
		x1 = x1.replace(rgx, '$1' + ',' + '$2');
	}

	return x1 + x2;
}

function addCommasToNumberTextbox()
{
	this.controls[0].value = addCommas( this.controls[0].value );
}

function getIntegerFromTextbox( control )
{
	return parseInt( control.value.replace(/[^0-9]*/g, ""), 10 );
}

function getFloatFromTextbox( control )
{
	return parseFloat( control.value.replace(/[^0-9.]*/g, ""), 10 );
}

function getPageProtocol()
{
	if( window.location.protocol.indexOf("https") >= 0 )
	{
		return "https://";
	}

	return "http://";
}

function generateGuid()
{
	var guid = '';

	for (var i = 1; i <= 32; i++) 
	{ 
		var n = Math.floor(Math.random() * 16.0).toString(16); 
		guid += n; 
		
		if ((i == 8) || (i == 12) || (i == 16) || (i == 20)) guid += "-"; 
	}

	return guid;
}

function remoteJson(listener)
{
	if (listener && listener.uri)
	{
		var script = document.createElement("script"); // new script element.
		script.setAttribute("type", "text/javascript");
		script.setAttribute("id", "remotejson" + generateGuid());

		if( listener.uri.indexOf("?") > 0 )
		{
			script.setAttribute("src", listener.uri + "&nocache=" + generateGuid() );
		}
		else
		{
			script.setAttribute("src", listener.uri + "?nocache=" + generateGuid() );
		}

		document.getElementsByTagName("head")[0].appendChild(script);
	}
}

function log( message )
{
	if( lb_loggingEnabled ) $('LB_Log').innerHTML += message + "<br />";
}

// Determines if an element is rendered on the page
function isVisible( object )
{
	return (object.offsetWidth > 0 && object.offsetHeight > 0);
}

// addEvent and removeEvent, designed by Aaron Moore
function addEvent(element, listener, handler)
{
	//if the system is not set up, set it up, and
	// store any outside script's event registration in the first handler slot
	if(typeof element[listener] != 'function' || 
	typeof element[listener + '_num'] == 'undefined'){
		element[listener + '_num'] = 0;
		if(typeof element[listener] == 'function'){
			element[listener + 0] = element[listener];
			element[listener + '_num']++;
		}
		element[listener] = function(e){
			var r = true;
			e = (e) ? e : window.event;
			for(var i = 0; i < element[listener + '_num']; i++)
				if(element[listener + i](e) === false) r = false;
			return r;
		}
	}
	//if handler is not already stored, assign it
	for(var i = 0; i < element[listener + '_num']; i++)
		if(element[listener + i] == handler) return;
	element[listener + element[listener + '_num']] = handler;
	element[listener + '_num']++;
}

var urlSafeBase64Characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789*-.";

function base64Encode( input )
{
	var output = "";
	var chr1, chr2, chr3;
	var enc1, enc2, enc3, enc4;
	var i = 0;

	do
	{
		chr1 = input.charCodeAt(i++);
		chr2 = input.charCodeAt(i++);
		chr3 = input.charCodeAt(i++);

		enc1 = chr1 >> 2;
		enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
		enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
		enc4 = chr3 & 63;

		if (isNaN(chr2))
		{
			enc3 = enc4 = 64;
		}
		else if (isNaN(chr3))
		{
			enc4 = 64;
		}

		output = output + urlSafeBase64Characters.charAt(enc1) + urlSafeBase64Characters.charAt(enc2) + urlSafeBase64Characters.charAt(enc3) + urlSafeBase64Characters.charAt(enc4);
	}
	while (i < input.length);

	return output;
}

/* ==================================================================================
   "HAS VALUE" FUNCTIONS FOR BUILT-IN TYPES
   ================================================================================== */

function textboxHasValueTest( controls )
{
	if( controls[0].value.length > 0 )
	{
		return true;
	}
	else
	{
		return false;
	}
}

/* ==================================================================================
   VALIDATION SETUP FUNCTIONS
   ================================================================================== */

function addValidation( controls, validations, labelNode, errorAdviceNode, trimData, stripNonNumericCharacters, stopOnFirstError, submitButton, trackFocus, validateOnlyIfAllVisible, captureClickEventForSelectElement, extraValidators, successValidators, failureValidators, afterValidationFunctions, hasValueFunction, requiredValueValidators, beforeValidationFunctions )
{
	var validatorData = {eventControl: null, controls: controls, validations: validations, labelNode: labelNode, errorAdviceNode: errorAdviceNode, trimData: trimData, stripNonNumericCharacters: stripNonNumericCharacters, stopOnFirstError: stopOnFirstError, validateOnlyIfAllVisible: validateOnlyIfAllVisible, extraValidators: extraValidators, successValidators: successValidators, failureValidators: failureValidators, afterValidationFunctions: afterValidationFunctions, hasValueFunction: hasValueFunction, requiredValueValidators: requiredValueValidators, beforeValidationFunctions: beforeValidationFunctions };

	for( var controlIndex = 0 ; controlIndex < controls.length ; controlIndex++ )
	{
		validatorData.eventControl = controls[controlIndex];

		var subControls = document.getElementsByName( controls[controlIndex].name );
		
		for( var subControlIndex = 0 ; subControlIndex < subControls.length ; subControlIndex++ )
		{
			var eventTypeToCatch = 'blur';
			switch( subControls[subControlIndex].type.substring(0,7) )
			{
				case 'radio':
				{
					eventTypeToCatch = 'click';
					break;
				}
				
				case 'select-':
				{
					if( captureClickEventForSelectElement )
					{
						eventTypeToCatch = 'click';
					}
					break;
				}
			}

			addEvent( subControls[subControlIndex], 'on' + eventTypeToCatch, validateFromEvent.bindAsEventListener( validatorData ) );

			if( trackFocus )
			{
				addEvent(subControls[subControlIndex], 'onfocus', hasFocusEvent.bindAsEventListener( validatorData ) );
			}

			if( submitButton )
			{
				if( !submitButton.validators )
				{
					submitButton.validators = new Array();
				}
				
				submitButton.validators.extend([validatorData]);
			}
		}
	}
	validatorData.eventControl = controls[0];
	return validatorData;
}

function trackFocus( controls )
{
	for( var controlIndex = 0 ; controlIndex < controls.length ; controlIndex++ )
	{
		controls[controlIndex].addEvent('focus', hasFocusEvent.bindAsEventListener() );
	}
}


function validateMultiple( event )
{
	var errors = 0;

	if( event.target.validators )
	{
		for( var i = 0 ; i < event.target.validators.length ; i++ )
		{
			errors += delayedValidate.attempt( event, event.target.validators[i] );
		}
	}

	return errors == 0;
}

function validateFromEvent( event )
{
	var event = new Event(event);

	delayedValidate.delay( 10, this, event );
}

function delayedValidate( event )
{
	if( this.beforeValidationFunctions )
	{
		for( var i = 0 ; i < this.beforeValidationFunctions.length ; i++ )
		{
			this.beforeValidationFunctions[i].attempt( event, this );
		}
	}	

	// If this validator relies on another field on the page being filled out, then this section checks for that
	if( this.requiredValueValidators )
	{
		// Loop round all the validators that need checking before this validator can run
		for( var validatorIndex = 0 ; validatorIndex < this.requiredValueValidators.length ; validatorIndex++ )
		{
			// Check if the validator incorporates a "hasValue" function
			if( this.requiredValueValidators[validatorIndex].hasValueFunction )
			{
				// It does, so run it and see if it actually has a value in the other field
				if( !this.requiredValueValidators[validatorIndex].hasValueFunction( this.requiredValueValidators[validatorIndex].controls ) )
				{
					// No value, so we can't continue - clear out any existing error message and return
					this.errorAdviceNode.innerHTML = '&nbsp;';
					this.errorAdviceNode.style.visibility = 'hidden';
					this.labelNode.className = this.labelNode.className.replace(/ LB_ErrorLabel/gi, '').replace(/LB_ErrorLabel/gi, '');
					return 0;
				}
			}
		}
	}

	for( var controlIndex = 0 ; controlIndex < this.controls.length ; controlIndex++ )
	{
		if( this.trimData && this.controls[controlIndex].type == 'text' )
		{
			this.controls[controlIndex].value = this.controls[controlIndex].value.trim();
		}

		if( this.stripNonNumericCharacters && this.controls[controlIndex].type == 'text' )
		{
			this.controls[controlIndex].value = this.controls[controlIndex].value.replace(/[^0-9]*/g, "");
		}
		
		if( this.validateOnlyIfAllVisible && !isVisible( this.controls[controlIndex] ) )
		{
			return 0;
		}
	}

	for( var validationIndex = 0 ; validationIndex < this.validations.length ; validationIndex++ )
	{
		var validationState = this.validations[validationIndex].validator( event, this.controls, this.validations[validationIndex], this.extraValidators );

		if( validationState.errorCode >= 0 )
		{
			var errorMessage = '';
	
			if( validationState.errorMessage )
			{
				errorMessage = validationState.errorMessage;
			}
			else
			{
				errorMessage = this.validations[validationIndex].errorMessages[validationState.errorCode];
			}

			setControlToErrorState( this, errorMessage );

			if( this.stopOnFirstError )
			{
				if( this.afterValidationFunctions )
				{
					for( var i = 0 ; i < this.afterValidationFunctions.length ; i++ )
					{
						this.afterValidationFunctions[i].attempt( event, this );
					}
				}			

				return 1;
			}
		}
		else
		{
			this.errorAdviceNode.innerHTML = '&nbsp;';
			this.errorAdviceNode.style.visibility = 'hidden';
			this.labelNode.className = this.labelNode.className.replace(/ LB_ErrorLabel/gi, '').replace(/LB_ErrorLabel/gi, '');
		}
	}

	if( this.successValidators )
	{
		for( var i = 0 ; i < this.successValidators.length ; i++ )
		{
			delayedValidate.attempt( event, this.successValidators[i] );
		}
	}

	if( this.afterValidationFunctions )
	{
		for( var i = 0 ; i < this.afterValidationFunctions.length ; i++ )
		{
			this.afterValidationFunctions[i].attempt( event, this );
		}
	}

	return 0;
}

function setControlToErrorState( validatorData, errorMessage )
{
	validatorData.errorAdviceNode.innerHTML = errorMessage;
	validatorData.errorAdviceNode.style.visibility = 'visible';

	if( validatorData.labelNode.className.indexOf('LB_ErrorLabel') < 0 )
	{
		validatorData.labelNode.className += ' LB_ErrorLabel';
	}
}


function setCurrentControlFocus( control )
{
	lb_currentControlFocus = control;
}

function hasFocusEvent( event )
{
	var event = new Event(event);
	setCurrentControlFocus( event.target );
}

function getRadioButtonListSelectedValue(name)
{
	var controls = document.getElementsByName(name);
	
	for( var i = 0 ; i < controls.length ; i++ )
	{
		if( controls[i].checked )
		{
			return controls[i].value;
		}
	}
	
	return null;
}

function textboxHasValueValidator( event, controls, validation, extraValidators )
{
	if( controls[0].value.length < 1 )
	{
		return {errorCode: 0};
	}
	
	return {errorCode: -1};
}

function radioButtonListHasValueValidator( event, controls, validation, extraValidators )
{
	var radioButtonListValue = getRadioButtonListSelectedValue( controls[0].name );

	if( radioButtonListValue == null || radioButtonListValue.length <= 0 || radioButtonListValue == "" )
	{
		return {errorCode: 0};
	}

	return {errorCode: -1};
}

function selectHasValueValidator( event, controls, validation, extraValidators )
{
	if( controls[0].value == null || controls[0].value.length <= 0 || controls[0].value == "" )
	{
		return {errorCode: 0};
	}

	return {errorCode: -1};
}

/* ==================================================================================
   VALIDATORS - GENERIC
   ================================================================================== */

function EmailAddressValidator( event, controls, validation, extraValidators )
{
	if( controls[0].value.test("^([-\\w\\.!#\\$%\+`'_]+@[-A-Za-z0-9]+(\\.[-A-Za-z0-9\]{2,})+)$") )
	{
		return {errorCode: -1};
	}

	return {errorCode: 0};
}

function RegexValidator( event, controls, validation, extraValidators )
{
	if( controls[0].value.test(validation.validationData) )
	{
		return {errorCode: -1};
	}

	return {errorCode: 0};
}

function dateGroupValidator( event, controls, validation, extraValidators )
{
	var validate = true;

	// If the eventControl is equal to the controlWithFocus it means the user has clicked on a control that doesn't fire our
	// special onfocus event, therefore it's not one of the other drop-downs in the group and we definitely need to validate
	
	// If it isn't equal then we need to check if it's some other random control or one of the other 2 in the date group
	if( lb_currentControlFocus != event.target )
	{
		// Search the other date drop-downs to see if it's one of them that now has focus
		for( var i = 0 ; i < controls.length ; i++ )
		{
			if( controls[i] == lb_currentControlFocus )
			{
				// It is one of them, so don't validate it yet
				validate = false;
			}
		}
	}

	if( validate )
	{
		// This loop checks to see there is something selected in each of the 3 drop-downs in the date group
		for( var i = 0 ; i < controls.length ; i++ )
		{
			if( controls[i].value.length < 1 || controls[i].value == "" )
			{
				// One of the drop-downs is not selected, so return that error
				return {errorCode: 0};
			}
		}

		// Get the date as a string from the group of SELECTs
		var dateString = controls[0].value + controls[1].value + controls[2].value;

		if ( dateString.match(/^[0-3][0-9][01][0-9][12][0-9]{3}$/) == null )
		{
			return {errorCode: 1};
		}
		
		// Extract the separate date components from the string
		var day = parseInt( dateString.substring(0,2), 10 );
		var month = parseInt( dateString.substring(2,4), 10 );
		var year = parseInt( dateString.substring(4,8), 10 );
	
		// Check if the day is valid for the month (e.g. 30th Feb, 31st April is never valid)
		if( daysInMonth( month, year ) < day )
		{
			return {errorCode: 1};
		}
	}
	
	return {errorCode: -1};
}

function daysInFebruary(year)
{
	// February has 29 days in any year evenly divisible by four,
	// EXCEPT for centurial years which are not also divisible by 400.
	return (((year % 4 == 0) && ( (!(year % 100 == 0)) || (year % 400 == 0))) ? 29 : 28 );
}

function daysInMonth( month, year )
{
	// April, June, September, November
	if( month == 4 || month == 6 || month == 9 || month == 11 )
	{
		return 30;
	}
	else if( month == 2 ) // February
	{
		return daysInFebruary( year );
	}
	else // January, March, May, July, August, October, December
	{
		return 31;
	}
}

// Checks a date group value is inside an age range. Expects the date to be validated already.
function ageValidator( event, controls, validation, extraValidators )
{
	// Get the date as a string from the group of SELECTs
	var dateString = controls[0].value + controls[1].value + controls[2].value;

	// Extract the separate date components from the string
	var day = parseInt( dateString.substring(0,2), 10 );
	var month = parseInt( dateString.substring(2,4), 10 );
	var year = parseInt( dateString.substring(4,8), 10 );

	// Get current date
	var now = new Date();
	var nowYear = now.getFullYear();
	var nowMonth = now.getMonth() + 1; // +1 converts from JavaScript month numbering (0-11)
	var nowDay = now.getDate();

	var age = nowYear - year;

	// Decrease age if we're too late in the year (before day and month of birth)
	if ( ( month > nowMonth ) || ( month == nowMonth && day > nowDay ) )
	{
		age --;
	}

//	var minAge = validatorData.split(',')[0].length > 0 ? validatorData.split(',')[0] : -1;
//	var maxAge = validatorData.split(',')[1].length > 0 ? validatorData.split(',')[1] : 1000;

	if( age < validation.validationData.minAge )
	{
		return {errorCode: 0};
	}

	if( age > validation.validationData.maxAge )
	{
		return {errorCode: 1};
	}

	return {errorCode: -1};
}

function GreaterThanValueValidator( event, controls, validation, extraValidators )
{
	if( parseInt( controls[0].value, 10 ) <= validation.validationData.minValue )
	{
		return {errorCode: 0};
	}

	return {errorCode: -1};
}

function LessThanValueValidator( event, controls, validation, extraValidators )
{
	if( parseInt( controls[0].value, 10 ) >= validation.validationData.maxValue )
	{
		return {errorCode: 0};
	}

	return {errorCode: -1};
}

function ValidIntegerValidator( event, controls, validation, extraValidators )
{
	if( isNaN( parseInt( controls[0].value, 10 ) ) )
	{
		return {errorCode: 0};
	}

	return {errorCode: -1};
}

var UkPhoneNumberErrorMessages = ["Enter without country code", "Should be 10 or 11 digits", "Should start with a zero", "06 / 070 numbers not accepted", "Enter home, work or mobile number"];

function UkPhoneNumberValidator( event, controls, validation, extraValidators )
{
	// Get the phone number as a string from the text box
	var telephoneNumber = controls[0].value;

	// Don't allow country codes to be included (assumes a leading "+")
	if ( telephoneNumber.match(/^\+.+$/) )
	{
		return {errorCode: 0};
	}

	// Remove everything but numeric digits from the telephone number to help validation
	telephoneNumber = telephoneNumber.replace(/[^0-9]*([0-9]*)/g, "$1");

	// Now check that it is 10 or 11 digits long
	if( telephoneNumber.match(/^[0-9]{10,11}$/) == null )
	{
		return {errorCode: 1};
	}

	// Now check that the first digit is 0
	if ( telephoneNumber.match(/^0[0-9]{9,10}$/) == null )
	{
		return {errorCode: 2};
	}

	// Finally check that the telephone number is appropriate.
	if ( telephoneNumber.match(/^(06|070)[0-9]+$/) )
	{
		return {errorCode: 3};
	}

	// Check that the telephone number is appropriate.
	if (telephoneNumber.match(/^(01|02|03|05|07|08)[0-9]+$/) == null )
	{
		return {errorCode: 4};
	}

	// Check for too many repeating digits
	if (telephoneNumber.match(/^\d*(\d)\1{7}\d*$/) )
	{
		return {errorCode: 4};
	}

	return {errorCode: -1};
}

var postcodeOutcodes = new Array();
postcodeOutcodes[0]="AB";
postcodeOutcodes[1]="DG";
postcodeOutcodes[2]="DD";
postcodeOutcodes[3]="FK";
postcodeOutcodes[4]="EH";
postcodeOutcodes[5]="KY";
postcodeOutcodes[6]="KA";
postcodeOutcodes[7]="IV";
postcodeOutcodes[8]="KW";
postcodeOutcodes[9]="PA";
postcodeOutcodes[10]="PH";
postcodeOutcodes[11]="ML";
postcodeOutcodes[12]="HS";
postcodeOutcodes[13]="ZE";
postcodeOutcodes[14]="CF";
postcodeOutcodes[15]="LD";
postcodeOutcodes[16]="LL";
postcodeOutcodes[17]="NP";
postcodeOutcodes[18]="SA";
postcodeOutcodes[19]="SY";
postcodeOutcodes[20]="BD";
postcodeOutcodes[21]="DH";
postcodeOutcodes[22]="DL";
postcodeOutcodes[23]="DN";
postcodeOutcodes[24]="HD";
postcodeOutcodes[25]="HG";
postcodeOutcodes[26]="HU";
postcodeOutcodes[27]="HX";
postcodeOutcodes[28]="LN";
postcodeOutcodes[29]="LS";
postcodeOutcodes[30]="NE";
postcodeOutcodes[31]="SR";
postcodeOutcodes[32]="TS";
postcodeOutcodes[33]="WF";
postcodeOutcodes[34]="YO";
postcodeOutcodes[35]="BB";
postcodeOutcodes[36]="BL";
postcodeOutcodes[37]="CA";
postcodeOutcodes[38]="CH";
postcodeOutcodes[39]="CW";
postcodeOutcodes[40]="FY";
postcodeOutcodes[41]="LA";
postcodeOutcodes[42]="M";
postcodeOutcodes[43]="OL";
postcodeOutcodes[44]="PR";
postcodeOutcodes[45]="SK";
postcodeOutcodes[46]="TF";
postcodeOutcodes[47]="WA";
postcodeOutcodes[48]="WN";
postcodeOutcodes[49]="B";
postcodeOutcodes[50]="CV";
postcodeOutcodes[51]="DE";
postcodeOutcodes[52]="DY";
postcodeOutcodes[53]="LE";
postcodeOutcodes[54]="NG";
postcodeOutcodes[55]="NN";
postcodeOutcodes[56]="ST";
postcodeOutcodes[57]="WS";
postcodeOutcodes[58]="WV";
postcodeOutcodes[59]="AL";
postcodeOutcodes[60]="CB";
postcodeOutcodes[61]="CM";
postcodeOutcodes[62]="CO";
postcodeOutcodes[63]="EN";
postcodeOutcodes[64]="IG";
postcodeOutcodes[65]="IP";
postcodeOutcodes[66]="LU";
postcodeOutcodes[67]="MK";
postcodeOutcodes[68]="NR";
postcodeOutcodes[69]="PE";
postcodeOutcodes[70]="RM";
postcodeOutcodes[71]="SG";
postcodeOutcodes[72]="SS";
postcodeOutcodes[73]="WD";
postcodeOutcodes[74]="BA";
postcodeOutcodes[75]="BH";
postcodeOutcodes[76]="BS";
postcodeOutcodes[77]="DT";
postcodeOutcodes[78]="EX";
postcodeOutcodes[79]="GL";
postcodeOutcodes[80]="HR";
postcodeOutcodes[81]="PL";
postcodeOutcodes[82]="TA";
postcodeOutcodes[83]="TQ";
postcodeOutcodes[84]="TR";
postcodeOutcodes[85]="WR";
postcodeOutcodes[86]="GU";
postcodeOutcodes[87]="HA";
postcodeOutcodes[88]="HP";
postcodeOutcodes[89]="OX";
postcodeOutcodes[90]="PO";
postcodeOutcodes[91]="RG";
postcodeOutcodes[92]="SL";
postcodeOutcodes[93]="SN";
postcodeOutcodes[94]="SO";
postcodeOutcodes[95]="SP";
postcodeOutcodes[96]="UB";
postcodeOutcodes[97]="BN";
postcodeOutcodes[98]="BR";
postcodeOutcodes[99]="CR";
postcodeOutcodes[100]="CT";
postcodeOutcodes[101]="DA";
postcodeOutcodes[102]="KT";
postcodeOutcodes[103]="ME";
postcodeOutcodes[104]="RH";
postcodeOutcodes[105]="SM";
postcodeOutcodes[106]="TN";
postcodeOutcodes[107]="TW";
postcodeOutcodes[108]="E";
postcodeOutcodes[109]="EC";
postcodeOutcodes[110]="N";
postcodeOutcodes[111]="NW";
postcodeOutcodes[112]="SE";
postcodeOutcodes[113]="SW";
postcodeOutcodes[114]="W";
postcodeOutcodes[115]="WC";
postcodeOutcodes[116]="G";
postcodeOutcodes[117]="TD";
postcodeOutcodes[118]="GY";
postcodeOutcodes[119]="JE";
postcodeOutcodes[120]="BT";
postcodeOutcodes[121]="IM";
postcodeOutcodes[122]="S";
postcodeOutcodes[123]="L";

function postcodeTest( postcode )
{
	// Permitted letters depend upon their position in the postcode.
	var alpha1 = "[abcdefghijklmnoprstuwyz]";                       // Character 1
	var alpha2 = "[abcdefghklmnopqrstuvwxy]";                       // Character 2
	var alpha3 = "[abcdefghjkstuw]";                                // Character 3
	var alpha4 = "[abehmnprvwxy]";                                  // Character 4
	var alpha5 = "[abdefghjlnpqrstuwxyz]";                          // Character 5

	// Array holds the regular expressions for the valid postcodes
	var pcexp = new Array ();

	// Expression for postcodes: AN NAA, ANN NAA, AAN NAA, and AANN NAA
	pcexp.push (new RegExp ("^(" + alpha1 + "{1}" + alpha2 + "?[0-9]{1,2})(\\s*)([0-9]{1}" + alpha5 + "{2})$","i"));
	
	// Expression for postcodes: ANA NAA
	pcexp.push (new RegExp ("^(" + alpha1 + "{1}[0-9]{1}" + alpha3 + "{1})(\\s*)([0-9]{1}" + alpha5 + "{2})$","i"));

	// Expression for postcodes: AANA  NAA
	pcexp.push (new RegExp ("^(" + alpha1 + "{1}" + alpha2 + "?[0-9]{1}" + alpha4 +"{1})(\\s*)([0-9]{1}" + alpha5 + "{2})$","i"));

	// Assume we're not going to find a valid postcode
	var valid = false;
	
	// Check the string against the types of post codes
	for ( var i=0; i<pcexp.length; i++ )
	{
		if (pcexp[i].test(postcode))
		{
		  // The post code is valid - split the post code into component parts
		  pcexp[i].exec(postcode);
		  
		  // Copy it back into the original string, converting it to uppercase and
		  // inserting a space between the inward and outward codes
		  postcode = RegExp.$1.toUpperCase() + " " + RegExp.$3.toUpperCase();
		  
		  // Load new postcode back into the form element
		  valid = true;
		  
		  // Remember that we have found that the code is valid and break from loop
		  break;
		}
	}
  
	if( valid )
	{
		var postcodeOutcode = '';
		
		// Pull just the Outcode from the Postcode
		if( isFinite( postcode.charAt(1) ) )
		{
			postcodeOutcode = postcode.charAt(0);
		}
		else
		{
			postcodeOutcode = postcode.substring(0, 2);
		}

		// Check the Outcode is in the list
		for( index in postcodeOutcodes )
		{
			if( postcodeOutcode == postcodeOutcodes[index] )
			{
				// Appears valid
				return -1;
			}
		}
	}

	// Is invalid
	return 0;
}

function PostcodeValidator( event, controls, validation, extraValidators )
{
	// Get the postcode as a string from the text box
	var postcode = controls[0].value;

	switch( postcodeTest( postcode ) )
	{
		case 0:
			return {errorCode: 0};
		case -1:
			return {errorCode: -1};
	}
}

// PACKER here: http://dean.edwards.name/packer/

var lb_lastPostcodeChecked = null;

var lb_detailedMortgageTypes = { remortgage: {ltvPercent: 100.0, id: 1}, firstTimeBuyer: {ltvPercent: 110.0, id: 2}, selfCertifyRemortgage: {ltvPercent: 95.0, id: 3}, selfCertifyOther: {ltvPercent: 95.0, id: 4}, buyToLet: {ltvPercent: 95.0, id: 5}, purchase: {ltvPercent: 100.0, id: 6}, adverseRemortgage: {ltvPercent: 95.0, id: 7}, adverseOther: {ltvPercent: 95.0, id: 8} };

// URLs for web services
var lb_ajaxBrokerSearchUrl = 'mortgages.leadbay.co.uk/webservice/broker_search_webservice.aspx';
var lb_ajaxProcessLeadUrl = 'mortgages.leadbay.co.uk/webservice/process_lead_webservice.aspx';

var lb_ajaxTestBrokerSearchUrl = 'testmortgages.leadbay.co.uk/webservice/broker_search_webservice.aspx';
var lb_ajaxTestProcessLeadUrl = 'testmortgages.leadbay.co.uk/webservice/process_lead_webservice.aspx';

/* ==================================================================================
   MORTGAGE FORM VALIDATION SETUP
   ================================================================================== */

// Step 1
addValidation( [ $('LB_MortgageType') ], [{validator: radioButtonListHasValueValidator, validationData: null, errorMessages: ["Make a selection"]}], $('LB_MortgageType_Label'), $('LB_MortgageType_ErrorAdvice'), false, false, true, $('LB_Step1_NextButton'), true, true, false, null, null, null );
addValidation( [ $('LB_AmountToBorrow') ], [{validator: textboxHasValueValidator, validationData: null, errorMessages: ["Enter value, e.g. £225,500"]}, {validator: ValidIntegerValidator, validationData: null, errorMessages: ["Enter valid value"]}, {validator: GreaterThanValueValidator, validationData: {minValue: 24999}, errorMessages: ["Must be £25,000 or over"]}, {validator: LessThanValueValidator, validationData: {maxValue: 1000000000}, errorMessages: ["Must be under £1,000,000,000"]} ], $('LB_AmountToBorrow_Label'), $('LB_AmountToBorrow_ErrorAdvice'), true, true, true, $('LB_Step1_NextButton'), false, true, false, null, null, null, [addCommasToNumberTextbox] );
addValidation( [ $('LB_PropertyValue') ], [{validator: textboxHasValueValidator, validationData: null, errorMessages: ["Enter value, e.g. £250,000"]}, {validator: ValidIntegerValidator, validationData: null, errorMessages: ["Enter valid value"]}, {validator: GreaterThanValueValidator, validationData: {minValue: 24999}, errorMessages: ["Must be £25,000 or over"]}, {validator: LessThanValueValidator, validationData: {maxValue: 1000000000}, errorMessages: ["Must be under £1,000,000,000"]} ], $('LB_PropertyValue_Label'), $('LB_PropertyValue_ErrorAdvice'), true, true, true, $('LB_Step1_NextButton'), false, true, false, null, null, null, [addCommasToNumberTextbox] );

// Step 2
addValidation( [ $('LB_FirstTimeBuyer') ], [{validator: radioButtonListHasValueValidator, validationData: null, errorMessages: ["Make a selection"]}], $('LB_FirstTimeBuyer_Label'), $('LB_FirstTimeBuyer_ErrorAdvice'), false, false, true, $('LB_Step2_NextButton'), true, true, false, null, null, null );
addValidation( [ $('LB_SelfCertifyIncome') ], [{validator: radioButtonListHasValueValidator, validationData: null, errorMessages: ["Make a selection"]}], $('LB_SelfCertifyIncome_Label'), $('LB_SelfCertifyIncome_ErrorAdvice'), false, false, true, $('LB_Step2_NextButton'), true, true, false, null, null, null );

// Step 2b
var lb_amountToBorrowValidator2 = addValidation( [ $('LB_AmountToBorrow2') ], [{validator: textboxHasValueValidator, validationData: null, errorMessages: ["Enter value, e.g. £225,500"]}, {validator: ValidIntegerValidator, validationData: null, errorMessages: ["Enter valid value"]}, {validator: GreaterThanValueValidator, validationData: {minValue: 24999}, errorMessages: ["Must be £25,000 or over"]}, {validator: LessThanValueValidator, validationData: {maxValue: 5000000}, errorMessages: ["Must be under £5,000,000"]}, {validator: DetailedLtvValidator, validationData: $('LB_PropertyValue2'), errorMessages: ["Amount to borrow is more than ###MAXLTV###% of property value. Amend borrow amount or property value."]} ], $('LB_AmountToBorrow2_Label'), $('LB_AmountToBorrow2_ErrorAdvice'), true, true, true, $('LB_Step2b_NextButton'), false, false, false, null, null, null, [addCommasToNumberTextbox] );
addValidation( [ $('LB_PropertyValue2') ], [{validator: textboxHasValueValidator, validationData: null, errorMessages: ["Enter value, e.g. £250,000"]}, {validator: ValidIntegerValidator, validationData: null, errorMessages: ["Enter valid value"]}, {validator: GreaterThanValueValidator, validationData: {minValue: 24999}, errorMessages: ["Must be £25,000 or over"]}, {validator: LessThanValueValidator, validationData: {maxValue: 5000000}, errorMessages: ["Must be under £5,000,000"]}, {validator: FireAmountToBorrowValidator, validationData: $('LB_AmountToBorrow2'), errorMessages: null} ], $('LB_PropertyValue2_Label'), $('LB_PropertyValue2_ErrorAdvice'), true, true, true, $('LB_Step2b_NextButton'), false, false, false, [lb_amountToBorrowValidator2], null, null, [addCommasToNumberTextbox] );

// Step 3
addValidation( [ $('LB_FirstName') ], [{validator: textboxHasValueValidator, validationData: null, errorMessages: ["Enter first name"]}, {validator: RegexValidator, validationData: "^[-`'\\wÁáĆćÉéÍíĹĺŃńÓóŔŕŚśÚúÝýŹźÀàÈèÌìÒòÙùÂâĈĉÊêĜĝĤĥÎîĴĵÔôŜŝÛûŴŵŶŷÄäËëÏïÖöÜüŸÿßÃãẼẽĨĩÑñÕõŨũỸỹÇçĢģĶķĻļŅņŖŗŞşŢţĐđŮůǍǎČčĎďĚěǏǐĽľŇňǑǒŘřŠšŤťǓǔŽžĀāĒēĪīŌōŪūǢǣǖǘǚǜĂăĔĕĞğĬĭŎŏŬŭĊċĖėĠġİıŻżĄąĘęĮįǪǫŲųḌḍḤḥḶḷḸḹṂṃṆṇṚṛṜṝṢṣṬṭŁłŐőŰűĿŀĦħÐðÞþŒœÆæØøÅåƏə\\s]{2,50}$", errorMessages: ["Enter valid name"]}, {validator: RegexValidator, validationData: "^[\\D]{2,}$", errorMessages: ["Enter valid name"]} ], $('LB_FirstName_Label'), $('LB_FirstName_ErrorAdvice'), true, false, true, $('LB_Step2_NextButton'), false, false, false, null, null, null );
addValidation( [ $('LB_LastName') ], [{validator: textboxHasValueValidator, validationData: null, errorMessages: ["Enter last name"]}, {validator: RegexValidator, validationData: "^[-`'\\wÁáĆćÉéÍíĹĺŃńÓóŔŕŚśÚúÝýŹźÀàÈèÌìÒòÙùÂâĈĉÊêĜĝĤĥÎîĴĵÔôŜŝÛûŴŵŶŷÄäËëÏïÖöÜüŸÿßÃãẼẽĨĩÑñÕõŨũỸỹÇçĢģĶķĻļŅņŖŗŞşŢţĐđŮůǍǎČčĎďĚěǏǐĽľŇňǑǒŘřŠšŤťǓǔŽžĀāĒēĪīŌōŪūǢǣǖǘǚǜĂăĔĕĞğĬĭŎŏŬŭĊċĖėĠġİıŻżĄąĘęĮįǪǫŲųḌḍḤḥḶḷḸḹṂṃṆṇṚṛṜṝṢṣṬṭŁłŐőŰűĿŀĦħÐðÞþŒœÆæØøÅåƏə\\s]{2,50}$", errorMessages: ["Enter valid name"]}, {validator: RegexValidator, validationData: "^[\\D]{2,}$", errorMessages: ["Enter valid name"]} ], $('LB_LastName_Label'), $('LB_LastName_ErrorAdvice'), true, false, true, $('LB_Step2_NextButton'), false, false, false, null, null, null );
addValidation( [ $('LB_EmailAddress') ], [{validator: textboxHasValueValidator, validationData: null, errorMessages: ["Enter e-mail address"]}, {validator: EmailAddressValidator, validationData: null, errorMessages: ["Invalid e-mail address"]} ], $('LB_EmailAddress_Label'), $('LB_EmailAddress_ErrorAdvice'), true, false, true, $('LB_Step3_FinishButton'), false, false, false, null, null, null );
addValidation( [ $('LB_PhoneNumber') ], [{validator: textboxHasValueValidator, validationData: null, errorMessages: ["Enter number"]}, {validator: UkPhoneNumberValidator, validationData: null, errorMessages: UkPhoneNumberErrorMessages} ], $('LB_PhoneNumber_Label'), $('LB_PhoneNumber_ErrorAdvice'), true, false, true, $('LB_Step3_FinishButton'), false, false, false, null, null, null );
addValidation( [ $('LB_AlternatePhoneNumber') ], [{validator: textboxHasValueValidator, validationData: null, errorMessages: ["Enter number"]}, {validator: UkPhoneNumberValidator, validationData: null, errorMessages: UkPhoneNumberErrorMessages} ], $('LB_AlternatePhoneNumber_Label'), $('LB_AlternatePhoneNumber_ErrorAdvice'), true, false, true, $('LB_Step3_FinishButton'), false, false, false, null, null, null );
addValidation( [ $('LB_FirstLineAddress') ], [{validator: textboxHasValueValidator, validationData: null, errorMessages: ["Enter address"]}, {validator: RegexValidator, validationData: "^[-`'&:\\.,/\\\\\\(\\)\\wÁáĆćÉéÍíĹĺŃńÓóŔŕŚśÚúÝýŹźÀàÈèÌìÒòÙùÂâĈĉÊêĜĝĤĥÎîĴĵÔôŜŝÛûŴŵŶŷÄäËëÏïÖöÜüŸÿßÃãẼẽĨĩÑñÕõŨũỸỹÇçĢģĶķĻļŅņŖŗŞşŢţĐđŮůǍǎČčĎďĚěǏǐĽľŇňǑǒŘřŠšŤťǓǔŽžĀāĒēĪīŌōŪūǢǣǖǘǚǜĂăĔĕĞğĬĭŎŏŬŭĊċĖėĠġİıŻżĄąĘęĮįǪǫŲųḌḍḤḥḶḷḸḹṂṃṆṇṚṛṜṝṢṣṬṭŁłŐőŰűĿŀĦħÐðÞþŒœÆæØøÅåƏə\\s]{2,128}$", errorMessages: ["Enter valid address"]} ], $('LB_FirstLineAddress_Label'), $('LB_FirstLineAddress_ErrorAdvice'), true, false, true, $('LB_Step3_FinishButton'), false, false, false, null, null, null );
var lb_postcodeValidator = addValidation( [ $('LB_Postcode') ], [{validator: textboxHasValueValidator, validationData: null, errorMessages: ["Enter postcode"]}, {validator: PostcodeValidator, validationData: null, errorMessages: ["Enter valid postcode"]} ], $('LB_Postcode_Label'), $('LB_Postcode_ErrorAdvice'), true, false, true, $('LB_Step3_FinishButton'), false, false, false, null, null, null );
addValidation( [ $('LB_DateOfBirth_Day'), $('LB_DateOfBirth_Month'), $('LB_DateOfBirth_Year') ], [{validator: dateGroupValidator, validationData: null, errorMessages: ["Select date of birth", "Invalid date"]}, {validator: ageValidator, validationData: {minAge: 18, maxAge: 65}, errorMessages: ["Must be 18 or over", "Must be 65 or under"]} ], $('LB_DateOfBirth_Label'), $('LB_DateOfBirth_ErrorAdvice'), false, false, true, $('LB_Step2_NextButton'), true, false, false, null, null, null );


//MY VALIDATIONS
addValidation( [ $('PreferredContactMethod') ], [{validator: radioButtonListHasValueValidator, validationData: null, errorMessages: ["Make a selection"]}], $('PreferredContactMethod_Label'), $('PreferredContactMethod_ErrorAdvice'), false, false, true, $('LB_Step2_NextButton'), true, true, false, null, null, null );
addValidation( [ $('UkResident') ], [{validator: radioButtonListHasValueValidator, validationData: null, errorMessages: ["Make a selection"]}], $('LB_UkResident_Label'), $('LB_UkResident_ErrorAdvice'), false, false, true, $('LB_Step2_NextButton'), true, true, false, null, null, null );
addValidation( [ $('LB_Title') ], [{validator: textboxHasValueValidator, validationData: null, errorMessages: ["Enter a title"]}, {validator: RegexValidator, validationData: "^[-`'\\wÁáĆćÉéÍíĹĺŃńÓóŔŕŚśÚúÝýŹźÀàÈèÌìÒòÙùÂâĈĉÊêĜĝĤĥÎîĴĵÔôŜŝÛûŴŵŶŷÄäËëÏïÖöÜüŸÿßÃãẼẽĨĩÑñÕõŨũỸỹÇçĢģĶķĻļŅņŖŗŞşŢţĐđŮůǍǎČčĎďĚěǏǐĽľŇňǑǒŘřŠšŤťǓǔŽžĀāĒēĪīŌōŪūǢǣǖǘǚǜĂăĔĕĞğĬĭŎŏŬŭĊċĖėĠġİıŻżĄąĘęĮįǪǫŲųḌḍḤḥḶḷḸḹṂṃṆṇṚṛṜṝṢṣṬṭŁłŐőŰűĿŀĦħÐðÞþŒœÆæØøÅåƏə\\s]{2,50}$", errorMessages: ["Enter valid title"]}, {validator: RegexValidator, validationData: "^[\\D]{2,}$", errorMessages: ["Enter valid title"]} ], $('LB_Title_Label'), $('LB_Title_ErrorAdvice'), true, false, true, $('LB_Step2_NextButton'), false, false, false, null, null, null );

/* ==================================================================================
   MORTGAGE FORM EVENT SETUP
   ================================================================================== */

// Mortgage Type on Step 1 - defines what is visible on Step 2
addEvent( $('LB_MortgageType'), 'onclick', mortgageTypeChange );
addEvent( $('LB_MortgageType_2'), 'onclick', mortgageTypeChange );
addEvent( $('LB_MortgageType_3'), 'onclick', mortgageTypeChange );

// Back, Next, Finish buttons
addEvent( $('LB_Step1_NextButton'), 'onclick', LB_Step1_NextButton_Event_Click );

addEvent( $('LB_Step2_BackButton'), 'onclick', LB_Step2_BackButton_Event_Click );
addEvent( $('LB_Step2_NextButton'), 'onclick', LB_Step2_NextButton_Event_Click );

addEvent( $('LB_Step2b_BackButton'), 'onclick', LB_Step2b_BackButton_Event_Click );
addEvent( $('LB_Step2b_NextButton'), 'onclick', LB_Step2b_NextButton_Event_Click );

addEvent( $('LB_Step3_BackButton'), 'onclick', LB_Step3_BackButton_Event_Click );
addEvent( $('LB_Step3_FinishButton'), 'onclick', LB_Step3_FinishButton_Event_Click );

// Monitor Postcode field for changes
addEvent( $('LB_Postcode'), 'onkeyup', getBrokerName );
addEvent( $('LB_Postcode'), 'onblur', getBrokerName );
addEvent( $('LB_Postcode'), 'onchange', getBrokerName );

function mortgageTypeChange()
{
	if( this == window )
	{
		sessionStartPing( "MORTGAGEHTML10", "MORTGAGE" );
	}

	var propertyValueLabel = "Property value: ";
	var firstTimeBuyerDivDisplay = "none";
	var incomeClassName = '';

	switch( getRadioButtonListSelectedValue('LB_MortgageType') )
	{
		case 'buy':
		{
			firstTimeBuyerDivDisplay="none";
			break;
		}

		case 'remortgage':
		{
			propertyValueLabel = "Property value: ";
			firstTimeBuyerDivDisplay="none";
			break;
		}
		
		case 'buyToLet':
		{
			if(navigator.appName == 'Microsoft Internet Explorer'){firstTimeBuyerDivDisplay = "inline";}
			else{firstTimeBuyerDivDisplay = "table-row";}
			break;
		}
	}
	//$('LB_Income_Div').className = incomeClassName;
	$('LB_FirstTimeBuyer_Div').style.display = firstTimeBuyerDivDisplay;
	$('LB_PropertyValue2_Label').innerHTML = $('LB_PropertyValue_Label').innerHTML = propertyValueLabel;
}

/* ==================================================================================
   MORTGAGE FORM BUTTON EVENT HANDLERS
   ================================================================================== */

function findElementPosition(element)
{
	var curleft = curtop = 0;
	if (element.offsetParent)
	{
		curleft = element.offsetLeft;
		curtop = element.offsetTop;
		while (element = element.offsetParent)
		{
			curleft += element.offsetLeft;
			curtop += element.offsetTop;
		}

	}

	return {left: curleft, top: curtop};
}

// Step 1
function LB_Step1_NextButton_Event_Click( event )
{
	var event = new Event(event);
	
	setCurrentControlFocus( event.target );

	if( validateMultiple( event ) )
	{
		// Change the visible wizard step	
		$('LB_Step1').className = 'LB_FormStep LB_FormStepHidden';
		$('LB_Step2').className = 'LB_FormStep LB_FormStepVisible';
		$('tooltipLarge1').className = 'tooltipLarge_hidden';
		$('tooltipLarge3').className = 'tooltipLarge_hidden';
		$('tooltipLarge2').className = 'tooltipLarge';

		// Update the status of this session in the database
		sessionStepPing( "STEP2", 0 );
	}
}

// Step 2
function LB_Step2_BackButton_Event_Click( event )
{
	var event = new Event(event);
	setCurrentControlFocus( event.target );

	$('LB_Step2').className = 'LB_FormStep LB_FormStepHidden';
	$('LB_Step1').className = 'LB_FormStep LB_FormStepVisible';
	$('tooltipLarge2').className = 'tooltipLarge_hidden';
	$('tooltipLarge3').className = 'tooltipLarge_hidden';
	$('tooltipLarge1').className = 'tooltipLarge';
}

function LB_Step2_NextButton_Event_Click( event )
{
	var event = new Event(event);
	setCurrentControlFocus( event.target );

	if( validateMultiple( event ) )
	{
		$('LB_Step2').className = 'LB_FormStep LB_FormStepHidden';

		// Copy off the values from PropertyValue and AmountToBorrow into the replica boxes on Step2b. If the
		// LTV is out of whack then we can re-present the boxes to the user and get them to adjust the values
		$('LB_PropertyValue2').value = $('LB_PropertyValue').value;
		$('LB_AmountToBorrow2').value = $('LB_AmountToBorrow').value;

		var mortgageType = getRadioButtonListSelectedValue('LB_MortgageType');
		var firstTimeBuyer = parseInt(getRadioButtonListSelectedValue('LB_FirstTimeBuyer'));
		var selfCertifyIncome = parseInt(getRadioButtonListSelectedValue('LB_SelfCertifyIncome'));
		var ltvPercent = calculateLtvPercent( getFloatFromTextbox($('LB_AmountToBorrow')), getFloatFromTextbox($('LB_PropertyValue')) );

		var detailedMortgageType = getDetailedMortgageType( mortgageType, customerHasBadCredit(), firstTimeBuyer, selfCertifyIncome, ltvPercent );

		// Re-check the Loan-To-Value now that we have ALL the information we need to make a decision (e.g. credit score)
		if( ltvPercent > detailedMortgageType.ltvPercent )
		{
			// If Loan-To-Value is now too high, then we need to show user the Property Value and Amount To Borrow and get
			// them to change one
			$('LB_LtvProblem').innerHTML = 'Amount you wish to borrow is more than ' + detailedMortgageType.ltvPercent + '% of your property value. Please amend Amount To Borrow or your Property Value.';
			$('LB_Step2b').className = 'LB_FormStep LB_FormStepVisible';

			// Update the status of this session in the database
			sessionStepPing( "STEP2B", 0 );
		}
		else
		{
			// Otherwise, if Loan-To-Value is fine, jump to last Step (Contact Details) as normal
			$('LB_Step3').className = 'LB_FormStep LB_FormStepVisible';
			$('tooltipLarge1').className = 'tooltipLarge_hidden';
			$('tooltipLarge2').className = 'tooltipLarge_hidden';
			$('tooltipLarge3').className = 'tooltipLarge';

			// Update the status of this session in the database
			sessionStepPing( "STEP3", 0 );

			// We call this here in case they've gone back through the form and changed an earlier value - we now
			// need to get a new broker name for them as the type of lead might have changed
			getBrokerName(true);
		}
	}
}

// Step 2b
function LB_Step2b_BackButton_Event_Click( event )
{
	var event = new Event(event);
	setCurrentControlFocus( event.target );

	// Copy back the values from PropertyValue2 and AmountToBorrow2 into the original boxes on Step1 & 2.
	$('LB_PropertyValue').value = $('LB_PropertyValue2').value;
	$('LB_AmountToBorrow').value = $('LB_AmountToBorrow2').value;

	$('LB_Step2b').className = 'LB_FormStep LB_FormStepHidden';
	$('LB_Step2').className = 'LB_FormStep LB_FormStepVisible';
	$('tooltipLarge1').className = 'tooltipLarge_hidden';
	$('tooltipLarge3').className = 'tooltipLarge_hidden';
	$('tooltipLarge2').className = 'tooltipLarge';
}

function LB_Step2b_NextButton_Event_Click( event )
{
	var event = new Event(event);
	setCurrentControlFocus( event.target );

	// Copy back the values from PropertyValue2 and AmountToBorrow2 into the original boxes on Step1 & 2.
	$('LB_PropertyValue').value = $('LB_PropertyValue2').value;
	$('LB_AmountToBorrow').value = $('LB_AmountToBorrow2').value;

	if( validateMultiple( event ) )
	{
		$('LB_Step2b').className = 'LB_FormStep LB_FormStepHidden';
		$('LB_Step3').className = 'LB_FormStep LB_FormStepVisible';
		$('tooltipLarge1').className = 'tooltipLarge_hidden';
		$('tooltipLarge2').className = 'tooltipLarge_hidden';
		$('tooltipLarge3').className = 'tooltipLarge';

		// Update the status of this session in the database
		sessionStepPing( "STEP3", 0 );

		// We call this here in case they've gone back through the form and changed an earlier value - we now
		// need to get a new broker name for them as the type of lead might have changed
		getBrokerName(true);
	}
}

// Step 3
function LB_Step3_BackButton_Event_Click( event )
{
	var event = new Event(event);
	setCurrentControlFocus( event.target );

	$('LB_Step3').className = 'LB_FormStep LB_FormStepHidden';
	$('LB_Step2').className = 'LB_FormStep LB_FormStepVisible';
	$('tooltipLarge1').className = 'tooltipLarge_hidden';
	$('tooltipLarge3').className = 'tooltipLarge_hidden';
	$('tooltipLarge2').className = 'tooltipLarge';
}

function LB_Step3_FinishButton_Event_Click( event )
{
	var event = new Event(event);
	setCurrentControlFocus( event.target );

	if( validateMultiple( event ) )
	{
		$('LB_Step3_FinishButton').disabled = true;
		$('LB_Step3_FinishButton').value = "Submitting details...";

//		var stepPosition = findElementPosition($('LB_Step3'));

//		$('back').style.left = stepPosition.left;
//		$('back').style.top = stepPosition.top;
//		$('back').style.width = $('LB_Step3').offsetWidth;
//		$('back').style.height = $('LB_Step3').offsetHeight;
//		$('back').style.visibility = "visible";


//		$('indicator').style.left = stepPosition.left + (($('LB_Step3').offsetWidth - $('indicator').offsetWidth) / 2) + "px";
//		$('indicator').style.top = stepPosition.top + (($('LB_Step3').offsetHeight - $('indicator').offsetHeight) / 2) + "px";
//		$('indicator').style.visibility = "visible";		
		
		setTimeout('revertSubmitButton()', 20000);
		
		submitLead();
	}
	
	return false;
}

function revertSubmitButton()
{
	$('LB_Step3_FinishButton').disabled = false;
	$('LB_Step3_FinishButton').value = "Submit";
	
	$('LB_SubmitIndicator').style.visibility = "hidden";
	$('LB_AlphaLayer').style.visibility = "hidden";

	return;
}

/* ==================================================================================
   JSON AJAX MORTGAGE CALLBACK FUNCTIONS
   ================================================================================== */

function BrokerSearchCallback(BrokerDetails)
{
	if( BrokerDetails )
	{
		if( BrokerDetails.Error.ErrorNumber == '0' )
		{
			var BrokerText = BrokerDetails.Broker.DisplayText;
			//BrokerText = BrokerText.replace('Based on your mortgage requirements we have selected an FSA regulated broker called ', '');
			//BrokerText = BrokerText.replace(' to help you with your enquiry. ', '');
			BrokerText = BrokerText.replace('Please click Submit to send your enquiry.', '');
			$('LB_BrokerName').innerHTML = BrokerText.replace(/&amp;/g, "&");
			$('LB_Consent').style.display = 'block';
			$('LB_SessionId').value = BrokerDetails.Broker.Id;
			$('LB_Step3_FinishButton').disabled = false;
			$('LB_Step3_FinishButton').value = "Submit";
		}
		else
		{
			$('LB_BrokerName').innerHTML = 'ERROR ' + BrokerDetails.Error.ErrorMessage;
			$('LB_Consent').style.display = 'none';
			$('LB_SessionId').value = '';
		}
	}
}

function ProcessLeadCallback( returnData )
{
	var grossLeadPrice = 0;

	if( returnData.Lead && returnData.Lead.GrossPrice )
	{
		grossLeadPrice = returnData.Lead.GrossPrice;
	}

	switch( returnData.Error.ErrorNumber )
	{
		case '235':
		case '0':
		{
			// Update the status of this session in the database
			sessionStepPing( "FINISH", 1, "&lp=" + grossLeadPrice );

			if( lb_redirectThankYouPage )
			{
				if( lb_leadPriceQueryStringParameterName )
				{
					if( lb_thankYouPageHref.indexOf("?") > 0 )
					{
						lb_thankYouPageHref += "&" + lb_leadPriceQueryStringParameterName + "=" + grossLeadPrice;
					}
					else
					{
						lb_thankYouPageHref += "?" + lb_leadPriceQueryStringParameterName + "=" + grossLeadPrice;
					}
				}
							
				window.location.href = lb_thankYouPageHref;
			}
			else
			{
				$('LB_Step3').className = 'LB_FormStep LB_FormStepHidden';
				$('LB_Step4').className = 'LB_FormStep LB_FormStepVisible';
				$('tooltipLarge1').className = 'tooltipLarge_hidden';
				$('tooltipLarge2').className = 'tooltipLarge_hidden';
				$('tooltipLarge3').className = 'tooltipLarge';
			}
			
			break;
		}

		case '100':
		{
			setControlToErrorState( lb_postcodeValidator, "Enter valid UK postcode" );
			break;
		}
		
		default:
		{
			// Unknown error
			break;
		}
	}
}

/* ==================================================================================
   JSON AJAX MORTGAGE CALLOUT FUNCTIONS
   ================================================================================== */

function buildBasicQueryString()
{
	var postcode = $('LB_Postcode').value.trim().toUpperCase();

	var queryString = '?';
	
	switch( getRadioButtonListSelectedValue('LB_MortgageType') )
	{
		case 'remortgage':
		{
			queryString += 'Mortgage_Type=1';
			break;
		}				
		case 'buyToLet':
		{
			queryString += 'Mortgage_Type=5';
			break;
		}
		case 'buy':
		{
			queryString += 'Mortgage_Type=6';
			break;
		}
	}
	var amount = $('LB_AmountToBorrow').value;
	amount = amount.replace(",","");
	
	queryString += '&Mortgage_Size=' + getFloatFromTextbox($('LB_AmountToBorrow'));
	queryString += '&Property_Value=' + getFloatFromTextbox($('LB_PropertyValue'));
	queryString += '&Income=' + $('LB_Income').value;
	queryString += '&SelfCert=';
	queryString += getRadioButtonListSelectedValue('LB_SelfCertifyIncome') === null ? '0' : getRadioButtonListSelectedValue('LB_SelfCertifyIncome');
	queryString += '&BadCredit=0';
	queryString += '&FTB=';
	queryString += getRadioButtonListSelectedValue('LB_FirstTimeBuyer') == null ? '0' : getRadioButtonListSelectedValue('LB_FirstTimeBuyer');
	queryString += '&FP=0';
	queryString += '&Postcode=' + escape(postcode);
	queryString += '&ContactTime=' + $('PreferredContactTime').value;
	queryString += '&Password=marlow19';
	queryString += '&IPAddress=' + $('LB_IPAddress').value;
	queryString += '&AffiliateID=' + (lb_testing ? lb_testAffiliateId : lb_affiliateId);
	queryString += '&ajax=y&filladdress=1';

	return queryString;
}

function getBrokerName(overrideIdenticalPostcodeCheck)
{
	var postcode = $('LB_Postcode').value.trim().toUpperCase();

	if( lb_lastPostcodeChecked == postcode && overrideIdenticalPostcodeCheck != true )
	{
		return;
	}
	else
	{
		lb_lastPostcodeChecked = postcode;
	}

	if( postcodeTest( postcode ) != -1 )
	{
		$('LB_Consent').style.display = 'none';
		$('LB_SessionId').value = '';
		$('LB_Step3_FinishButton').disabled = false;
		$('LB_Step3_FinishButton').value = "Submit";
		return;
	}

	$('LB_Step3_FinishButton').disabled = true;
	$('LB_Step3_FinishButton').value = "Searching...";
	// set decision vars
	var mfp_isMonetised = false;
	var incoming_value = getFloatFromTextbox($('LB_AmountToBorrow'));
	var incoming_job = getFloatFromTextbox($('Occupation'));
	// If amount is less than our cap, user is not a professional, and mortgage type
	// is not a remortgage
	if(incoming_value < mfp_valueCap && incoming_job < 1 && getRadioButtonListSelectedValue('LB_MortgageType')=="buy") {
		// Commented out to disable feature
		//	mfp_isMonetised = true;
	}
	var queryString = buildBasicQueryString();
	//remoteJson({"uri": getPageProtocol() + mfp_getBrokerUrl })
	if(mfp_isMonetised == false){
			remoteJson({"uri": getPageProtocol() + mfp_getBrokerUrl })
	} else {
		if( lb_testing ){
			remoteJson({"uri": getPageProtocol() + lb_ajaxTestBrokerSearchUrl + queryString});
		}
		else{
			remoteJson({"uri": getPageProtocol() + lb_ajaxBrokerSearchUrl + queryString});
		}
	}

	return true;
}

function submitLead(){
	var mfp_isMonetised = 0;
	var incoming_value = getFloatFromTextbox($('LB_AmountToBorrow'));
	var incoming_job = getFloatFromTextbox($('Occupation'));
	// If amount is less than our cap, user is not a professional, and mortgage type
	// is not a remortgage
	if(incoming_value < mfp_valueCap && incoming_job < 1 && getRadioButtonListSelectedValue('LB_MortgageType')=="buy") {
		//commented out to disable monetisation
		//mfp_isMonetised = 1;	
	}
	
	if( $('LB_SessionId').value.length < 1 || $('LB_SessionId').value == '' )
	{
		getBrokerName();
	}

	var queryString = buildBasicQueryString();
	
	queryString += '&Title=' + $('LB_Title').value;
	queryString += '&First_Name=' + $('LB_FirstName').value;
	queryString += '&Surname=' + $('LB_LastName').value;
	queryString += '&ProfessionId=' + $('Occupation').value;
	queryString += '&ContactBy=' + getRadioButtonListSelectedValue('PreferredContactMethod');
	queryString += '&UkResident=' + getRadioButtonListSelectedValue('UkResident');
	queryString += '&DOBday=' + $('LB_DateOfBirth_Day').value;
	queryString += '&DOBmonth=' + $('LB_DateOfBirth_Month').value;
	queryString += '&DOByear=' + $('LB_DateOfBirth_Year').value;
	queryString += '&adr1=' + $('LB_FirstLineAddress').value;
	queryString += '&adr2=&town=&county=';
	queryString += '&Home_Phone=' + $('LB_PhoneNumber').value;
	queryString += '&Work_Phone=' + $('LB_AlternatePhoneNumber').value;
	queryString += '&Mobile_Phone=&Email=' + $('LB_EmailAddress').value;
	queryString += '&Mortgage_Time_Scale=1&Payment_Term=' + $('LB_MortgagePeriod').value;
	queryString += '&Other_Info=&sessionid=' + $('LB_SessionId').value;
	queryString += '&monetised=' + mfp_isMonetised;
	queryString += '&Notes=' + $('LB_Notes').value;
	if( lb_testing ){queryString += '&test=true';}
	
	remoteJson({"uri": getPageProtocol() + mfp_submitUrl + queryString});
	
	//if( lb_testing ){
	//	var test = "&test=true";
	//	
	//	remoteJson({"uri": getPageProtocol() + lb_ajaxTestProcessLeadUrl + queryString});
	//}
	//else{
	//	remoteJson({"uri": getPageProtocol() + lb_ajaxProcessLeadUrl + queryString});
	//}
	
	return true;
}

/* ==================================================================================
   VALIDATORS - MORTGAGE SPECIFIC
   ================================================================================== */

function FireAmountToBorrowValidator( event, controls, validation, extraValidators )
{
	// Check if AmountToBorrow is filled out
	if( validation.validationData.value.length > 0 )
	{
		delayedValidate.attempt( event, extraValidators[0] );
	}
	
	return {errorCode: -1};
}

function BasicLtvValidator( event, controls, validation, extraValidators )
{
	// Check if PropertyValue is filled out
	if( validation.validationData.value.length > 0 )
	{
		var amountToBorrow = parseFloat(controls[0].value);
		var propertyValue = getFloatFromTextbox(validation.validationData);

		var loanToValuePercent = calculateLtvPercent( amountToBorrow, propertyValue );

		if( loanToValuePercent > 110.0 )
		{
			return {errorCode: 0};
		}
	}
	
	return {errorCode: -1};
}

function DetailedLtvValidator( event, controls, validation, extraValidators )
{
	// Check if PropertyValue is filled out
	if( validation.validationData.value.length > 0 )
	{
		var mortgageType = getRadioButtonListSelectedValue('LB_MortgageType');
		var firstTimeBuyer = parseInt(getRadioButtonListSelectedValue('LB_FirstTimeBuyer'));
		var selfCertifyIncome = parseInt(getRadioButtonListSelectedValue('LB_SelfCertifyIncome'));
		var ltvPercent = calculateLtvPercent( parseFloat(controls[0].value), getFloatFromTextbox(validation.validationData) );

		var detailedMortgageType = getDetailedMortgageType( mortgageType, customerHasBadCredit(), firstTimeBuyer, selfCertifyIncome, ltvPercent );

		if( ltvPercent > detailedMortgageType.ltvPercent )
		{
			return {errorCode: 0, errorMessage: validation.errorMessages[0].replace(/###MAXLTV###/, detailedMortgageType.ltvPercent) };
		}
	}
	
	return {errorCode: -1};
}


/* ==================================================================================
   UTILITY FUNCTIONS - MORTGAGE SPECIFIC
   ================================================================================== */

function calculateLtvPercent( amountToBorrow, propertyValue )
{
	return ( amountToBorrow / propertyValue ) * 100.0;
}

function customerHasBadCredit()
{
	if( $('LB_CCJ').checked || $('LB_MissedPayments').checked || $('LB_Bankrupt_IVA').checked )
	{
		return true;
	}
	
	return false;
}

// Check Visio diagram named "Mortgage Types Flowchart.vsd" for a flowchart of this
function getDetailedMortgageType( basicMortgageType, badCredit, firstTimeBuyer, selfCertifyIncome, ltvPercent )
{
	switch( basicMortgageType )
	{
		case 'buy':
			if( firstTimeBuyer )
			{
				if( badCredit && ( ltvPercent <= lb_detailedMortgageTypes.adverseOther.ltvPercent ) )
				{
					return lb_detailedMortgageTypes.adverseOther;
				}
				else
				{
					return lb_detailedMortgageTypes.firstTimeBuyer;
				}
			}
			else
			{
				if( badCredit )
				{
					return lb_detailedMortgageTypes.adverseOther;
				}
				else
				{
					if( selfCertifyIncome )
					{
						return lb_detailedMortgageTypes.selfCertifyOther;
					}
					else
					{
						return lb_detailedMortgageTypes.purchase;
					}
				}
			}

		case 'remortgage':
			if( selfCertifyIncome )
			{
				return lb_detailedMortgageTypes.selfCertifyRemortgage;
			}
			else
			{
				if( badCredit )
				{
					return lb_detailedMortgageTypes.adverseRemortgage;
				}
				else
				{
					return lb_detailedMortgageTypes.remortgage;
				}
			}

		case 'buyToLet':
			if( badCredit )
			{
				return lb_detailedMortgageTypes.adverseOther;
			}
			else
			{
				return lb_detailedMortgageTypes.buyToLet;
			}
	}
}