/*
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"
    };

    /*
    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();
        //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_displayAverageApr(p_response);
                break;
            case $.financeManager.requestTypes.SINGLE:
                m_displayItem(p_response);
                m_displayItemAverageApr(p_response);
                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();
    };



    /*
    Output our average APR on list view.
    */
    function m_displayAverageApr(p_response) {
        var averageUiItem = $($.financeManager.UI.FINANCE_LIST_AVERAGE_APR);
        var uiHtml = averageUiItem.html();
        var averageApr = m_getAprAverage(p_response);
        if (!isNaN(averageApr)) {
            averageUiItem.html(uiHtml.replace("{APR}", averageApr));
            averageUiItem.show();
        }
    }

    /*
    Output our average APR on item view.
    */
    function m_displayItemAverageApr(p_response) {
        var averageUiItem = $($.financeManager.UI.FINANCE_AVERAGE_APR_CONTIANER);
        var uiHtml = averageUiItem.html();
        if (uiHtml != null) {
            var averageApr = m_getItemAprAverage(p_response);
            if (!isNaN(averageApr)) {
                averageUiItem.html(uiHtml.replace("{APR}", ("Typical " + averageApr + "% APR.")));
                //averageUiItem.show();
            }        
        }
    }

    /*
    Calculate the average APR based on a list of items.
    */
    function m_getAprAverage(p_response) {
        var aprValues = new Array();
        var averageApr = 0;

        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;
            //For each calculation extract the APR value into our global APR list.
            for (c_i = 0; c_i < calculationItem.length; c_i++) {
                if (calculationItem[c_i].Figures) aprValues.push(parseFloat(calculationItem[c_i].Figures.APR));
            }
        }

        //Sort our array so the numbers are sequential.
        aprValues.sort(m_arrayNumericalSort);

        //Get our avearge value.
        switch (aprValues.length) {
            case 1:
                averageApr = aprValues[0];
                break;
            case 2:
                averageApr = aprValues[1];
                break;
            default:
                averageApr = aprValues[Math.ceil(aprValues.length * 0.66)-1];
                break;
        }
        //Tidy up the display format of the number and return it.
        //averageApr = Math.round(averageApr * 10) / 10;
        //averageApr.toFixed(1);
        return averageApr;
    }

    /*
    Calculate the average APR based on a list of products for a single item.
    */
    function m_getItemAprAverage(p_response) {
        var aprValues = new Array();
        var averageApr = 0;

        for (i = 0; i < p_response.CalculationResult.length; i++) {
            //For each product returned (HP, PCP etc.) extract the APR value into our global APR list.
            if (p_response.CalculationResult[i].Figures) aprValues.push(parseFloat(p_response.CalculationResult[i].Figures.APR));
        }

        //Sort our array so the numbers are sequential.
        aprValues.sort(m_arrayNumericalSort);

        //Get our avearge value.
        switch (aprValues.length) {
            case 1:
                averageApr = aprValues[0];
                break;
            default:
                averageApr = aprValues[1];
                break;
        }
        //Tidy up the display format of the number and return it.
        //averageApr = Math.round(averageApr * 10) / 10;
        //averageApr.toFixed(1);
        return averageApr;
    }


    /*
    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() {
                $.financeManager.onError(null, 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 "Hire_Purchase";
            case "PCP": return "PCP";
            case "Lease Purchase": return "Lease_Purchase";
            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.
        uiItem = $($.financeManager.UI.FINANCE_ITEM);

        //Loop through our available calculations and sum up which ones error.
        var errorCount = 0;
        for (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();

                //ouput the average apr
                /*var avgApr = (totalApr / (p_response.CalculationResult.length - errorCount));
                var avgAprContainer = uiItem.find($.financeManager.UI.FINANCE_AVERAGE_APR_CONTIANER).html('Typical ' + avgApr.toFixed(1) + '% APR.');
                avgAprContainer.html(avgAprContainer.html().replace('{APR}', avgApr));*/

                //Remove our data template information.
                //uiItem.find($.financeManager.UI.FINANCE_ITEM_DATATEMPLATE).remove();		
            }


        }

        //Loop through our available forms and store annual mileage value.                
        for (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;
    }
});