(function (codeweavers) {

    var _defaults, _vehicle, _organisationIdentifier, _channel, _quoteReference, _offerReference, _customerReference,
        _vehicleSelection, _proposalReference, _isPersonalised, _settings, _postcode, _age,
        _languageCode;
    var _events = {};
    var _apiKey = 'DQrD0b4pJ2Pz1i3e66', _associatedDealerKey = 'BLA084', _systemKey = 'Codeweavers',
        _scriptOrganisationIdentifier = 'BLA084', _scriptOrganisationIdentifierType = 'AssociatedDealerKey';

    var _financePluginInstance = {};
    var _debugParameters = {};

    codeweavers.sessionId = codeweavers.sessionId || 'd2c117d6-ad0e-4aeb-8509-bedd1c6c30f2';

    codeweavers.dumpMainParameters = function () {
        return JSON.stringify(_debugParameters, null, '\t');
    };

    var _postMessagePluginAvailableToBrowserExtensions = function (parameters) {
        window.postMessage(['DebuggerReady', {
            script_parameters: {
                api_key: 'DQrD0b4pJ2Pz1i3e66',
                system_key: 'Codeweavers',
                dealer_key: 'BLA084'
            },
            plugin_parameters: JSON.parse(JSON.stringify(parameters))
        }], '*');
    };

    codeweavers.main = function (parameters) {
        try {
            if (!document.getElementById(parameters.pluginContentDivId)) {
                console.log("Missing or invalid 'pluginContentDivId' parameter");
                return;
            }
            if (_associatedDealerKey && _associatedDealerKey.indexOf('$$') !== 0 && parameters.dealer && _associatedDealerKey !== parameters.dealer) {
                console.log('Plugin script loaded with dealer: BLA084 does not match dealer: ' + parameters.dealer + ' passed to codeweavers.main()');
                return;
            }

            _debugParameters = JSON.parse(JSON.stringify(parameters, null, '\t'));
            _defaults = codeweavers.v1.parameterValidator.validate(parameters.defaultParameters);

            if (parameters.organisationIdentifier && parameters.organisationIdentifier.type && parameters.organisationIdentifier.value) {
                _organisationIdentifier = parameters.organisationIdentifier
            } else if (parameters.retailerReference && parameters.retailerReference.type && parameters.retailerReference.value) {
                _organisationIdentifier = parameters.retailerReference
            } else if (parameters.dealer) {
                _organisationIdentifier = {
                    value: parameters.dealer,
                    type: 'AssociatedDealerKey'
                };
            } else if (_associatedDealerKey && _associatedDealerKey.indexOf('$$') !== 0) {
                _organisationIdentifier = {
                    value: _associatedDealerKey,
                    type: 'AssociatedDealerKey'
                };
            } else if (_scriptOrganisationIdentifier && _scriptOrganisationIdentifier.indexOf('$$') !== 0 && _scriptOrganisationIdentifierType && _scriptOrganisationIdentifierType.indexOf('$$') !== 0) {
                _organisationIdentifier = {
                    value: _scriptOrganisationIdentifier,
                    type: _scriptOrganisationIdentifierType
                };
            } else {
                _organisationIdentifier = {
                    value: null,
                    type: null
                };
            }

            if (!_associatedDealerKey && _organisationIdentifier.type === 'AssociatedDealerKey' && _organisationIdentifier.value) {
                _associatedDealerKey = _organisationIdentifier.value;
            }

            _channel = parameters.channel || null;
            _offerReference = parameters.offerReference || null;
            _quoteReference = parameters.quoteReference || null;
            _proposalReference = parameters.proposalReference || null;
            _settings = parameters.settings || null;
            _customerReference = parameters.customerReference || codeweavers.sessionId;
            _languageCode = parameters.languageCode ? parameters.languageCode : null;

            if (parameters.customer) {
                _postcode = parameters.customer.postcode;
                _age = parameters.customer.age;
            }
            _isPersonalised = parameters.isPersonalised || null;
            _vehicleSelection = codeweavers.v1.vehicleSelectionValidator.validate(parameters.vehicleSelection);
            _events.loaded = typeof parameters.loaded === "function" ? parameters.loaded : false;
            _events.onSuccessfulCalculation = typeof parameters.onSuccessfulCalculation === "function" ? parameters.onSuccessfulCalculation : false;
            if (!_offerReference && !_quoteReference && !_vehicleSelection.isEnabled) {
                _vehicle = codeweavers.v1.vehicleValidator.validate(parameters.vehicle);
            }
            var financePluginParameters = codeweavers.v1.requestFactory.buildPluginParameters(
                _vehicle,
                _defaults,
                _organisationIdentifier,
                _channel, _quoteReference,
                _offerReference,
                _apiKey,
                _associatedDealerKey,
                _systemKey,
                _customerReference,
                _events,
                _vehicleSelection,
                _proposalReference,
                _isPersonalised,
                _settings,
                _age,
                _postcode,
                _languageCode,
                parameters.utm);

            var pluginData = {
                SystemKey: "Codeweavers",
                ApiKey: "DQrD0b4pJ2Pz1i3e66",
                AssociatedDealerKey: "BLA084",
                RetailerReferenceType: _organisationIdentifier.type,
                RetailerReference: _organisationIdentifier.value,
                SessionId: codeweavers.sessionId,
                AnalyticTrackingEnabled: financePluginParameters.settings.analytics.isEnabled,
                CodeweaversMainParameters: financePluginParameters
            };

            var _onScriptEvent = function (event, data) {
                switch (event.split('|')[0]) {
                    case 'custom-button-label':
                        var button = financePluginParameters.settings.callToAction.custom.find(function (x) {
                            return x.id === event.split('|')[1];
                        });
                        if (button && typeof button.label === 'string') {
                            return button.label;
                        } else if (button && typeof button.label === 'function') {
                            return button.label.apply(this, [data]);
                        }
                        break;
                    case 'custom-button-visibility':
                        var button = financePluginParameters.settings.callToAction.custom.find(function (x) {
                            return x.id === event.split('|')[1];
                        });
                        if (button && typeof button.isVisible === 'boolean') {
                            return button.isVisible;
                        } else if (button && typeof button.isVisible === 'function') {
                            return button.isVisible.apply(this, [data]);
                        }
                        break;
                    case 'custom-button-click':
                        var button = financePluginParameters.settings.callToAction.custom.find(function (x) {
                            return x.id === event.split('|')[1];
                        });
                        if (button && typeof button.onClick === 'function') {
                            return button.onClick.apply(this, [data]);
                        }
                        break;
                }
            };

            var _onUserEvent = function (event, data) {
                switch (event) {
                    case 'apply.start':
                        if (financePluginParameters.settings.callToAction.apply.onClick) {
                            financePluginParameters.settings.callToAction.apply.onClick({
                                quoteReference: data.quote_reference
                            })
                        }
                        break;
                    case 'reserve.start':
                        if (financePluginParameters.settings.callToAction.reserve.onClick) {
                            financePluginParameters.settings.callToAction.reserve.onClick({
                                quoteReference: data.quote_reference
                            })
                        }
                        break;
                    case 'part-exchange.start':
                        if (financePluginParameters.settings.callToAction.partExchange.onClick) {
                            financePluginParameters.settings.callToAction.partExchange.onClick({
                                quoteReference: data.quote_reference
                            })
                        }
                        break;
                    case 'credit-check.start':
                        if (financePluginParameters.settings.callToAction.creditCheck.onClick) {
                            financePluginParameters.settings.callToAction.creditCheck.onClick({
                                quoteReference: data.quote_reference
                            })
                        }
                        break;
                    case 'checkout.start':
                        if (financePluginParameters.settings.callToAction.checkout.onClick) {
                            financePluginParameters.settings.callToAction.checkout.onClick({
                                quoteReference: data.quote_reference
                            })
                        }
                        break;
                }

                if (typeof parameters.onUserEvent === "function") {
                    parameters.onUserEvent.apply(this, [event, data]);
                }
            };

            _financePluginInstance = codeweavers.v1.iframeUtils.createIframePlugin('https://plugins.codeweavers.net/plugins/v1/platform/finance/flexicalc', pluginData, document.getElementById(parameters.pluginContentDivId), _onUserEvent, parameters.onDomainEvent, _onScriptEvent, null);

            _postMessagePluginAvailableToBrowserExtensions(parameters);
        } catch (error) {
            document.getElementById(parameters.pluginContentDivId).innerHTML = codeweavers.v1.tools.pluginErrorHtmlGenerator(error.message);
        }
    };

    codeweavers.triggerActiveQuoteEvent = function (result) {
        if (_events.onSuccessfulCalculation) {
            _events.onSuccessfulCalculation.apply(this, [result.quote, result.extraData]);
        }
    };

    codeweavers.triggerCalculationEvent = function (result) {
        if (_events.onSuccessfulCalculation) {
            var successfulCalculations = [];
            if (typeof result !== 'undefined' && typeof result.VehicleResults !== 'undefined' && result.VehicleResults.length > 0) {
                for (var a = 0; a < result.VehicleResults.length; a++) {
                    var vehicleResult = result.VehicleResults[a];
                    if (typeof vehicleResult.FinanceProductResults !== 'undefined' && vehicleResult.FinanceProductResults.length > 0) {
                        var financeProductResults = result.VehicleResults[a].FinanceProductResults;
                        for (var b = 0; b < financeProductResults.length; b++) {
                            var calculation = financeProductResults[b];
                            if (!calculation.HasError) {
                                successfulCalculations.push(calculation);
                            }
                        }
                    }
                }
                if (successfulCalculations.length > 0) {
                    _events.onSuccessfulCalculation.apply(this, [successfulCalculations]);
                }
            }
        }
    };

}(window.codeweavers = window.codeweavers || {}));
(function (codeweavers, codeweaversV1, vehicleValidator) {
    'use strict';
    vehicleValidator.validate = function (vehicle) {
        if (!vehicle) {
            throw new Error("The vehicle element has not been supplied");
        }

        if (vehicle.isNew && typeof vehicle.isNew === 'string') {
            vehicle.isNew = JSON.parse(vehicle.isNew.toLowerCase());
        }

        if (vehicle.stockId) {
            return vehicle;
        }

        if (vehicle.isNew === undefined || vehicle.isNew === null || vehicle.isNew === '') {
            throw new Error("Is new has not been supplied");
        }

        if ((!vehicle.hasOwnProperty('identifier') || !vehicle.hasOwnProperty('identifierType')) && !vehicle.hasOwnProperty('registration') && !vehicle.registration.hasOwnProperty('number')) {
            throw new Error("Vehicle identifier and IdentifierType has not been supplied");
        }

        if (!vehicle.linkBackUrl) {
            throw new Error("Link back url has not been supplied");
        }

        if (!vehicle.hasOwnProperty('cashPrice') && !vehicle.hasOwnProperty('costBreakdown') && (!vehicle.costBreakdown.hasOwnProperty("otrPrice") || !vehicle.costBreakdown.hasOwnProperty("basePrice"))) {
            throw new Error("Cash price, or a cost breakdown containing an OTR or base price is required.");
        }

        var index;
        if (vehicle.accessories) {
            for (index = 0; index < vehicle.accessories.length; ++index) {
                if (!vehicle.accessories[index].description) {
                    throw new Error("Accessories description has not been supplied, for accessory " + index);
                }

                if (!vehicle.accessories[index].price) {
                    throw new Error("Accessories price has not been supplied, for accessory " + index);
                }
            }
        }

        if (vehicle.isNew === false) {
            if (typeof vehicle.mileage === 'undefined' || vehicle.mileage === null) {
                throw new Error("Mileage has not been supplied, this is required for used vehicles");
            }

            if (!vehicle.registration) {
                throw new Error("Registration has not been supplied, this is required for used vehicles");
            }
        }

        if (!vehicle.type) {
            throw new Error("Vehicle type not supplied. Please use 'car', 'bike', 'lcv'.");
        } else {
            var type = vehicle.type.toUpperCase();
            if (type !== "CAR" && type !== "BIKE" && type !== "LCV") {
                throw new Error("Invalid vehicle type supplied. Please use 'car', 'bike', 'lcv'.");
            }
        }

        return vehicle;
    };
}(window.codeweavers = window.codeweavers || {}, window.codeweavers.v1 = window.codeweavers.v1 || {}, window.codeweavers.v1.vehicleValidator = window.codeweavers.v1.vehicleValidator || {}));
(function (codeweavers, codeweaversV1, vehicleSelectionValidator) {
    'use strict';
    vehicleSelectionValidator.validate = function (options) {
        if (!options || 'undefined' === typeof options) {
            return {
                isEnabled: false
            };
        }

        var _build_manufacturers = function (manufacturers) {
            if ('undefined' === typeof manufacturers || !manufacturers.length) {
                return [];
            }

            return manufacturers.map(function (manufacturer) {
                return {
                    Key: manufacturer.toUpperCase(),
                    Value: manufacturer.toUpperCase()
                };
            });
        };

        var _set_vehicle_condition = function (condition) {
            if ('undefined' === typeof condition || !condition) {
                return {
                    hasNew: true,
                    hasUsed: true
                };
            }

            if (!condition.hasNew && !condition.hasUsed) {
                throw new Error('Vehicle selection condition is not set correctly, please select new or used. Omit the parameter completely to have both new and used available.');
            }

            return {
                hasNew: condition.hasNew ? condition.hasNew : false,
                hasUsed: condition.hasUsed ? condition.hasUsed : false
            };
        };

        return {
            isEnabled: true,
            manufacturers: _build_manufacturers(options.manufacturers),
            allowed_manufacturers: options.manufacturers || [],
            condition: _set_vehicle_condition(options.condition),
            dataSet: typeof options.dataSet !== 'undefined' ? options.dataSet : 'CAP'
        };
    };
}(window.codeweavers = window.codeweavers || {},
    window.codeweavers.v1 = window.codeweavers.v1 || {},
    window.codeweavers.v1.vehicleSelectionValidator = window.codeweavers.v1.vehicleSelectionValidator || {}));(function (codeweavers, codeweaversV1, requestFactory) {
	requestFactory.buildPluginParameters = function (vehicle, parameters, retailerReference, channel, quoteReference, offerReference, apiKey, associatedDealerKey, systemKey, userId, events, vehicleSelection, proposalReference, isPersonalised, settings, age, postcode, languageCode, utm) {
		var defaultDeposit = function (deposit) {
			if (typeof deposit.defaultValue !== 'undefined') {
				var depositPercentage = parseFloat(deposit.defaultValue);

				if (typeof vehicle !== 'undefined') {
					if (deposit.defaultType && deposit.defaultType.toUpperCase() === 'PERCENTAGE' && depositPercentage < 100) {
						if (vehicle.costBreakdown && vehicle.costBreakdown.otrPrice > 0) {
							return Math.round((vehicle.costBreakdown.otrPrice / 100 * depositPercentage) * 100) / 100;
						} else {
							if (typeof vehicle.cashPrice === 'string') {
								vehicle.cashPrice = vehicle.cashPrice.replace(',', '');
								vehicle.cashPrice = vehicle.cashPrice === '' ? 0 : parseFloat(vehicle.cashPrice);
							}
							return Math.round((vehicle.cashPrice / 100 * depositPercentage) * 100) / 100;
						}
					}
					return isNaN(depositPercentage) ? null : depositPercentage;
				}
			}
			return null;
		};

		var _defaultCtaValues = function () {
			return {
				preventDefault: false,
				isVisible: true,
				onClick: null,
				label: null,
				id: codeweaversV1.tools.guid()
			};
		}

		var result = {
			languageCode: languageCode ? languageCode : null,
			credentials: {
				apiKey: apiKey,
				systemKey: systemKey,
				associatedDealerKey: associatedDealerKey
			},
			customer: {
				reference: userId,
				postcode: postcode || null,
				age: age || null
			},
			parameters: { //@todo would like to remove this
				term: 36,
				annualMileage: 10000,
				regularPayment: 200,
				calculationType: 'RegularPayment',
				specificProductType: parameters.specificProductType || null,
				calculationTime: parameters.calculationTime || null
			},
			vehicleSelection: vehicleSelection,
			options: {
				term: {
					defaultValue: window.codeweavers.v1.tools.isNumericValue(parameters.term.defaultValue) ? window.parseInt(parameters.term.defaultValue) : null
				},
				annualMileage: {
					defaultValue: window.codeweavers.v1.tools.isNumericValue(parameters.annualMileage.defaultValue) ? window.parseInt(parameters.annualMileage.defaultValue) : null
				},
				deposit: {
					defaultValue: defaultDeposit(parameters.deposit),
					defaultType: window.codeweavers.v1.tools.isNumericValue(parameters.deposit.defaultValue) ? window.parseFloat(parameters.deposit.defaultValue) : null
				},
				payment: {
					defaultValue: window.codeweavers.v1.tools.isNumericValue(parameters.payment.defaultValue) ? window.parseFloat(parameters.payment.defaultValue) : null
				},
				settlement: {
					defaultValue: window.codeweavers.v1.tools.isNumericValue(parameters.settlement.defaultValue) ? window.parseFloat(parameters.settlement.defaultValue) : null
				},
				partExchange: {
					defaultValue: window.codeweavers.v1.tools.isNumericValue(parameters.partExchange.defaultValue) ? window.parseFloat(parameters.partExchange.defaultValue) : null
				},
				creditScore: {
					defaultValue: parameters.creditScore && window.codeweavers.v1.tools.isNumericValue(parameters.creditScore.defaultValue) ? window.parseInt(parameters.creditScore.defaultValue) : null
				},
				product: {
					defaultValue: parameters.product.defaultValue
				},
				calculationType: {
					defaultValue: parameters.calculationType.defaultValue
				},
				disableCommercialVehicleCalculations: parameters.disableCommercialVehicleCalculations || false
			},
			events: events || {},
			settings: {
				analytics: {
					isEnabled: true
				},
				callToAction: {
					apply: _defaultCtaValues(),
					reserve: _defaultCtaValues(),
					partExchange: _defaultCtaValues(),
					creditCheck: _defaultCtaValues(),
					checkout: _defaultCtaValues(),
					custom: []
				},
				disableBanner: false,
				financeWizard: {
					isEnabled: false
				},
				representativeExample: {
					isEnabled: true
				},
				dealerLogo: {
					isEnabled: false
				}
			},
			utm: {
				source: null,
				medium: null,
				campaign: null,
				campaignCodes: null,
				term: null,
				content: null
			}
		};

		if (retailerReference !== undefined && retailerReference !== null) {
			result.organisationIdentifier = {
				type: retailerReference.type,
				value: retailerReference.value
			};
		}

		if (typeof quoteReference !== 'undefined') {
			result.quoteReference = quoteReference;
		}

		if (typeof proposalReference !== 'undefined') {
			result.proposalReference = proposalReference;
		}

		if (typeof offerReference !== 'undefined') {
			result.offerReference = offerReference;
		}

		if (typeof isPersonalised !== 'undefined') {
			result.isPersonalised = isPersonalised;
		}

		if (typeof utm !== 'undefined') {
			result.utm = {
				campaign: typeof utm.campaign !== 'undefined' ? utm.campaign : null,
				campaignCodes: typeof utm.campaignCodes !== 'undefined' ? utm.campaignCodes : null,
				content: typeof utm.content !== 'undefined' ? utm.content : null,
				medium: typeof utm.medium !== 'undefined' ? utm.medium : null,
				source: typeof utm.source !== 'undefined' ? utm.source : null,
				term: typeof utm.term !== 'undefined' ? utm.term : null
			};
		}

		if (typeof vehicle !== 'undefined') {
			const vehicleRequest = {
				id: "Finance Plugin",
				dealer: retailerReference && retailerReference.type === 'AssociatedDealerKey' ? retailerReference.value : null,
				channel: channel && channel.key ? {
					key: channel.key
				} : null,
				retailerReference: retailerReference && retailerReference.type && retailerReference.value ? {
					type: retailerReference.type,
					value: retailerReference.value
				} : null,
				vehicle: {
					cashPrice: vehicle.cashPrice,
					costBreakdown: vehicle.costBreakdown || null,
					isNew: vehicle.isNew,
					identifier: vehicle.identifier,
					identifierType: vehicle.identifierType,
					type: vehicle.type,
					imageUrl: vehicle.imageUrl,
					dealerVehicleUrl: vehicle.linkBackUrl,
					currentMileage: vehicle.isNew ? 0 : vehicle.mileage,
					currentMileageUnit: vehicle.mileageUnit,
					registrationNumber: vehicle.registration ? vehicle.registration.number : null,
					registrationDate: vehicle.registration ? vehicle.registration.date : null,
					registrationPlate: vehicle.registration ? vehicle.registration.plate : null,
					registrationYear: vehicle.registration ? vehicle.registration.year : null,
					registrationCountryCode: vehicle.registration ? vehicle.registration.countryCode : null,
					vin: vehicle.vin ? vehicle.vin : null,
					stockId: vehicle.stockId || null,
					stockDate: vehicle.stockDate || vehicle.StockDate || null,
					manufacturer: vehicle.technicalSpecification ? vehicle.technicalSpecification.manufacturer : null,
					description: vehicle.technicalSpecification ? vehicle.technicalSpecification.description : null,
					model: vehicle.technicalSpecification ? vehicle.technicalSpecification.model : null,
					variant: vehicle.technicalSpecification ? vehicle.technicalSpecification.variant : null,
					derivative: vehicle.technicalSpecification ? vehicle.technicalSpecification.derivative : null,
					bodyStyle: vehicle.technicalSpecification ? vehicle.technicalSpecification.bodyStyle : null,
					colour: vehicle.technicalSpecification ? vehicle.technicalSpecification.colour : null,
					doors: vehicle.technicalSpecification ? vehicle.technicalSpecification.doors : null,
					transmission: vehicle.technicalSpecification ? vehicle.technicalSpecification.transmission : null,
					carbonDioxideEmissions: vehicle.technicalSpecification ? vehicle.technicalSpecification.cO2Emissions : null,
					engineCapacity: vehicle.technicalSpecification ? vehicle.technicalSpecification.engineCapacity : null,
					yearOfManufacturer: vehicle.technicalSpecification ? vehicle.technicalSpecification.yearOfManufacturer : null,
					manualResidual: vehicle.manualResidual ? vehicle.manualResidual : null,
					isFranchiseApproved: vehicle.isFranchiseApproved ? vehicle.isFranchiseApproved : null,
					vehicleTag: vehicle.vehicleTag ? vehicle.vehicleTag : null,
					countryCode: vehicle.countryCode,
					pricingIncludesGovernmentGrant: vehicle.PricingIncludesGovernmentGrant
				},
				vehicleParameters: {
					equipmentOptions: vehicle.options
				}
			};

			result.vehicleRequests = [vehicleRequest];
		}

		if (typeof settings !== 'undefined') {
			if (settings && typeof settings.callToAction !== 'undefined') {
				var _overrideCallToActionSettings = function (setting, override) {
					if (typeof override !== 'undefined') {
						if (typeof override.label === 'string' || typeof override.label === 'function') {
							setting.label = override.label;
						}
						if (typeof override.isVisible === 'boolean' || typeof override.isVisible === 'function') {
							setting.isVisible = override.isVisible;
						}
						if (typeof override.onClick === 'function') {
							setting.onClick = override.onClick;
						}
						if (typeof override.preventDefault === 'boolean') {
							setting.preventDefault = override.preventDefault;
						}
					}
				};
				_overrideCallToActionSettings(result.settings.callToAction.apply, settings.callToAction.apply);
				_overrideCallToActionSettings(result.settings.callToAction.reserve, settings.callToAction.reserve);
				_overrideCallToActionSettings(result.settings.callToAction.partExchange, settings.callToAction.partExchange);
				_overrideCallToActionSettings(result.settings.callToAction.creditCheck, settings.callToAction.creditCheck);
				_overrideCallToActionSettings(result.settings.callToAction.checkout, settings.callToAction.checkout);

				if (typeof settings.callToAction.custom !== 'undefined') {
					for (var i = 0; i < settings.callToAction.custom.length; i++) {
						result.settings.callToAction.custom[i] = _defaultCtaValues();
						_overrideCallToActionSettings(result.settings.callToAction.custom[i], settings.callToAction.custom[i]);
					}
				}
			}

			if (settings && typeof settings.analytics !== 'undefined' && typeof settings.analytics.isDisabled === 'boolean') {
				result.settings.analytics.isEnabled = settings.analytics.isDisabled === false;
			}

			if (settings && typeof settings.disableBanner === 'boolean') {
				result.settings.disableBanner = settings.disableBanner;
			}

			if (settings && typeof settings.financeWizard !== 'undefined') {
				result.settings.financeWizard = settings.financeWizard;
			}

			if (settings && typeof settings.representativeExample !== 'undefined') {
				result.settings.representativeExample = settings.representativeExample;
			}

			if (settings && typeof settings.dealerLogo !== 'undefined') {
				result.settings.dealerLogo = settings.dealerLogo;
			}
		}

		return result;
	};
}(window.codeweavers = window.codeweavers || {}, window.codeweavers.v1 = window.codeweavers.v1 || {}, window.codeweavers.v1.requestFactory = window.codeweavers.v1.requestFactory || {}));
(function (codeweavers, codeweaversV1, parameterValidator) {
    'use strict';
    parameterValidator.validate = function (parameters) {
        if (!parameters) {
            return {
                deposit: { defaultValue: null },
                product: { defaultValue: null },
                term: { defaultValue: null },
                annualMileage: { defaultValue: null },
                payment: { defaultValue: null },
                calculationType: { defaultValue: 'RegularPayment' },
                settlement: { defaultValue: null },
                partExchange: { defaultValue: null },
                creditScore: { defaultValue: null },
            };
        }

        if (typeof parameters.deposit === 'undefined' || typeof parameters.deposit.defaultValue === 'undefined') {
            parameters.deposit = { defaultValue: null };
        }

        if (typeof parameters.product === 'undefined' || typeof parameters.product.defaultValue === 'undefined') {
            parameters.product = { defaultValue: null };
        }

        if (typeof parameters.term === 'undefined' || typeof parameters.term.defaultValue === 'undefined') {
            parameters.term = { defaultValue: null };
        }

        if (typeof parameters.annualMileage === 'undefined' || typeof parameters.annualMileage.defaultValue === 'undefined') {
            parameters.annualMileage = { defaultValue: null };
        }

        if (typeof parameters.payment === 'undefined' || typeof parameters.payment.defaultValue === 'undefined') {
            parameters.payment = { defaultValue: null };
        }

        if (typeof parameters.calculationType === 'undefined' || typeof parameters.calculationType.defaultValue === 'undefined') {
            parameters.calculationType = { defaultValue: 'RegularPayment' };
        }

        if (typeof parameters.settlement === 'undefined' || typeof parameters.settlement.defaultValue === 'undefined') {
            parameters.settlement = { defaultValue: null };
        }

        if (typeof parameters.partExchange === 'undefined' || typeof parameters.partExchange.defaultValue === 'undefined') {
            parameters.partExchange = { defaultValue: null };
        }

        if (typeof parameters.creditScore === 'undefined' || typeof parameters.creditScore.defaultValue === 'undefined') {
            if (codeweavers.v1.tools.isNumericValue(parameters.creditScore)) {
                parameters.creditScore = { defaultValue: parameters.creditScore };
            } else {
                parameters.creditScore = { defaultValue: null };
            }
        }

        return parameters;
    };
}(window.codeweavers = window.codeweavers || {}, window.codeweavers.v1 = window.codeweavers.v1 || {}, window.codeweavers.v1.parameterValidator = window.codeweavers.v1.parameterValidator || {}));
(function (codeweavers, codeweaversV1, iframeUtils) {
    'use strict';

    var _buildIframeHtml = function (iframeUrl, iframeId) {
        var iframe = document.createElement('iframe');
        iframe.id = iframeId;
        iframe.name = iframeId;
        iframe.className = 'cw-finance-plugin';
        iframe.setAttribute('style', 'height:2000px; border: 0; margin: 0; overflow:hidden; width: 1px; min-width: 100%; *width: 100%;');
        iframe.setAttribute('marginheight', '0');
        iframe.setAttribute('marginwidth', '0');
        iframe.setAttribute('frameborder', '0');
        iframe.setAttribute('scrolling', 'no');
        iframe.setAttribute('webkitallowfullscreen', '');
        iframe.setAttribute('mozallowfullscreen', '');
        iframe.setAttribute('allowfullscreen', '');
        iframe.setAttribute('title', 'Finance plugin iframe');
        return iframe;
    };

    var _buildFormSubmitterElement = function (iframeUrl, submitTarget, formId, pluginData) {
        var form = document.createElement('form');
        form.id = formId;
        form.target = submitTarget;
        form.method = "POST";
        form.action = iframeUrl;
        form.style.display = "none";

        pluginData.PLUGIN_INTEGRATION_REFERER = window.location.href;

        for (var dataKey in pluginData) {
            if (pluginData.hasOwnProperty(dataKey) && pluginData[dataKey] !== null && pluginData[dataKey] !== '') {
                var input = document.createElement('input');
                input.type = "hidden";
                input.name = dataKey;
                if (typeof pluginData[dataKey] === 'object') {
                    input.value = JSON.stringify(pluginData[dataKey]);
                } else {
                    input.value = pluginData[dataKey];
                }
                form.appendChild(input);
            }
        }

        return {
            form: form,
            input: input
        };
    };

    function IframePluginMessagingEvents(pluginElement, iframeElement, iframeUrl, onUserEventCallback, onDomainEventCallback, onScriptEventCallback, messengerEventSubscriptions) {
        var iframeId = iframeElement.id;

        var iframeWindow = iframeElement.contentWindow;

        var getOffsetTop = function (elem) {
            var offsetTop = 0;
            do {
                if (!isNaN(elem.offsetTop)) {
                    offsetTop += elem.offsetTop;
                }
            } while (elem = elem.offsetParent);
            return offsetTop;
        };

        var windowMessenger = {
            send: function (event, data) {
                iframeWindow.postMessage([event, data], iframeUrl);
            }
        };

        var modalController = {
            lockIframeHeightAdjustment: false,
            originalIframeHeight: 0,
            offset: {},
            open: function () {
                var iframe = iframeElement;
                this.lockIframeHeightAdjustment = true;
                this.originalIframeHeight = iframe.style.height;
                // this.offset = codeweavers.v1.tools.windowScrollOffset();
                iframe.style.left = 'auto';
                iframe.style.top = 'auto';
                iframe.style.position = 'relative';
                iframe.style.height = window.innerHeight + 'px';
                document.body.style.overflow = "hidden";
                document.body.style.paddingRight = "17px";
                window.scrollTo(0, getOffsetTop(iframe));
                this.addBackdrop();
            },
            close: function () {
                this.lockIframeHeightAdjustment = false;
                var iframe = iframeElement;
                window.scrollTo(0, this.offset.y);
                iframe.style.left = "";
                iframe.style.top = "";
                iframe.style.position = "";
                iframe.style.height = modalController.originalIframeHeight;
                document.body.style.overflow = "";
                document.body.style.paddingRight = "";
                var backdrop = document.getElementById("cw-finance-plugin-backdrop");
                backdrop.parentElement.removeChild(backdrop);
            },
            addBackdrop: function () {
                var backdrop = document.createElement("div");
                backdrop.id = "cw-finance-plugin-backdrop";
                backdrop.style.position = "fixed";
                backdrop.style.top = 0;
                backdrop.style.right = 0;
                backdrop.style.left = 0;
                backdrop.style.height = "100%";
                backdrop.style.opacity = "0.8";
                backdrop.style.backgroundColor = "#FFF";
                pluginElement.insertBefore(backdrop, pluginElement.childNodes[0]);
                codeweavers.v1.tools.bindEvent(backdrop, "click", function () {
                    windowMessenger.send('ModalClosed');
                });
            }
        };

        var scrollController = {
            scrollToIframeOffsetTop: function (offset) {
                var y = getOffsetTop(iframeElement);
                if (offset)
                    y -= offset;
                window.scrollTo(0, y);
            },
            smoothScrollToIframeTop: function (offset, duration) {
                var y = getOffsetTop(iframeElement);

                offset = typeof offset !== 'undefined' ? offset : 0;

                if (typeof jQuery !== 'undefined') {
                    jQuery({ virtualValue: window.pageYOffset })
                        .animate({ virtualValue: y + offset }, {
                            step: function (animatedValue) {
                                window.scrollTo(0, animatedValue);
                            },
                            duration: duration
                        });
                } else {
                    window.scrollTo(0, y + offset);
                }
            }
        };

        var minHeight = 900;

        var adjustIframeHeight = function (initialHeight, newHeight) {
            if (!modalController.lockIframeHeightAdjustment) {

                if (newHeight < minHeight) {
                    minHeight = newHeight;
                }

                if (typeof jQuery !== 'undefined') {
                    // virtual since nothing is being animated than just a number
                    jQuery({ virtualHeight: initialHeight }).dequeue().animate({ virtualHeight: newHeight }, {
                        step: function (animatedValue) {
                            if (animatedValue < minHeight) {
                                animatedValue = minHeight;
                            }

                            if (pluginElement) {
                                pluginElement.childNodes[0].style.height = animatedValue + 'px';
                            }
                        },
                        duration: 700
                    });
                } else {
                    pluginElement.childNodes[0].style.height = newHeight + 'px';
                }
            }
        };

        var initialiseReceiver = function (event) {
            var data = (typeof event.data === 'string') ? event.data.split(',') : event.data;
            var domain = event.origin.toLowerCase();

            var messageOriginFrameId = null;
            if ('undefined' === typeof event.source) {
                return false;
            }

            var currentIframe = pluginElement.querySelector('IFRAME');

            if (event.source && (currentIframe.contentWindow === event.source /* absolute URLs */ || currentIframe.contentWindow === event.source.parent /* relative URLs */)) {
                messageOriginFrameId = currentIframe.id;
            }

            if ((domain === 'https://plugins.codeweavers.net' || domain === 'https://dqrd0b4pj2pz1i3e66.findvehicles.co.uk') && messageOriginFrameId === iframeId) {
                if (messengerEventSubscriptions !== null && typeof messengerEventSubscriptions !== "undefined" && typeof messengerEventSubscriptions[data[0]] === "function") {
                    messengerEventSubscriptions[data[0]].call(this, [data[1]]);
                } else {
                    switch (data[0]) {
                        case "iframeHeightChange":
                            if (Array.isArray(data[1])) {
                                adjustIframeHeight(data[1][0], data[1][1], iframeId);
                            } else {
                                adjustIframeHeight(null, data[1], iframeId);
                            }
                            break;
                        case "ModalOpened":
                            modalController.open();
                            break;
                        case "ModalClosed":
                            modalController.close();
                            break;
                        case "ScrollTop":
                            window.scrollTo(0, 0);
                            break;
                        case "ScrollToIframeOffsetTop":
                            scrollController.scrollToIframeOffsetTop(data[1]);
                            break;
                        case "ScrollToIframeTop": // deprecated, use ScrollToIframeOffset
                            scrollController.scrollToIframeOffsetTop(data[1]);
                            break;
                        case "SmoothScrollToIframeTop":
                            var duration = (data[2] !== 0 && !data[2] ? 400 : data[2]);
                            scrollController.smoothScrollToIframeTop(data[1], duration);
                            break;
                        case "CwFinancePluginCalculated":
                            codeweavers.v1.tools.postMessage('CW_FINANCE_CALCULATOR.CALCULATED', data[1]);
                            codeweavers.triggerCalculationEvent(JSON.parse(data[1]));
                            break;
                        case "CwFinancePluginActiveQuote":
                            codeweavers.triggerActiveQuoteEvent(JSON.parse(data[1]));
                            break;
                        case "cw.user-event":
                            if (typeof onUserEventCallback === "function") {
                                var pluginUserEventData = JSON.parse(data[1]);
                                onUserEventCallback.apply(this, [pluginUserEventData.event, pluginUserEventData.data]);
                            }
                            break;
                        case "cw.domain-event":
                            if (typeof onDomainEventCallback === "function") {
                                var onDomainEventCallbackData = JSON.parse(data[1]);
                                onDomainEventCallback.apply(this, [onDomainEventCallbackData.event, onDomainEventCallbackData.data]);
                            }
                            break;
                        case "cw.script-event":
                            if (typeof onScriptEventCallback === "function") {
                                var onScriptEventCallbackData = JSON.parse(data[1]);
                                var result = onScriptEventCallback.apply(this, [onScriptEventCallbackData.event, onScriptEventCallbackData.data]);
                                codeweavers.v1.tools.postMessage(onScriptEventCallbackData.event + '-reply', result);
                            }
                            break;
                        default:
                            break;
                    }
                }
            }
        };

        this.sendMessage = windowMessenger.send;

        this.listen = function () {
            if (window.addEventListener) {
                window.addEventListener("message", initialiseReceiver, false);
            } else {
                window.attachEvent("onmessage", initialiseReceiver);
            }
        };
    }

    iframeUtils.createEcommercePluginIframe = function (pluginType, pluginData, pluginElement, onUserEventsCallback, onDomainEventsCallback, onScriptEventCallbacks, hostMessageSubscriptions) {
        var srcUrl = 'https://services.codeweavers.net/navigator/redirectToApplication/ecommerce-plugin-' +
            pluginType +
            '?apiKey=DQrD0b4pJ2Pz1i3e66' +
            '&systemKey=Codeweavers' +
            '&disableAnalytics=' + pluginData.CodeweaversMainParameters.DisableAnalytics;

        if (pluginData.CodeweaversMainParameters.QuoteReference) {
            srcUrl = srcUrl + '&quoteReference=' + pluginData.CodeweaversMainParameters.QuoteReference;
        }

        var iframeId = [pluginType.replace(/\//g, '-'), codeweavers.v1.tools.guid(), "ecommerce"].join("-");
        var iframeElement = _buildIframeHtml(null, iframeId);
        iframeElement.src = srcUrl;
        pluginElement.innerHTML = "";
        pluginElement.appendChild(iframeElement);

        var messenger = new IframePluginMessagingEvents(pluginElement, iframeElement, srcUrl, onUserEventsCallback, onDomainEventsCallback, onScriptEventCallbacks, hostMessageSubscriptions);
        messenger.listen();

        return {
            messenger: messenger,
            id: iframeId
        };
    }

    iframeUtils.createIframePlugin = function (pluginUrl, pluginData, pluginElement, onUserEventsCallback, onDomainEventsCallback, onScriptEventCallbacks, hostMessageSubscriptions) {
        var iframeId = [codeweavers.v1.tools.guid(), "plugin"].join("-");
        var submitFormId = iframeId + "-form";
        var submitTarget = ('frame' === '_blank' || 'frame' === '_self' || 'frame' === '_top') ? 'frame' : iframeId;

        var iframeElement = _buildIframeHtml(pluginUrl, iframeId);
        var element = _buildFormSubmitterElement(pluginUrl, submitTarget, submitFormId, pluginData);

        pluginElement.innerHTML = "";
        pluginElement.appendChild(iframeElement);
        document.body.appendChild(element.form); // appends to the end so that it can escape sites that wrap the plugin in a form element

        var messenger = new IframePluginMessagingEvents(pluginElement, iframeElement, pluginUrl, onUserEventsCallback, onDomainEventsCallback, onScriptEventCallbacks, hostMessageSubscriptions);
        messenger.listen();

        iframeElement.addEventListener('load', function () { // workaround for dealers realoding page and losing iframe e.g. (http://www.motorparks.co.uk)
            try {
                if (iframeElement.contentWindow.location.href.indexOf('plugins.') === -1) { //check if plugin has loaded correctly
                    element.form.submit();
                    iframeElement.removeEventListener('load', this);
                } else {
                    document.body.removeChild(element.form);
                }
            } catch (e) {
                document.body.removeChild(element.form);
            }
        });
        element.form.submit();
        return {
            messenger: messenger,
            id: iframeId
        };
    };

}(window.codeweavers = window.codeweavers || {}, window.codeweavers.v1 = window.codeweavers.v1 || {}, window.codeweavers.v1.iframeUtils = window.codeweavers.v1.iframeUtils || {}));(function (codeweavers, codeweaversV1, tools) {
    'use strict';

    if (!Function.prototype.bind) {
        Function.prototype.bind = function (oThis) {
            if (typeof this !== 'function') {
                // closest thing possible to the ECMAScript 5
                // internal IsCallable function
                throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
            }

            var aArgs = Array.prototype.slice.call(arguments, 1),
                fToBind = this,
                fNOP = function () {
                },
                fBound = function () {
                    return fToBind.apply(this instanceof fNOP && oThis
                        ? this
                        : oThis,
                        aArgs.concat(Array.prototype.slice.call(arguments)));
                };

            fNOP.prototype = this.prototype;
            fBound.prototype = new fNOP();

            return fBound;
        };
    }

    tools.isNumericValue = function (n) {
        return !window.isNaN(window.parseFloat(n)) && window.isFinite(n);
    };

    tools.setCookie = function (cname, cvalue, exdays) {
        var d = new Date();
        d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
        var expires = "expires=" + d.toUTCString();
        document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
    };

    tools.guid = function () {
        function s4() {
            return Math.floor((1 + Math.random()) * 0x10000)
                .toString(16)
                .substring(1);
        }

        return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
    };

    tools.postMessage = function (key, message) {
        window.parent.postMessage([key, message], '*');
    };

    tools.bindEvent = function (el, eventName, eventHandler) {
        if (el.addEventListener) {
            el.addEventListener(eventName, eventHandler, false);
        } else if (el.attachEvent) {
            el.attachEvent('on' + eventName, eventHandler);
        }
    };

    tools.pluginErrorHtmlGenerator = function (message) {
        var html = [];
        html.push('<div id="cw-error-container" class="cw-error-container">');
        html.push('<div class="cw-error">An error occurred initialising the finance plugin.</div>');
        html.push('<div class="cw-error cw-technical-message">' + message + '</div>');
        html.push('</div>');
        return html.join('');
    };

}(window.codeweavers = window.codeweavers || {}, window.codeweavers.v1 = window.codeweavers.v1 || {}, window.codeweavers.v1.tools = window.codeweavers.v1.tools || {}));
