/*
The finance manager application wraps up our ajax request call to the finance web service.
*/
jQuery(function ($) {
	var m_options = {};
	var m_vehicles = new Array();
	var m_REQUESTURL = "/Commerce/Finance/REQUESTTYPECalculation.ashx";
	var m_Args =
	{
		AUTHENTICATIONKEY: { name: "auky", value: null },
		TERM: { name: "mtrm", value: null },
		DEPOSIT: { name: "dpst", value: null },
		ANNUALMILEAGE: { name: "amlg", value: null },
		PRODUCT: { name: "prod", value: null },
		RESPONSETYPE: { name: "resp", value: null },
		REQUESTTYPE: { name: "reqt", value: null },
		VEHICLES: { name: "vhls", value: null }
	}

	$.financeManager = {
		initialise: function (p_options) {
			$.extend(m_options, $.financeManager.defaults, p_options);
		},
		options: m_options,
		vehicles: m_vehicles,
		getData: function (p_dataType, p_requestType) {
			m_makeFinanceRequest(p_dataType, p_requestType);
		},
		/* Method used to substitute option values from session. */
		getValues: function (p_dataType, p_requestType) {
			m_makeValuesRequest();
		},
		/* Method used for binding passed in option look-up criteria. */
		bindOptions: function (p_uiOptionContainers) {
			this.onBindOptions(p_uiOptionContainers);
		},
		onBindOptions: on_BindOptions,
		/* Default properties for before send, error and success functions. */
		onBeforeSend: on_BeforeSend,
		onSuccess: on_Success,
		onError: on_Error
	};

	$.financeManager.responseTypes = { JSON: "Json",
		HTML: "Html"
	};
	$.financeManager.requestTypes = { SINGLE: "Full",
		MULTIPLE: "List",
		OPTIONS: "Options"
	};
	$.financeManager.productTypes = { ALL: { name: "All", value: "ALL" },
		HP: { name: "Hire Purchase", value: "HP" },
		PCP: { name: "PCP", value: "PCP" },
		LP: { name: "Lease Purchase", value: "LP" }
	};
	$.financeManager.maximumTerms = { TWELVE: { name: "12 months", value: 12 },
		EIGHTEEN: { name: "18 months", value: 18 },
		TWENTYFOUR: { name: "24 months", value: 24 },
		THIRTY: { name: "30 months", value: 30 },
		THIRTYSIX: { name: "36 months", value: 36 },
		FORTYTWO: { name: "42 months", value: 42 },
		FORTYEIGHT: { name: "48 months", value: 48 },
		FIFTYFOUR: { name: "54 months", value: 54 },
		SIXTY: { name: "60 months", value: 60 }
	};
	$.financeManager.totalDeposits = { ZERO: { name: "No Deposit", value: 0 },
		ONEHUNDRED: { name: "&pound;100", value: 100 },
		TWOHUNDRED: { name: "&pound;200", value: 200 },
		THREEHUNDRED: { name: "&pound;300", value: 300 },
		FOURHUNDRED: { name: "&pound;400", value: 400 },
		FIVEHUNDRED: { name: "&pound;500", value: 500 },
		SIXHUNDRED: { name: "&pound;600", value: 600 },
		SEVENHUNDRED: { name: "&pound;700", value: 700 },
		EIGHTHUNDRED: { name: "&pound;800", value: 800 },
		NINEHUNDRED: { name: "&pound;900", value: 900 },
		ONETHOUSAND: { name: "&pound;1,000", value: 1000 },
		ONETHOUSANDTWOHUNDREDANDFIFTY: { name: "&pound;1,250", value: 1250 },
		FIFTEENHUNDRED: { name: "&pound;1,500", value: 1500 },
		ONETHOUSANDSEVENHUNDREDANDFIFTY: { name: "&pound;1,750", value: 1750 },
		TWOTHOUSAND: { name: "&pound;2,000", value: 2000 },
		TWOTHOUSANDFIVEHUNDRED: { name: "&pound;2,500", value: 2500 },
		THREETHOUSAND: { name: "&pound;3,000", value: 3000 },
		THREETHOUSANDFIVEHUNDRED: { name: "&pound;3,500", value: 3500 },
		FOURTHOUSAND: { name: "&pound;4,000", value: 4000 },
		FOURTHOUSANDFIVEHUNDRED: { name: "&pound;4,500", value: 4500 },
		FIVETHOUSAND: { name: "&pound;5,000", value: 5000 },
		SIXTHOUSAND: { name: "&pound;6,000", value: 6000 },
		SEVENTHOUSAND: { name: "&pound;7,000", value: 7000 },
		EIGHTTHOUSAND: { name: "&pound;8,000", value: 8000 },
		NINETHOUSAND: { name: "&pound;9,000", value: 9000 },
		TENTHOUSAND: { name: "&pound;10,000", value: 10000 },
		TWELVETHOUSANDFIVEHUNDRED: { name: "&pound;12,500", value: 12500 },
		FIFTEENTHOUSAND: { name: "&pound;15,000", value: 15000 },
		SEVENTEENTHOUSANDFIVEHUNDRED: { name: "&pound;17,500", value: 17500 },
		TWENTYTHOUSAND: { name: "&pound;20,000", value: 20000 }
	};
	$.financeManager.annualMileages = { FIVETHOUSAND: { name: "5,000 miles", value: 5000 },
		SIXTHOUSAND: { name: "6,000 miles", value: 6000 },
		SEVENTHOUSAND: { name: "7,000 miles", value: 7000 },
		EIGHTTHOUSAND: { name: "8,000 miles", value: 8000 },
		NINETHOUSAND: { name: "9,000 miles", value: 9000 },
		TENTHOUSAND: { name: "10,000 miles", value: 10000 },
		ELEVENTHOUSAND: { name: "11,000 miles", value: 11000 },
		TWELVETHOUSAND: { name: "12,000 miles", value: 12000 },
		THIRTEENTHOUSAND: { name: "13,000 miles", value: 13000 },
		FOURTEENTHOUSAND: { name: "14,000 miles", value: 14000 },
		FIFTEENTHOUSAND: { name: "15,000 miles", value: 15000 },
		SIXTEENTHOUSAND: { name: "16,000 miles", value: 16000 },
		SEVENTEENTHOUSAND: { name: "17,000 miles", value: 17000 },
		EIGHTEENTHOUSAND: { name: "18,000 miles", value: 18000 },
		NINETEENTHOUSAND: { name: "19,000 miles", value: 19000 },
		TWENTYTHOUSAND: { name: "20,000 miles", value: 20000 },
		TWENTYONETHOUSAND: { name: "21,000 miles", value: 21000 },
		TWENTYTWOTHOUSAND: { name: "22,000 miles", value: 22000 },
		TWENTYTHREETHOUSAND: { name: "23,000 miles", value: 23000 },
		TWENTYFOURTHOUSAND: { name: "24,000 miles", value: 24000 },
		TWENTYFIVETHOUSAND: { name: "25,000 miles", value: 25000 },
		TWENTYSIXTHOUSAND: { name: "26,000 miles", value: 26000 },
		TWENTYSEVENTHOUSAND: { name: "27,000 miles", value: 27000 },
		TWENTYEIGHTTHOUSAND: { name: "28,000 miles", value: 28000 },
		TWENTYNINETHOUSAND: { name: "29,000 miles", value: 29000 },
		THIRTYTHOUSAND: { name: "30,000 miles", value: 30000 }
	};
	$.financeManager.ZERO = 0;
	$.financeManager.MINIMUM_FINANCE_AMOUNT = 1500;

	/*
	The finance application expects elements marked up with explicit class definitions. This way we can hande errors an pre-loaders in a standard fashion.
	*/
	$.financeManager.UI = {
		FINANCE_LIST: ".pe-finance-list",
		FINANCE_LIST_AVERAGE_APR: ".pe-finance-list-average-apr",
		FINANCE_ITEM: ".pe-finance-item",
		FINANCE_ITEM_STATE: ".pe-finance-state",
		FINANCE_ITEM_LOADING: ".pe-finance-loading",
		FINANCE_ITEM_DATA: ".pe-finance-data-",
		FINANCE_ITEM_DATAHEADER: ".pe-finance-dataheader",
		FINANCE_ITEM_DATATEMPLATE: ".pe-finance-datatemplate",
		FINANCE_ITEM_NODATA: ".pe-finance-nodata",
		FINANCE_ITEM_USERERROR: ".pe-finance-usererror",
		FINANCE_ITEM_DATA_MODE: ".pe-finance-data-mode",
		FINANCE_ITEM_DATA_SUMMARY_MODE: ".pe-finance-data-summary-mode",
		FINANCE_ITEM_DATA_DETAIL_MODE: ".pe-finance-data-detail-mode",
		FINANCE_HIDDEN: "pe-finance-hidden",
		FINANCE_ITEM_ID: ".pe-finance-itemid",
		FINANCE_OPTION_CONTAINER: ".pe-finance-option-container",
		FINANCE_OPTIONS: ".pe-finance-options",
		FINANCE_OPTIONS_UPDATE: ".pe-finance-options-update",
		FINANCE_AVERAGE_APR_CONTIANER: ".pe-average-apr",
		FINANCE_REPRESENTATIVE_EXAMPLE_CONTAINER: ".pe-finance-representative-example",
		FINANCE_REPRESENTATIVE_EXAMPLE_CONTAINER_VEHICLE: ".pe-finance-representative-example-vehicle",
		FINANCE_REPRESENTATIVE_DISCLAIMER: ".pe-finance-disclaimer",
		FINANCE_LEGEND: ".finance-legend"
	};

	/*
	The finance application expects certain user defined options the list of these is below.
	*/
	$.financeManager.userOptions = {
		FINANCE_MAXIMUM_TERMS: "maximumTerm",
		FINANCE_DEPOSIT: "totalDeposit",
		FINANCE_ANNUAL_MILEAGE: "annualMileage"
	};

	$.financeManager.userValues = {
		maximumTerm: null,
		totalDeposit: null,
		annualMileage: null
	};

	$.financeManager.defaults = {
		responseType: $.financeManager.responseTypes.JSON,
		requestType: $.financeManager.requestTypes.SINGLE,
		productType: $.financeManager.productTypes.ALL.value,
		maximumTerm: $.financeManager.maximumTerms.TWENTYFOUR.value,
		totalDeposit: $.financeManager.totalDeposits.FIVETHOUSAND.value,
		annualMileage: $.financeManager.annualMileages.TENTHOUSAND.value,
		autenticationKey: null,
		requestGroup: null,
		requestGroupType: null,
		demo: false
	};


	$.financeManager.vehicle = {
		add: function (p_options) {
			var m_vehicle = $.extend({}, $.financeManager.vehicle.defaults, p_options);
			if (!m_vehicle.GroupID) m_vehicle.GroupID = m_options.requestGroup;
			if (!m_vehicle.GroupTypeID) m_vehicle.GroupTypeID = m_options.requestGroupType;
			m_vehicles.push(m_vehicle);
		}
	};


	$.financeManager.vehicle.defaults = {
		GroupID: m_options.requestGroup,
		GroupTypeID: m_options.requestGroupType,
		CentreID: $.financeManager.ZERO,
		VehicleID: $.financeManager.ZERO,
		CashPrice: $.financeManager.ZERO
	};


	/*
	Utility method for binding any look-up data.
	*/
	function on_BindOptions(p_uiOptionContainers) {

		//Load our matching finance options if we don't specify the collection explicitly.
		if (!p_uiOptionContainers) p_uiOptionContainers = $($.financeManager.UI.FINANCE_OPTION_CONTAINER + " " + $.financeManager.UI.FINANCE_OPTIONS);

		//Loop through our option ui containers and bind values.
		p_uiOptionContainers.filter("select").each(function (ui_i) {
			var uiItem = $(this);

			switch (uiItem.attr("name")) {
				case $.financeManager.userOptions.FINANCE_DEPOSIT:
					var vehiclePrices = new Array();
					//Check the vehicle data as we cannot have a deposit value where finance is less than 1500 pounds.
					for (var v_i = 0; v_i < m_vehicles.length; v_i++) {
						vehiclePrices.push(parseInt(m_vehicles[v_i].CashPrice) - $.financeManager.MINIMUM_FINANCE_AMOUNT);
					}

					vehiclePrices.sort(m_arrayNumericalSort);
					m_bindSelectOptions(uiItem, m_evaluateOptionSource(uiItem.attr("name")), 0, vehiclePrices[vehiclePrices.length - 1]);
					break;
				default:
					m_bindSelectOptions(uiItem, m_evaluateOptionSource(uiItem.attr("name")));
					break;
			}
		});

	};

	/*
	Default method called before the request is made.
	In a standard incarnation this will dispay our FINANCE_ITEM matched DOM element(s).
	*/
	function on_BeforeSend(p_request, p_responseType, p_requestType) {
		var uiList;
		var uiItem;
		switch (p_requestType) {
			case $.financeManager.requestTypes.MULTIPLE:
				uiList = $($.financeManager.UI.FINANCE_LIST);
				uiItem = $($.financeManager.UI.FINANCE_LIST + " " + $.financeManager.UI.FINANCE_ITEM).show();
				break;
			case $.financeManager.requestTypes.SINGLE:
				uiItem = $($.financeManager.UI.FINANCE_ITEM).show();
				break;
		}
		//Hide Column Headers.
		uiItem.find($.financeManager.UI.FINANCE_ITEM_DATAHEADER).hide();
		//Hide all UI states before showing the root finance item.
		uiItem.find($.financeManager.UI.FINANCE_ITEM_STATE).hide();
		if (uiList) uiList.find($.financeManager.UI.FINANCE_LIST_AVERAGE_APR).hide();
		uiItem.show();
		//hide the representative example container
		$($.financeManager.UI.FINANCE_REPRESENTATIVE_EXAMPLE_CONTAINER).hide();
		$($.financeManager.UI.FINANCE_REPRESENTATIVE_EXAMPLE_CONTAINER_VEHICLE).hide();
		//hide the disclaimer
		$($.financeManager.UI.FINANCE_REPRESENTATIVE_DISCLAIMER).hide();
		//Now show our pre-loading message(s).
		uiItem.find($.financeManager.UI.FINANCE_ITEM_LOADING).show();
	};


	/*
	Default method called one the response has been recieved correctly.
	This function can be overridden from the client application by setting the onSuccess function.
	*/
	function on_Success(p_response, p_responseType, p_requestType) {
		//First handle any returned server errors by switching to the error handler state.
		if (p_response.Error) {
			on_Error(p_response, p_responseType, p_requestType);
			return;
		}

		//If we don't return an error continue processing our result output.
		switch (p_requestType) {
			case $.financeManager.requestTypes.MULTIPLE:
				m_displayList(p_response);
				m_DisplayRepresentativeExample(p_response, $.financeManager.UI.FINANCE_REPRESENTATIVE_EXAMPLE_CONTAINER);
				break;
			case $.financeManager.requestTypes.SINGLE:
				m_displayItem(p_response);
				m_DisplayRepresentativeExample(p_response, $.financeManager.UI.FINANCE_REPRESENTATIVE_EXAMPLE_CONTAINER_VEHICLE);
				break;
		}
	};


	/*
	Default method for handling errors should they occur.
	*/
	function on_Error(p_response, p_responseType, p_requestType) {
		var uiItem;
		switch (p_requestType) {
			case $.financeManager.requestTypes.MULTIPLE:
				uiItem = $($.financeManager.UI.FINANCE_LIST + " " + $.financeManager.UI.FINANCE_ITEM)
				break;
			case $.financeManager.requestTypes.SINGLE:
				uiItem = $($.financeManager.UI.FINANCE_ITEM);
				break;
		}
		uiItem.find($.financeManager.UI.FINANCE_ITEM_LOADING).hide();
		uiItem.find($.financeManager.UI.FINANCE_ITEM_NODATA).show();
	};


	// function used to output the the representative example to the page
	function m_DisplayRepresentativeExample(p_response, selector) {
		//locate the ui element and relevant quotation for the representative example output
		var representativeExampleContainer = $(selector);
		var repExampleObj = m_GetRepresentativeExample(p_response);

		//if we have both the output the data to the user
		if (representativeExampleContainer && repExampleObj) {
			m_OutputRepresentativeExample(repExampleObj, representativeExampleContainer);

			//display the populated data
			representativeExampleContainer.show();

			//display the disclaimer
			$($.financeManager.UI.FINANCE_REPRESENTATIVE_DISCLAIMER).show();
		}
	};

	//function used to output the selected finance calculation as the Representative example
	function m_OutputRepresentativeExample(calculation, uiContainer) {
		//now we need to output the calculation data
		replaceSinglePlaceholder(uiContainer.find('.apr'), '{APR}', calculation.Figures.APR);
		replaceSinglePlaceholder(uiContainer.find('.price'), '{PRICE}', calculation.Figures.TotalDeposit + calculation.Figures.Balance);
		replaceSinglePlaceholder(uiContainer.find('a.product-family'), '{Product.MappedFamily}', calculation.Figures.Product.MappedFamily);
		replaceSinglePlaceholder(uiContainer.find('td.deposit'), '{ToalDepositt}', calculation.Figures.TotalDeposit);
		replaceSinglePlaceholder(uiContainer.find('td.balance'), '{Balance}', calculation.Figures.Balance);
		replaceSinglePlaceholder(uiContainer.find('td.term'), '{Term}', calculation.Figures.Term);
		replaceSinglePlaceholder(uiContainer.find('td.total-payable'), '{TotalPayableMain}', calculation.Figures.TotalPayableMain);
		replaceSinglePlaceholder(uiContainer.find('td.fees'), '{DocumentationFee}', calculation.Figures.DocumentationFee);		
		replaceSinglePlaceholder(uiContainer.find('td.final-payment'), '{FinalPaymentTotal}', calculation.Figures.FinalPaymentTotal);
		replaceSinglePlaceholder(uiContainer.find('td.monthly-payment'), '{RegularPaymentTotal}', calculation.Figures.RegularPaymentTotal);
		replaceSinglePlaceholder(uiContainer.find('td.documentation-fee'), '{DocumentationFee}', calculation.Figures.DocumentationFee);
		replaceSinglePlaceholder(uiContainer.find('td.purchase-fee'), '{PurchaseFee}', calculation.Figures.OptionToPurchaseFee);
		replaceSinglePlaceholder(uiContainer.find('div.pe-finance-rate-of-interest'), '{ROI}', calculation.Figures.CustomerRate);
	};

	//function used to replace a single placeholder
	function replaceSinglePlaceholder(uiElement, templateString, value) {
		//only run the replacement if the uielement has been found
		if (uiElement.length > 0) {
			//get the raw value of the uiElement
			var rawValue = uiElement.text();

			//replace the template String
			rawValue = rawValue.replace(templateString, value);

			//overwrite the text of the ui element
			uiElement.text(rawValue);
		}
	}

	//function used to get the representative example from the responses that are passed in
	function m_GetRepresentativeExample(p_response) {
		//create the array used to store the quotations that have been returned
		var calculationsArray = new Array(); ;

		//Handle the list and single implementations
		if (p_response.ListResult) {
			//interate the quotes that have been returned from the CW service
			for (i = 0; i < p_response.ListResult.length; i++) {
				// get our root calculation item this may contain more than one finance type. HP, PCP etc.
				var calculationItem = p_response.ListResult[i].Calculation;

				// iterate each calculation that has been sent back for each quote
				for (c_i = 0; c_i < calculationItem.length; c_i++) {
					// If the calculation has been successful then add it to the calculations array
					if (calculationItem[c_i].Figures) {
						calculationsArray.push(calculationItem[c_i]);
					}
				}
			}
		}
		else {
			// iterate each calculation that has been sent back for each quote
			for (c_i = 0; c_i < p_response.CalculationResult.length; c_i++) {
				// If the calculation has been successful then add it to the calculations array
				if (p_response.CalculationResult[c_i].Figures) {
					calculationsArray.push(p_response.CalculationResult[c_i]);
				}
			}
		}

		//sort the array
		calculationsArray.sort(m_ArrayObjectSort);

		//now return the representative example, the example 51% down the list
		switch (calculationsArray.length) {
			case 1:
				return calculationsArray[0];
				break;
			case 2:
				return calculationsArray[1];
				break;
			default:
				return calculationsArray[Math.ceil(calculationsArray.length * 0.51) - 1];
				break;
		}

	}


	//function used to perform the sort that is being used to arrange the quotations by APR
	function m_ArrayObjectSort(a, b) {
		//error catching	
		if (!a.Figures.APR || !b.Figures.APR) {
			return -1;
		}
		else {
			return (a.Figures.APR - b.Figures.APR);
		}
	}

	/*
	Utility function for sorting array values.
	*/
	function m_arrayNumericalSort(a, b) {
		return (a - b);
	}


	/*
	Get the data source for the finance options look-up.
	*/
	function m_evaluateOptionSource(p_key) {
		switch (p_key) {
			case $.financeManager.userOptions.FINANCE_MAXIMUM_TERMS:
				return $.financeManager.maximumTerms;
			case $.financeManager.userOptions.FINANCE_DEPOSIT:
				return $.financeManager.totalDeposits;
			case $.financeManager.userOptions.FINANCE_ANNUAL_MILEAGE:
				return $.financeManager.annualMileages;
			default:
				return null;
		}
	}

	/*
	Bind options to our select list.
	*/
	function m_bindSelectOptions(p_uiItem, p_rootDataItem, p_lowerBound, p_upperBound) {
		//Remove any static options on the select list.
		p_uiItem.children("option").remove();

		for (var key in p_rootDataItem) {
			if (!(key in Object.prototype) || p_rootDataItem[key] !== Object.prototype[key]) {
				//Check the item is within our lower and upper bounds if they have been passed in.
				if ((p_lowerBound) && (isInt(p_rootDataItem[key].value))) {
					if (parseInt(p_rootDataItem[key].value) < p_lowerBound) continue;
				}

				if ((p_upperBound) && (isInt(p_rootDataItem[key].value))) {
					if (parseInt(p_rootDataItem[key].value) > p_upperBound) continue;
				}

				//Should this value be selected?
				var isSelected = (eval("m_options." + p_uiItem.attr("name")) == p_rootDataItem[key].value);
				p_uiItem.append("<option value=\"" + p_rootDataItem[key].value + "\" " + (isSelected ? " selected=\"selected\"" : "") + ">" + p_rootDataItem[key].name + "</option>");
			}
		}
	}

	/*
	Make the ajax request to the finance proxy service.
	*/
	function m_makeFinanceRequest(p_responseType, p_requestType) {
		//Sanity check our incoming request type.		
		if (!p_responseType) p_responseType = m_options.responseType;
		if (!p_requestType) p_requestType = m_options.requestType;

		//Build our finance request arguments object. First set our common arguments.
		var requestArgs = $.extend({}, m_Args);
		requestArgs.AUTHENTICATIONKEY.value = m_options.autenticationKey;
		requestArgs.TERM.value = m_options.maximumTerm;
		requestArgs.DEPOSIT.value = m_options.totalDeposit;
		requestArgs.ANNUALMILEAGE.value = m_options.annualMileage;
		requestArgs.PRODUCT.value = m_options.productType;
		requestArgs.RESPONSETYPE.value = p_responseType;
		requestArgs.REQUESTTYPE.value = p_requestType;
		requestArgs.VEHICLES.value = JSON.stringify(m_vehicles);

		$.ajax({
			type: "POST",
			url: m_REQUESTURL.replace(/REQUESTTYPE/i, p_requestType),
			dataType: "json",
			data: toNameValueString(requestArgs),
			responseType: p_responseType,
			beforeSend: function (p_request) {
				$.financeManager.onBeforeSend(p_request, p_responseType, p_requestType);
			},
			success: function (p_response) {
				$.financeManager.onSuccess(p_response, p_responseType, p_requestType);
			},
			error: function (p_response) {
				$.financeManager.onError(p_response, p_responseType, p_requestType);
			}
		});
	};

	//function used to make a request to the server to see if we can retrieve options specified by the user
	function m_makeValuesRequest(p_responseType) {
		$.ajax({
			type: "POST",
			url: m_REQUESTURL.replace(/REQUESTTYPE/i, $.financeManager.requestTypes.OPTIONS),
			dataType: "json",
			data: '.',
			responseType: p_responseType,
			success: function (p_response) {
				m_setValues(p_response);
			}
		});
	}

	//function used to output any cached options into the clientside finance options form
	function m_setValues(p_response) {
		//Retrieve option values from session and if not null replace options currently defined in 'm_options'.
		if (p_response.Term != null) { $.financeManager.userValues.maximumTerm = p_response.Term; }
		else { $.financeManager.userValues.maximumTerm = m_options.maximumTerm; }
		if (p_response.Deposit != null) { $.financeManager.userValues.totalDeposit = p_response.Deposit; }
		else { $.financeManager.userValues.totalDeposit = m_options.totalDeposit; }
		if (p_response.Mileage != null) { $.financeManager.userValues.annualMileage = p_response.Mileage; }
		else { $.financeManager.userValues.annualMileage = m_options.annualMileage; }
		$.extend(m_options, $.financeManager.userValues);

		//Bind any option data if required.
		$.financeManager.bindOptions();

		//Replace the input item used to contain the deposit option with the corresponding value in 'm_options'.
		var p_uiOptionContainers = $($.financeManager.UI.FINANCE_OPTION_CONTAINER + " " + $.financeManager.UI.FINANCE_OPTIONS);
		p_uiOptionContainers.filter("input").each(function (ui_i) {
			var uiItem = $(this);
			switch (uiItem.attr("name")) {
				case $.financeManager.userOptions.FINANCE_DEPOSIT:
					uiItem.val(p_response.Deposit);
					break;
				default:
					break;
			}
		});

		//Get our finance quote.
		$.financeManager.getData();
	}

	/*
	Internal method for returning appropriate key value for product name.
	*/
	function m_evaluateProductKey(p_ProductName) {
		switch (p_ProductName) {
			case "Hire Purchase": return "HP";
			case "PCP": return "PCP";
			case "Lease Purchase": return "LP";
			default: return p_ProductName;
		}
	}
	/*
	Internal method for returning required 'value' from Residual object.
	*/
	function m_evaluateResidual(p_Residual, value) {
		if (p_Residual != null) {
			var residual = String(p_Residual[value]);
			residual = residual.replace(/ /g, '');
			return residual;
		}
		else {
			return "";
		}
	}

	/*
	Internal method for displaying finance details for a single request.
	*/
	function m_displayItem(p_response) {
		//Get our finance container UI element.
		var uiItem = $($.financeManager.UI.FINANCE_ITEM);

		//Loop through our available calculations and sum up which ones error.
		var errorCount = 0;
		for (var d_i = 0; d_i < p_response.CalculationResult.length; d_i++) {
			if (p_response.CalculationResult[d_i].Error) errorCount++;
			//Delete any existing finance ui data for this finance type.
			uiItem.find($.financeManager.UI.FINANCE_ITEM_DATA + d_i.toString()).remove();
		}

		//Loop through our available calculations and sum up how many products returned with data based on finance options supplied.
		var noProductCount = 0;
		for (d_i = 0; d_i < p_response.CalculationResult.length; d_i++) {
			if (p_response.CalculationResult[d_i].Error) noProductCount++;
		}
		noProductCount = p_response.CalculationResult.length - noProductCount;

		//Hide the loading message.
		uiItem.find($.financeManager.UI.FINANCE_ITEM_LOADING).hide();

		//If the finance options entered yield no results, display the user error message.
		if (noProductCount == 0) {
			uiItem.find($.financeManager.UI.FINANCE_ITEM_USERERROR).show();
		}
		else {
			//If all our finance calculations are in error then display the no finance message.
			if (errorCount == p_response.CalculationResult.length) {
				uiItem.find($.financeManager.UI.FINANCE_ITEM_NODATA).show();
			}
			else {
				var totalApr = 0;

				//declare the vars needed
				var uiItemDataTemplate, calculationDataItem, uiItemIdentifier;

				//Loop through our available calculations and display finance information for each calculation not in error.
				for (d_i = 0; d_i < p_response.CalculationResult.length; d_i++) {
					//Get our data format template to display finance data.
					uiItemDataTemplate = uiItem.find($.financeManager.UI.FINANCE_ITEM_DATATEMPLATE).clone();
					//Get our product information.
					calculationDataItem = p_response.CalculationResult[d_i].Figures;
					//Add our product identifier to this ui container.	
					uiItemIdentifier = $.financeManager.UI.FINANCE_ITEM_DATA + d_i.toString();

					if (!p_response.CalculationResult[d_i].Error) {
						//Get our Cap Id/Code from the Vehicle Residual object.
						// if the ShortCode is not supplied then make the value of calculationDataItem.Vehicle.CapId null.  A value of zero causes the finance service to fail 2010-02-05 MS
						if (m_evaluateResidual(calculationDataItem.Vehicle.Residual, "ShortCode") != "") { calculationDataItem.Vehicle.CapId = m_evaluateResidual(calculationDataItem.Vehicle.Residual, "ShortCode"); } else { calculationDataItem.Vehicle.CapId = null; }
						calculationDataItem.Vehicle.CapCode = m_evaluateResidual(calculationDataItem.Vehicle.Residual, "Code");
						//Get our FinalValue from the Vehicle Residual object.
						if (m_evaluateResidual(calculationDataItem.Vehicle.Residual, "FinalValue") != "") { calculationDataItem.Vehicle.FinalValue = m_evaluateResidual(calculationDataItem.Vehicle.Residual, "FinalValue"); } else { calculationDataItem.Vehicle.FinalValue = 0; }
						//Get our mapped family key from the label.
						calculationDataItem.Product.MappedFamilyKey = m_evaluateProductKey(calculationDataItem.Product.MappedFamily);
						//Remove our data template css class.
						uiItemDataTemplate.removeClass($.financeManager.UI.FINANCE_ITEM_DATATEMPLATE.substring(1)).addClass(uiItemIdentifier.substring(1));
						//Replace our placeholder data with real data
						replaceDataPlaceholders(calculationDataItem, uiItemDataTemplate);
						//add this value to apr
						totalApr = totalApr + calculationDataItem.APR;
						uiItem.append(uiItemDataTemplate);
						//Now we have all our finance data fragment show them to the user.
						uiItem.find(uiItemIdentifier).show();
					}
				}

				//If this is being used on a demo site, then repeat the values to ensure that 3 rows are always returned
				if (m_options.demo && ((p_response.CalculationResult.length - errorCount) == 1)) {
					uiItem.append(uiItemDataTemplate.clone());
					uiItem.append(uiItemDataTemplate.clone());
					uiItem.find('.pe-finance-data-0').eq(1).removeClass('pe-finance-data-0').addClass('pe-finance-data-1');
					uiItem.find('.pe-finance-data-0').eq(1).removeClass('pe-finance-data-0').addClass('pe-finance-data-2');
				}
				else if (m_options.demo && ((p_response.CalculationResult.length - errorCount) == 2)) {
					uiItem.append(uiItemDataTemplate.clone());
					uiItem.find('.pe-finance-data-0').eq(1).removeClass('pe-finance-data-0').addClass('pe-finance-data-2');
				}

				//Show Column Headers.
				uiItem.find($.financeManager.UI.FINANCE_ITEM_DATAHEADER).show();
			}
		}

		//Loop through our available forms and store annual mileage value.                
		for (var d_i = 0; d_i < p_response.CalculationResult.length; d_i++) {
			var uiMileage = $($.financeManager.UI.FINANCE_ITEM_DATA + d_i.toString() + " form input#mileage");
			uiMileage.val($("select#mileage").val());
		}
	}

	/*
	Internal method for displaying finance details for a listing request.
	*/
	function m_displayList(p_response) {
		var financeListItems = $($.financeManager.UI.FINANCE_LIST + " " + $.financeManager.UI.FINANCE_ITEM);

		financeListItems.each(function (ui_i) {
			//Get the finance items.
			var uiItem = $(this);

			//Get the data item id from the hidden field.
			var dataItemId = uiItem.find($.financeManager.UI.FINANCE_ITEM_ID).val();

			//Get the data item from the response.
			var dataItem = getDataItemFromList(p_response, dataItemId);

			//Hide the loading message.
			uiItem.find($.financeManager.UI.FINANCE_ITEM_LOADING).hide();

			//If we don't have finance data for this item show the no finance message.
			if (!dataItem) {
				uiItem.find($.financeManager.UI.FINANCE_ITEM_NODATA).show();
				return;
			}

			//Loop through our available calculations and sum up which ones error.
			var errorCount = 0;
			for (d_i = 0; d_i < dataItem.Calculation.length; d_i++) {
				if (dataItem.Calculation[d_i].Error) errorCount++;
				//Delete any existing finance ui data for this finance type.
				uiItem.find($.financeManager.UI.FINANCE_ITEM_DATA + d_i.toString()).remove();
			}

			//Loop through our available calculations and sum up how many products returned with data based on finance options supplied.
			var noProductCount = 0;
			for (d_i = 0; d_i < dataItem.Calculation.length; d_i++) {
				if (dataItem.Calculation[d_i].Error) noProductCount++;
			}
			noProductCount = dataItem.Calculation.length - noProductCount;

			//If the finance options entered yield no results, display the user error message.
			if (noProductCount == 0) {
				uiItem.find($.financeManager.UI.FINANCE_ITEM_USERERROR).show();
				uiItem.find($.financeManager.UI.FINANCE_ITEM_DATAHEADER).hide();
			}
			else {
				//If all our finance calculations are in error then display the no finance message.
				if (errorCount == dataItem.Calculation.length) {
					uiItem.find($.financeManager.UI.FINANCE_ITEM_NODATA).show();
					uiItem.find($.financeManager.UI.FINANCE_ITEM_DATAHEADER).hide();
				}
				else {
					//create the vars needed for output
					var uiItemDataTemplate, calculationDataItem, uiItemIdentifier;

					//Loop through our available calculations and display finance information for each calculation not in error.
					for (d_i = 0; d_i < dataItem.Calculation.length; d_i++) {
						//Get our data format template to display finance data.
						uiItemDataTemplate = uiItem.find($.financeManager.UI.FINANCE_ITEM_DATATEMPLATE).clone();
						//Get our product information.
						calculationDataItem = dataItem.Calculation[d_i].Figures;
						//Add our product identifier to this ui container.	
						uiItemIdentifier = $.financeManager.UI.FINANCE_ITEM_DATA + d_i.toString();

						if (!dataItem.Calculation[d_i].Error) {
							//Remove our data template css class.
							uiItemDataTemplate.removeClass($.financeManager.UI.FINANCE_ITEM_DATATEMPLATE.substring(1)).addClass(uiItemIdentifier.substring(1));
							//Replace our placeholder data with real data
							replaceDataPlaceholders(calculationDataItem, uiItemDataTemplate);
							uiItem.append(uiItemDataTemplate);
							//Now we have all our finance data fragment show them to the user.
							uiItem.find(uiItemIdentifier).show();
						}
					}

					//If this is being used on a demo site, then repeat the values to ensure that 3 rows are always returned
					if (m_options.demo && ((dataItem.Calculation.length - errorCount) == 1)) {
						uiItem.append(uiItemDataTemplate.clone());
						uiItem.append(uiItemDataTemplate.clone());
						uiItem.find('.pe-finance-data-0').eq(1).removeClass('pe-finance-data-0').addClass('pe-finance-data-1');
						uiItem.find('.pe-finance-data-0').eq(1).removeClass('pe-finance-data-0').addClass('pe-finance-data-2');
					}
					else if (m_options.demo && ((dataItem.Calculation.length - errorCount) == 2)) {
						uiItem.append(uiItemDataTemplate.clone());
						uiItem.find('.pe-finance-data-0').eq(1).removeClass('pe-finance-data-0').addClass('pe-finance-data-2');
					}

					//Show Column Headers.
					uiItem.find($.financeManager.UI.FINANCE_ITEM_DATAHEADER).show();

					//Remove our data template information.
					//uiItem.find($.financeManager.UI.FINANCE_ITEM_DATATEMPLATE).remove();		
				}
			}
		});
	}

	function getDataItemFromList(p_response, p_DataItemId) {
		var dataItem;
		for (i = 0; i < p_response.ListResult.length; i++) {
			dataItem = p_response.ListResult[i];
			if (parseInt(dataItem.id) == parseInt(p_DataItemId)) return dataItem;
		}
		return false;
	}
});
