﻿var mazdaDealersMap = {
	mapDiv: 'mapDiv',
	isDealerLocator: false,
	useAjaxHandler: false,
	getDirectionsText: 'Get directions',
	viewDetailsText: 'View details',
	testDriveText: 'Arrange a test drive with this dealer',
	clearDirectionsText: 'Close directions',
	inputLocationText: 'Your address',
	submissiontype: 'testdrive',
	totalDistanceText: 'Total distance',
	selectDealerText: 'Select dealer',
	hourText: 'hr',
	minuteText: 'min',
	kmText: 'km',
	mileText: 'miles',
	fromText: 'From:',
	toText: 'To:',
	telText: 'Tel:',
	servicenumberText: 'Service number:',
	faxText: 'Fax:',
	emailText: 'Email:',
	serviceEmailText: 'Service Email',
	websiteText: 'Website:',
	formurl: null,
	getDirectionsLink: '<li class="directions"><a href="{formurl}step=2&amp;dealerid={dealerId}&amp;showdirectiondetails=true">{directionText}</a></li>',
	viewDetailsLink: '<li class="details"><a href="{formurl}step=2&amp;dealerid={dealerId}">{detailText}</a></li>',
	testDriveLink: '<li class="testdrive"><a href="{testDriveUrl}">{testdriveText}</a></li>',
	selectDealerLink: '<li class="selectdealer"><a href="#selectDealer" onclick="javascript:dealers.select({dealerId}); $(\'.primary input\').click(); return false;">{selectText}</a></li>',
	pushpinTemplate: '<img src="{src}" class="dealerIcon" rel="{dealerId}" />',
	inputLatLon: null,
	inputAddressString: null,
	singleDealerDetails: false,
	locs: null,
	data: [],
	culture: '',
	pushpinUrls: ['/images/markers/home.gif', '/images/markers/red_{letter}.gif', '/images/markers/start.gif', '/images/markers/end.gif', '/images/markers/red.gif'],
	map: null,
	radius: null,
	showDirections: false,
	shortestRouteOption: 'time',	// values: time or distance
	routeOption: null,     			// values: roundTrip or reverseTrip
	dataLayer: null,
	userLayer: null,
	defaultWidth: 590,
	defaultHeight: 400,
	maxWidth: 948,
	maxHeight: 490,
	initZoomLevel: 5,
	autoInteraction: false,
	viewportThreshold: 1280,
	dealersViewed: [],
	
	allowResizing: function() {
		if (!$('#mapResize').length) {
			$('#' + mazdaDealersMap.mapDiv).append('<a href="#" id="mapResize" onclick="mazdaDealersMap.toggleSize(); return false;"></a>'); // append map resize control
			$('.dealerLocator, .formwizard').css('overflow', 'visible'); // set overflow visible to allow for map resizing
			mazdaDealersMap.map.AttachEvent('onresize', mazdaDealersMap.onMapResize);
			mazdaDealersMap.toggleSize(cookie.get('mazdaMapSize'));
		}
	},
	
	disallowResizing: function() {
		if ($('#mapResize').length) {
			$('#mapResize').remove(); // remove the map resize control
			$('.dealerLocator, .formwizard').css('overflow', 'hidden'); // hide map overflow
			mazdaDealersMap.map.DetachEvent('onresize', mazdaDealersMap.onMapResize);
		}
	},
	
	loadMap: function() {
		this.locs = [];
		this.map = new VEMap(this.mapDiv);
		this.map.SetDashboardSize(VEDashboardSize.Normal);
	
		// Position the Russian map more westerly when there's no results
		if (this.culture == 'ru-RU') {
			if ($('.noResults').length || !this.data.length) {
				this.inputLatLon = new VELatLong('57.421294392094055', '52.734375');
			}
		}
	
		this.map.LoadMap(this.inputLatLon, 8, VEMapStyle.Road, false);
		this.map.Resize(this.defaultWidth, this.defaultHeight);
		
		// Map Resizing Behaviour
		if (!$('body.ie6, body.ie7').length) {
			var viewport = $(window);
			// onload
			if (viewport.width() >= mazdaDealersMap.viewportThreshold) {
				mazdaDealersMap.allowResizing();
			}
			// onresize
			viewport.bind('resize', function() {
				if (viewport.width() >= mazdaDealersMap.viewportThreshold) {
	 				mazdaDealersMap.allowResizing();
				} else {
	 				mazdaDealersMap.disallowResizing();
				}
			});
		}
		
		if (this.data != null && this.inputLatLon != null && this.inputAddressString != null) {
			var inputLocation = new VEShape(VEShapeType.Pushpin, this.inputLatLon);
			var customIcon = (this.showDirections === true) ? '<img src="' + this.pushpinUrls[2] + '" />' : '<img src="' + this.pushpinUrls[0] + '" />';
			inputLocation.SetCustomIcon(customIcon);
			//inputLocation.SetTitle(this.inputLocationText);
			//inputLocation.SetDescription(this.inputAddressString);
			this.userLayer = new VEShapeLayer();
			this.userLayer.AddShape(inputLocation);
			this.map.AddShapeLayer(this.userLayer);
		}
		
		var zoomLevel = {
			'en-IE': 6,
			'fr-LU': 8,
			'nl-BE': 7,
			'fr-BE': 7,
			'nl-NL': 7,
			'da-DK': 6,
			'pt-PT': 6,
			'ru-RU': 4,
			'hr-HR': 7,
			'cs-CZ': 6,
			'sl-SI': 8,
			'sk-SK': 7
		};
		this.initZoomLevel = zoomLevel[this.culture] || 5;
	
		if (this.data != null) {
			var initView = new VEMapViewSpecification(this.inputLatLon, this.initZoomLevel);
			if (this.dataLayer == null) this.dataLayer = new VEShapeLayer();
			
			this.dataLayer = this.addLocationsLayer(this.data, this.locs, false);
			this.map.AddShapeLayer(this.dataLayer);
			if (this.radius != null && this.culture != 'pl-PL') {
				if ($('.noResults').length == 0) this.map.AddShape(this.createRadiusLayer());
			} else if (this.singleDealerDetails) {
				this.setView(10);
			} else {
				this.setView(this.initZoomLevel);
			}
			dealers.init();
			if ($('.noResults').length > 0) {
				this.hideEachShape();
				this.map.SetMapView(initView);
			}
		} else {
			this.map.SetMapView(initView);
		}
		
		if (!$('#summaryArea .dealerSearchFieldset').length && !$('.summaryDirections').length && !$('.noResults').length) {
			var that = mazdaDealersMap,
			correctCulture = true;
			if (cookie.get('mapSearchData') != null) {
				// cookie = mkt | lat | lon | zoom | radius
				mapSearchData = cookie.get('mapSearchData').split('|');
				// is the culture correct?
				if (mapSearchData[0] !== that.culture) correctCulture = false;
					if (correctCulture) {
	 					that.autoInteraction = true;
	 					var mapSearchLatLon = new VELatLong(mapSearchData[1], mapSearchData[2]),
	  					serviceLatLon = mapSearchData[1] + ',' + mapSearchData[2],
	  					radius = parseInt(mapSearchData[4], 10);
	 					that.map.SetCenterAndZoom(mapSearchLatLon, parseInt(mapSearchData[3], 10));
	 					$.getJSON('/services/dealerajaxservice.ashx', { culture: that.culture, submissiontype: submissiontype, latlon: serviceLatLon, distance: radius }, function(json) {
	  					that.updateMap(json);
	  					that.autoInteraction = false;
	 				});
				}
			}
		}
		if (this.useAjaxHandler != null && this.useAjaxHandler == true && this.data.length == 0) this.map.AttachEvent('onchangeview', this.interactionHandler);
		if (this.showDirections && this.data.length && this.inputLatLon != null && this.inputAddressString != null) this.getDirections(this.data[0].lat, this.data[0].lon);
		
		// Handle the map scaling text
		if (this.culture != 'en-GB') {
			this.map.AttachEvent('onchangeview', this.fixMapScaling); // handles pan/zoom/mode/labels/resize // also handles onload as the map is zoomed to best view upon initialisation
			this.map.AttachEvent('oninitmode', this.fixMapScaling); // handles switching between 2d/3d
		}
	},
	
	invokeMapLoader: function() {
		var interval = setInterval(function() {
			if ((typeof(VEMap) !== 'undefined') && (typeof(document.getElementById('mapDiv').attachEvent) !== 'undefined')) {
				clearInterval(interval);
				
				// convert the inputLatLon into a VELatLong
				if (mazdaDealersMap.inputLatLon !== null) {
					var lat = mazdaDealersMap.inputLatLon.lat,
						lon = mazdaDealersMap.inputLatLon.lon;
					
					mazdaDealersMap.inputLatLon = new VELatLong(lat, lon);
				}
				
				mazdaDealersMap.loadMap();
			}
		}, 10);
	},
	
	fixMapScaling: function() {
		var fg = '', bg = '';

		// work out if we're in road or aerial view mode
		if ($('.MSVE_ScaleBarLabelFg').length) {
			// road view
			fg = 'Fg';
			bg = 'Bg';
		} else if ($('.MSVE_ScaleBarLabelFgInv').length) {
			// aerial view
			fg = 'FgInv';
			bg = 'BgInv';
		}

		// if the scaling is already in km, we don't have to do anything
		if ($('.MSVE_ScaleBarLabel' + fg).text().indexOf('km') != -1) return false;

		// otherwise, convert the miles/yrds to km/m and update the text
		$('.MSVE_ScaleBarLabel' + fg + ', .MSVE_ScaleBarLabel' + bg).each(function() {
			var scale = 0, unit = '';
	
			if ($(this).text().indexOf('miles') != -1) {
				var miles = parseInt($(this).text(), 10);
				if (miles == 0) {
	 				scale = Math.round(800 * 0.9144);
	 				unit = 'm';
				} else {
	 				scale = Math.round(miles * 1.609344);
	 				unit = 'km';
				}
			} else if ($(this).text().indexOf('yds') != -1) {
				var yds = parseInt($(this).text(), 10);
				scale = Math.round(yds * 0.9144);
				unit = 'm';
			}
	
			$(this).text(scale + ' ' + unit);
		});
	},
	
	toggleSize: function(sizeParam) {
		var sizeParam = sizeParam || 'setByUser', mapSize;
		if (sizeParam == 'setByUser') {
			cookie.kill('mazdaMapSize');
			if ($('#mapResize').attr('href') == '#expandMap') {
				mapSize = 'large';
				cookie.set('mazdaMapSize', 'large', 7);
			} else {
				mapSize = 'normal';
				cookie.set('mazdaMapSize', 'normal', 7);
			}
		} else {
			if (sizeParam == null || sizeParam == 'normal') {
				mapSize = 'normal';
			} else {
				mapSize = 'large';
			}
		}
		var w = this.defaultWidth, h = this.defaultHeight, cssObj = { width: w + 'px', height: h + 'px', borderRightWidth: '0px', borderTopWidth: '0px', marginTop: '0px' };
		if (mapSize == 'large') {
			w = this.maxWidth;
			h = this.maxHeight;
			cssObj.width = w + 'px';
			cssObj.height = h + 'px';
			cssObj.borderRightWidth = '22px';
			cssObj.borderTopWidth = '22px';
			cssObj.marginTop = '-18px';
		}
		$('#' + this.mapDiv).animate(cssObj, 250, function() {
			mazdaDealersMap.map.Resize(w, h);
		});
	},
		
	onMapResize: function() {
		var currWidth = $('#' + mazdaDealersMap.mapDiv).width(),
			el = $('#mapResize');
		if (currWidth == mazdaDealersMap.defaultWidth) {
			el.attr('href', '#expandMap');
			el.css('background-image', 'url(/images/icons/map_expand.gif)');
		} else {
			el.attr('href', '#contractMap');
			el.css('background-image', 'url(/images/icons/map_contract.gif)');
		}
	},
	
	interactionHandler: function(e) {
		var that = mazdaDealersMap;
		if (that.autoInteraction) return false;
		if (that.map.GetZoomLevel() > that.initZoomLevel && that.map.GetZoomLevel() <= 13) {
			var center = that.map.GetCenter(),
				latLon = center.Latitude + ',' + center.Longitude,
				radius = 30,
				scaleArray = $('.MSVE_ScaleBarLabelFg').text().split(' ');
			
			if (scaleArray.length > 0) radius = scaleArray[0];
			radius = that.getDistanceTranslation(radius);
			$.getJSON('/services/dealerajaxservice.ashx', { culture: that.culture, submissiontype: submissiontype, latlon: latLon, distance: radius }, function(json) {
				that.updateMap(json);
			});
			cookie.set('mapSearchData', that.culture + '|' + center.Latitude + '|' + center.Longitude + '|' + that.map.GetZoomLevel() + '|' + radius);
		}
	},
	
	updateMap: function(newData) {
		var dataToBind = [],
			that = mazdaDealersMap;

		for (var index = 0; index < newData.length; index++) {
			var dealer = newData[index];
			if (!dealerInArray(that.locs, dealer)) dataToBind.push(dealer);
		}
		that.map.AddShapeLayer(that.addLocationsLayer(dataToBind, that.locs, true));
	},
		
	setView: function(zoom) {
		var s = this.locs;
		if (this.inputLatLon != null) {
			if (s.length == 1) {
				if (!s[0].Latitude == this.inputLatLon.Latitude && !s[0].Longitude == this.inputLatLon.Longitude) {
 					s.push(this.inputLatLon);
				} else zoom = 10;
			} else s.push(this.inputLatLon);
		}
		if (this.locs.length > 1) {
			this.map.SetMapView(s);
		} else {
			var initView = new VEMapViewSpecification(s[0], zoom);
			this.map.SetMapView(initView);
		}
	},
	
	unloadMap: function() {
		if (this.map != null) {
			this.map.Dispose();
		}
	},
	
	addLocationsLayer: function(data, locs, isAddedOnDrag) {
		var that = this,
			layer = new VEShapeLayer();

		for (var index = 0; index < data.length; index++) {
			var dealer = data[index],
				itemLatLon = new VELatLong(dealer.lat, dealer.lon);
				locs.push(itemLatLon);
								
			var desc = '<div class="dealerPinPopup">';
			
			// extract dealer services array from dealer data and display in pushPin popup
			if (dealer.services !== undefined) {
				if (dealer.services.length > 0) {
 					var dslookup = {
  						sales: 'sales',
  						service: 'service',
  						parts: 'parts',
  						mpsspecialists: 'mpsspecialists',
  						zzapprovedused: 'zzapproved',
  						motability: 'motability',
  						testdrive: 'testdrive',
  						authorisedrepairers: 'authorisedrepairers',
  						mazdastore: 'mazdastore'
 					};
 					desc += '<ul class="services">';
 					for (var i in dealer.services) desc += '<li class="' + dslookup[dealer.services[i].toLowerCase()] + '"></li>';
				 	desc += '</ul>';
				}
			}
			desc += '<div class="contactInfo">';
			
			// extract dealer address from dealer data and display in pushPin popup
			if (dealer.location !== '') {
				var dealerAddr = dealer.location.split(',');
				desc += '<address>';
				if (that.culture == 'de-DE' || that.culture == 'de-AT') {
 					that.emailText = 'E-Mail:';
 					for (var i = 0; i < (dealerAddr.length - 1); i++) {
  						if (dealerAddr[i] !== '') desc += dealerAddr[i].replace(/^\s*/, '').replace(/\s*$/, '') + '<br />';
 					}
				} else {
 					for (var i in dealerAddr) {
  						if (dealerAddr[i] !== '') desc += dealerAddr[i].replace(/^\s*/, '').replace(/\s*$/, '') + '<br />';
 					}
				}
				desc += '</address>';
			}

			// extract dealer contact info from dealer data and display in pushPin popup
			var contactInfo = false;
			if (dealer.tel !== '' || dealer.fax !== '' || dealer.email !== '' || dealer.website !== '') contactInfo = true;
			if (contactInfo) desc += '<ul>';

			// Telephone label translations
			if (that.culture == 'pl-PL') {
				that.telText = 'Sprzeda&#380;:';
			}

			if (dealer.tel !== '') desc += '<li>' + that.telText + ' ' + dealer.tel + '</li>';

			// handle service numbers for Spain/Poland
			if (that.culture == 'es-ES') if (dealer.servicenumber !== '') desc += '<li>Tel. taller: ' + dealer.servicenumber + '</li>';
			if (that.culture == 'pl-PL') if (dealer.servicenumber !== '') desc += '<li>Serwis: ' + dealer.servicenumber + '</li>';

			if (dealer.fax !== '') desc += '<li>' + that.faxText + ' ' + dealer.fax + '</li>';
			if (that.culture == 'en-GB') that.emailText = 'Sales Email';
			if (typeof(dealer.email) != 'undefined' && dealer.email !== '') desc += '<li>' + that.emailText + ' <a href="mailto:' + dealer.email + '">' + dealer.email + '</a></li>';
			if (that.culture == 'es-ES') that.serviceEmailText = 'E-mail de Taller';
			if (typeof(dealer.serviceemail) != 'undefined' && dealer.serviceemail !== '') desc += '<li>' + that.serviceEmailText + ' <a href="mailto:' + dealer.serviceemail + '">' + dealer.serviceemail + '</a></li>';

			// handle sales emails - note: label text is matched from the following lookup object
			/*var salesEmailL10N = {
				'en-GB':'Sales Email:',
				setLabel: function() {
 					return (typeof(this[that.culture]) == 'undefined') ? this['default']() : this[that.culture];
				},
				default: function() {
 					return mazdaDealersMap.emailText;
				}
			};
			
			if (typeof(dealer.email) != 'undefined' && dealer.email !== '') {
				desc += '<li>' + salesEmailL10N.setLabel() + ' <a href="mailto:' + dealer.email + '">' + dealer.email + '</a></li>';
			}*/

			// handle service emails - note: label text is matched from the following lookup object
			/*var serviceEmailL10N = {
				'en-GB':'Service Email',
				'es-ES':'E-mail de Taller',
				setLabel: function() {
 					return (typeof(this[that.culture]) == 'undefined') ? this['default']() : this[that.culture];
				},
				default: function() {
 					return this['en-GB'];
				}
			};

			if (typeof(dealer.serviceemail) != 'undefined' && dealer.serviceemail !== '') {
				desc += '<li>' + serviceEmailL10N.setLabel() + ': <a href="mailto:' + dealer.serviceemail + '">' + dealer.serviceemail + '</a></li>';
			}*/

			if (that.culture == 'de-DE' || that.culture == 'de-AT') {
				if (dealer.website !== '') desc += '<li>' + that.websiteText + ' <a href="' + dealer.website + '" target="_blank">' + dealer.website + '</a></li>';
			} else {
				if (dealer.website !== '') desc += '<li>' + that.websiteText + ' <a href="' + dealer.website + '" target="_blank">' + dealer.name + '</a></li>';
			}
			
			if (contactInfo) desc += '</ul>';
			desc += '</div>';
			desc += '<ul class="dealerLinks" rel="' + dealer.id + '">';

			var linkSubstitutes = { 'formurl': mazdaDealersMap.formurl, 'dealerId': dealer.id, 'from': that.itemLatLon, 'directionText': that.getDirectionsText, 'detailText': that.viewDetailsText, 'testdriveText': that.testDriveText, 'selectText': that.selectDealerText, 'testDriveUrl': dealer.testdriveurl };

			if (!that.singleDealerDetails) {
				if (that.isDealerLocator) {
 					desc += that.viewDetailsLink.substitute(linkSubstitutes);
 					var directionExceptions = ['tr-TR', 'ru-RU', 'hr-HR', 'pl-PL', 'hu-HU', 'cs-CZ', 'sk-SK' ,'sl-SI' ];
						if (directionExceptions.toString().indexOf(that.culture) == -1) { // proceed if not found in exception list
  						desc += that.getDirectionsLink.substitute(linkSubstitutes);
 					}
 					var testDriveExceptions = ['fr-CH', 'de-CH', 'it-CH', 'da-DK'];
 					if (testDriveExceptions.toString().indexOf(that.culture) == -1) { // proceed if not found in exception list
  						if (dealer.testdriveurl != "") {
   							desc += that.testDriveLink.substitute(linkSubstitutes);
  						}
 					}
				} else {
 					desc += that.selectDealerLink.substitute(linkSubstitutes);
				}
			}
			
			desc += '</ul>';

			// Sophus tracking for dealer map pop-ups...
			// fires a tc_log call if its parent's visibility is visible after 1 second
			// avoids false calls when pins are simply hovered but not intended
			// *** Updated on 15/11/10
			// Adds each viewed id to a global array and only calls tc_log if the id hasn't already been viewed
			if (!that.singleDealerDetails) {
				var trackingScript = '<script type="text/javascript">\
    								var form_type = (mazdaDealersMap.isDealerLocator) ? \'dealerlocator\' : \'testdrive\';\
        							window.setTimeout(function() { var parent = $(\'.dealerLinks:visible\').parents(\'.ero\'); if (parent.css(\'visibility\') === \'visible\' && mazdaDealersMap.dealersViewed.toString().indexOf($(\'.dealerLinks\', parent).attr(\'rel\')) == -1) { tc_log(pageurl + form_type + \'_map_dealerdetails.htm?firststep=1&dealerId=\' + $(\'.dealerLinks\', parent).attr(\'rel\')); mazdaDealersMap.dealersViewed.push($(\'.dealerLinks\', parent).attr(\'rel\')); } }, 1500);\
       								</script>';
				desc += trackingScript;
			}
			
			desc += '</div>';
			
			var pin = new VEShape(VEShapeType.Pushpin, itemLatLon),
				formattedImg = { "src": that.pushpinUrls[1].substitute({ "letter": that.getMarkerImg(index) }), "dealerId": dealer.id };
			if (isAddedOnDrag) formattedImg = { "src": that.pushpinUrls[4], "dealerId": dealer.id };
			if (that.singleDealerDetails) formattedImg = { "src": that.pushpinUrls[3], "dealerId": dealer.id };
			pin.SetCustomIcon(that.pushpinTemplate.substitute(formattedImg));
			pin.SetTitle(dealer.name);
			pin.SetDescription(desc);
			layer.AddShape(pin);
			
			// Enable pin clustering
			var clusterOptions = new VEClusteringOptions();
			clusterOptions.Icon = new VECustomIconSpecification();
			clusterOptions.Icon.Image = '/images/markers/cluster.gif';
			layer.SetClusteringConfiguration(VEClusteringType.Grid, clusterOptions);
		}
		return layer;
	},
	
	createRadiusLayer: function() {
		var earthRadius = 6371,
			lat = (this.inputLatLon.Latitude * Math.PI) / 180,
			lon = (this.inputLatLon.Longitude * Math.PI) / 180;
				
		// increase the radius diameter slightly to avoid overlapping results
		var radius = this.radius,
			radiusAdjust = (radius == 100) ? 1.1 : 1.2,
			newRadius = radius * radiusAdjust,
			d = parseFloat(newRadius) / earthRadius,
			points = new Array();
			
		for (i = 0; i < 360; i++) {
			var point = new VELatLong(0, 0),
				bearing = i * Math.PI / 180; // rad
				
			point.Latitude = Math.asin(Math.sin(lat) * Math.cos(d) + Math.cos(lat) * Math.sin(d) * Math.cos(bearing));
			point.Longitude = ((lon + Math.atan2(Math.sin(bearing) * Math.sin(d) * Math.cos(lat), Math.cos(d) - Math.sin(lat) * Math.sin(point.Latitude))) * 180) / Math.PI;
			point.Latitude = (point.Latitude * 180) / Math.PI;
			points.push(point);
		}
		
		var circle = new VEShape(VEShapeType.Polygon, points);
		circle.HideIcon();
		circle.SetLineColor(new VEColor(0, 108, 184, 0.5));
		circle.SetFillColor(new VEColor(166, 218, 255, 0.3));
		window.setTimeout(function() {
			mazdaDealersMap.map.SetMapView(points);
		}, 500);
		return circle;
	},
	
	getMarkerImg: function(j) {
		var letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
		return letters.charAt(j);
	},
	
	getDirections: function(lat, lon) {
		// this condition stops the directions from populating automatically
		if (!$('#summaryArea .summaryDirections').length) {
			this.userLayer.DeleteAllShapes();
			return false;
		}
		var options = new VERouteOptions(),
			that = this;
		
		options.DistanceUnit = (that.culture == 'en-GB') ? VERouteDistanceUnit.Mile : VERouteDistanceUnit.Kilometer;
		options.RouteOptimize = (that.shortestRouteOption != 'time') ? VERouteOptimize.MinimizeDistance : VERouteOptimize.MinimizeTime;
		options.RouteCallback = that.onGotRoute;
		options.SetBestMapView = true;
		options.RouteZIndex = 9999;
		
		if (that.routeOption != null) {
			if (that.routeOption == 'roundTrip') {
				that.map.GetDirections([that.inputLatLon, new VELatLong(lat, lon), that.inputLatLon], options);
				options.SetBestMapView = false;
			} else if (that.routeOption == 'reverseTrip') {
				that.map.GetDirections([new VELatLong(lat, lon), that.inputLatLon], options);
			}
		} else {
			that.map.GetDirections([that.inputLatLon, new VELatLong(lat, lon)], options);
		}
	},
	
	onGotRoute: function(route) {
		var that = mazdaDealersMap;
		that.hideEachShape(); // hide existing pins
		
		var legs = route.RouteLegs,
			turns = '',
			numTurns = 0,
			leg = null,
			validRoute = false;
		
		for (var i = 0; i < legs.length; i++) {
			leg = legs[i]; // leg is a VERouteLeg object
			if (i == 0) { // from A to B
				turns += '<ul class="startEnd">';
				if (that.routeOption == 'reverseTrip') {
	 				turns += '<li class="start"><span>' + that.fromText + '</span> <strong>' + that.data[0].name + '</strong></li>';
	 				turns += '<li class="end"><span>' + that.toText + '</span> <strong>' + that.inputAddressString + '</strong></li>';
				} else {
	 				turns += '<li class="start"><span>' + that.fromText + '</span> <strong>' + that.inputAddressString + '</strong></li>';
	 				turns += '<li class="end"><span>' + that.toText + '</span> <strong>' + that.data[0].name + '</strong></li>';
				}
				turns += '</ul>';
			}
			if (i == 1) { // from B to A
				turns += '<ul class="startEnd roundTrip">';
				turns += '<li class="start"><span>' + that.fromText + '</span> <strong>' + that.data[0].name + '</strong></li>';
				turns += '<li class="end"><span>' + that.toText + '</span> <strong>' + that.inputAddressString + '</strong></li>';
				turns += '</ul>';
			}
			turns += '<h4>' + that.totalDistanceText + ': ' + route.Distance.toFixed(1) + ' ' + that.getUnits() + ' <span class="journeyTime">' + that.timeHandler(leg.Time) + '</span></h4>';
			
			var turn = null,
				turnHint = null,
				itinItems = legs[0].Itinerary.Items;
				
			// set start icon
			itinItems[0].Shape.SetCustomIcon(that.pushpinUrls[2]);
			// set end icon
			itinItems[itinItems.length - 1].Shape.SetCustomIcon(that.pushpinUrls[3]);
			// remove default end icon from roundTrip leg
			if (i == 1) legs[1].Itinerary.Items[legs[1].Itinerary.Items.length - 1].Shape.Hide();
	
			for (var j = 0; j < leg.Itinerary.Items.length; j++) {
				turn = leg.Itinerary.Items[j];
				turnHint = turn.Hints;
				numTurns++;
				turns += '<div class="itinStep" rel="' + turn.Shape.Primitives[0].iid + '"><em class="stepNum">' + turn.Shape.Title + '</em><span>' + turn.Text + '</span><em class="stepDis">' + turn.Distance.toFixed(1) + ' ' + that.getUnits() + '</em>';
				if (turnHint != null) {
	 				turns += '<ul class="hints">';
	 				for (var h in turnHint) {
	  					turns += '<li><em>' + turnHint[h].Text + '</em></li>';
	 				}
	 				turns += '</ul>';
				}
				turns += '</div>';
			}
			validRoute = true;
		}
		
		if (validRoute) {
			$('.dealerDirections .itinerary').append(turns);
			$('.dealerDirections .itinerary .itinStep:odd').css('background-color', '#eff9ff');
			
			// Add mouseover relationship between direction steps and map icons
			// $('.itinStep').mouseover(function() {
				//  var relId = $(this).attr('rel');
				//  $('div', '#'+relId).mouseover();
			// });
			
			// Create and append close directions link
			var clearDirectionsLink = '<br /><a href="#clearDirections" onclick="mazdaDealersMap.clearRoute()">' + that.clearDirectionsText + '</a>';
			$('.dealerDirections .itinerary').append(clearDirectionsLink);
			
			// Display the directions
			$('.dealerDirections').slideDown(300, function() {
				// Set the stepNum column width (padding allowance) by checking the text lengths
				var stepNumWidth = 0;
				$('.stepNum').each(function() {
		 			stepNumWidth = ($(this).width() > stepNumWidth) ? $(this).width() : stepNumWidth;
				});
				
				$('.itinStep span, .itinerary .itinStep .hints').css('padding-left', (stepNumWidth + 14) + 'px');
		
				// IE7 display fix
				$(this).show(function() {
		 			$('.ie7 .dealerDirections .itinerary').hide().show();
				});
				
				that.resetRouteTrips();
			});
		}
	},
	
	clearRoute: function() {
		var that = mazdaDealersMap;
		try {
			that.map.DeleteRoute();
			that.map.SetCenter(that.inputLatLon);
			that.setView(that.locs);
			$('.dealerDirections .itinerary').empty();
			
			$('.dealerDirections').slideUp(300, function() {
				$(this).hide(function() {
	 				//$('.ie7 .dealerDirections .itinerary').css({ 'position':'static' });
				});
			});
			
			that.showEachShape();
			that.userLayer.DeleteAllShapes();
		} catch (err) {
			alert(err.message);
		}
	},
	
	resetRouteTrips: function() {
		$('#summaryArea .directionActions input').attr('checked', false);
		mazdaDealersMap.routeOption = null;
		colourOpeningTimeRows();
	},
	
	hideEachShape: function() {
		if (this.dataLayer != null) {
			for (var i = 0; i < this.dataLayer.GetShapeCount(); i++) {
				var shape = this.dataLayer.GetShapeByIndex(i);
				shape.Hide();
			}
		}
	
		if (this.userLayer != null) {
			for (var i = 0; i < this.userLayer.GetShapeCount(); i++) {
				var shape = this.userLayer.GetShapeByIndex(i);
				shape.Hide();
			}
		}
	},
	
	showEachShape: function() {
		for (var i = 0; i < this.dataLayer.GetShapeCount(); i++) {
			var shape = this.dataLayer.GetShapeByIndex(i);
			shape.Show();
		}
	
		for (var i = 0; i < this.userLayer.GetShapeCount(); i++) {
			var shape = this.userLayer.GetShapeByIndex(i);
			shape.Show();
		}
	},
	
	timeHandler: function(time) {
		var timeStr = '',
			secs = parseInt(time, 10),
			hours = Math.floor(secs / 3600);
			
		if (hours > 0) timeStr += hours + ' ' + this.hourText + ' ';
		var minutes = Math.floor((secs % 3600) / 60);
		if (minutes > 0) timeStr += minutes + ' ' + this.minuteText;
		return timeStr;
	},
	
	getDistance: function(latlong1, latlong2, miles) {
		var lat1 = this.getDegtoRad(latlong1.Latitude),
			lon1 = this.getDegtoRad(latlong1.Longitude),
			lat2 = this.getDegtoRad(latlong2.Latitude),
			lon2 = this.getDegtoRad(latlong2.Longitude),
			dLat = lat2 - lat1,
			dLon = lon2 - lon1,
			cordLength = Math.pow(Math.sin(dLat / 2), 2) + Math.cos(lat1) * Math.cos(lat2) * Math.pow(Math.sin(dLon / 2), 2),
			centralAngle = 2 * Math.atan2(Math.sqrt(cordLength), Math.sqrt(1 - cordLength));
		
		return this.getEarthRadius() * centralAngle;
	},
	
	getUnits: function() {
		return this.culture == 'en-GB' ? this.mileText : this.kmText;
	},
	
	getDistanceTranslation: function(distance) {
		if (this.culture == 'en-GB') return (parseFloat(distance) / 0.621371192).toFixed(0);
		return distance;
	},
	
	getEarthRadius: function(miles) {
		var earthRadius = 6367;
		if (miles) return earthRadius * 0.621371192;
			return earthRadius;
		},
	
	getDegtoRad: function(x) {
		return x * Math.PI / 180;
	}
};

String.prototype.substitute = function(object) {
	return this.replace(/{[^{}]+}/g, function(key) {
		return object[key.replace(/[{}]+/g, "")] || "";
	});
};

function dealerInArray(array, obj) {
	for (var i = 0; i < array.length; i++) {
		if (array[i].Latitude == obj.lat && array[i].Longitude == obj.lon) return true;
	}
	return false;
}
