function BranchLocator() {
	
	var map;
	var geo;
	var userPt;
	var reasons = [];
	var markersAddedToMap = false;
	var gmarkers = [];

	
	this.init = function() {
		map = new GMap(document.getElementById("branch_locator_map"));
		map.addControl(new GLargeMapControl());
		map.addControl(new GMapTypeControl());

		// ====== Create a Client Geocoder ======
		geo = new GClientGeocoder();
		
		// ====== Array for decoding the failure codes ======
		reasons[G_GEO_SUCCESS] = "Success";
		reasons[G_GEO_MISSING_ADDRESS] = "Missing Address: The address was either missing or had no value.";
		reasons[G_GEO_UNKNOWN_ADDRESS] = "Please check the details and try again.";
		reasons[G_GEO_UNAVAILABLE_ADDRESS] = "Unavailable Address:  The geocode for the given address cannot be returned due to legal or contractual reasons.";
		reasons[G_GEO_BAD_KEY] = "Bad Key: The API key is either invalid or does not match the domain for which it was given";
		reasons[G_GEO_TOO_MANY_QUERIES] = "Too Many Queries: The daily geocoding quota for this site has been exceeded.";
		reasons[G_GEO_SERVER_ERROR] = "Server error: The geocoding request could not be successfully processed.";
		
		if(typeof(branch_locator_initial_longitude) != "undefined" && typeof(branch_locator_initial_latitude) != "undefined")
		{
			//bring up the markers
			this.setUserPt(branch_locator_initial_latitude, branch_locator_initial_longitude);
			
		}
		else
		{
			map.setCenter(new GLatLng(54.622978, -2.592773), 6);
		}

		if(search_input)
		{
			document.getElementById("branch_locator_search").value = search_input;
			this.showAddress();
		}

	}

    // A function to create a tabbed marker and set up the event window
    this.createMarker = function createTabbedMarker(point, name, html1, html2, label1, label2) {
      var marker = new GMarker(point, {title:name});
      GEvent.addListener(marker, "click", function() {
        marker.openInfoWindowTabsHtml([new GInfoWindowTab(label1,html1), new GInfoWindowTab(label2,html2)]);
      });
      return marker;
    }


	this.showAddress = function() {
		var locator = this;
		var search = document.getElementById("branch_locator_search").value + ", uk";	
		// ====== Perform the Geocoding ======        
		geo.getLocations(search, function(result) {
			//map.clearOverlays(); 
				if (result.Status.code == G_GEO_SUCCESS) {
					// ===== If there was more than one result, "ask did you mean" on them all =====
				if (result.Placemark.length > 1) {
					document.getElementById("branch_locator_message").innerHTML = "Did you mean:";
					// Loop through the results
					for ( var i = 0; i < result.Placemark.length; i++) {
						var p = result.Placemark[i].Point.coordinates;
						document.getElementById("branch_locator_message").innerHTML += "<br>"
								+ (i + 1) + ": <a href='javascript:BranchLocator.instance.setUserPt("
								+ p[1] + "," + p[0] + ")'>"
								+ result.Placemark[i].address + "<\/a>";
					}
				}
				// ===== If there was a single marker =====
				else {
					document.getElementById("branch_locator_message").innerHTML = "";
					var p = result.Placemark[0].Point.coordinates;
					locator.setUserPt(p[1], p[0]);
				}
			}
			// ====== Decode the error status ======
			else {
				var reason = "Code " + result.Status.code;
				if (reasons[result.Status.code]) {
					reason = reasons[result.Status.code]
				}
				var message = 'Sorry, we could not find "' + search + '". ' + reason;
				document.getElementById("branch_locator_message").innerHTML="<span id='branch_locator_message_text'>&nbsp;</span>";
				var e = document.getElementById("branch_locator_message_text");
				if (e.textContent) {
					e.textContent = message;
				} else {
					e.innerText = message;
				}
			}
		});
	}

	this.generateDataProperties = function() {
		var data = markerData;
		var length = data.length;

		
		for ( var i = 0; i < length; i++) {
			var row = data[i];
			if (!row) continue;
			row.point = new GLatLng(row.latitude, row.longitude);
			var addr = [];
			if (row.addressLine1) addr.push(row.addressLine1);
			if (row.addressLine2) addr.push(row.addressLine2);
			if (row.addressLine3) addr.push(row.addressLine3);
			if (row.addressLine4) addr.push(row.addressLine4);
			if (row.postCode) addr.push(row.postCode);
			addr = addr.join("<br/>");
			var hours = row.openingHours;
			hours = hours.replace(/,/g,"<br/>");
					
			// Directions Form
			directions_html = '<form action="http://maps.google.co.uk/maps" method="get" target="_blank" class="getDirctions">' + '<fieldset>' + '<legend>' + "Get directions from Google" + '</legend>' + '<label for="saddr">' + "Your location " + '</label>' + '<input type="text" name="saddr" id="saddr" value="" />' + '<button type="submit" value="Go" />Go</button>' + '<p class="promptForDirections">Address, postcode or town</p>' + '<input type="hidden" name="daddr" value="' + row.point + '" />' + '<input type="hidden" name="hl" value="en" />' + '</fieldset>' + '</form>';

			row.html1 = "<h4 class='branchLocatorHeading'>" + row.branchName + " Branch" + "</h4>" + "<address class='branchAddress'>" + addr + "</address>" + "<p class='telephone' title='Telephone number'>" + row.telephone + "</p>" + directions_html;
			row.html2 = "<h4 class='branchLocatorHeading'>" + "Opening Hours" + "</h4>" + hours;
			row.label1 = "Contact";
			row.label2 = "Hours";
		}
	}

	// ====== Plot a marker after positive reponse to "did you mean" ======
	this.setUserPt = function(lat, lng) {
		userPt = new GLatLng(lat, lng);
		this.updateMap();
	}

	this.updateMap = function() {
		if (!userPt)
			return;
		this.computeDistances();
		this.sortMarkers();
		this.setCenterWithBounds();
		this.addMarkersToMap();
		var nearest = markerData[0];
		nearest.marker.openInfoWindowTabsHtml([new GInfoWindowTab(nearest.label1,nearest.html1), new GInfoWindowTab(nearest.label2,nearest.html2)]);
	}

	this.computeDistances = function() {
		var data = markerData;
		var length = data.length;
		var pt = userPt;
		for ( var i = 0; i < length; i++) {
			var row = data[i];
			if (row) row.distance = row.point.distanceFrom(pt);
		}
	}

	this.sortMarkers = function() {
		markerData.sort(function(pt1, pt2) {
			return pt1.distance - pt2.distance;
		});
	}

	this.setCenterWithBounds = function() {
		var bounds = new GLatLngBounds();
		bounds.extend(userPt);
		var data = markerData;
		var lastDist;
		for ( var i = 0; i < 3; i++) {
			var row = data[i];
			var dist = row.distance;
			if (lastDist && dist > lastDist * 3)
				break;
			bounds.extend(row.point);
			lastDist = dist;
		}
		var z = map.getBoundsZoomLevel(bounds) - 1;
		var c = bounds.getCenter();
		map.setCenter(c, z);
	}

	this.addMarkersToMap = function() {
		if (!markersAddedToMap) {
			var data = markerData;
			var length = data.length;
			for ( var i = 0; i < length; i++) {
				var row = data[i];
				if (!row) continue;
				var marker = this.createMarker(row.point, "Newey & Eyre " + row.branchName, row.html1, row.html2, row.label1, row.label2)
				map.addOverlay(marker);
				row.marker = marker;
			}
			markersAddedToMap = true;
		}
	} 		
}

BranchLocator.instance = new BranchLocator();

if (GBrowserIsCompatible()) {
	BranchLocator.instance.generateDataProperties();
} else {
	alert("Sorry, the Google Maps API is not compatible with this browser");
}