	/* CONSTANTS */
	zoom1 = 5;  
	zoom2 = 9;
	zoom3 = 12;
	zoom4 = 14;
	zIn = "in";
	zOut = "out";
	root = "";
	/* END CONSTANTS */

	var map;
	var zoomLevel = zoom1;
	var tileLayerOverlayMobile;
	var tileLayerOverlayMBB;
	var marker = "temp";
	var geocoder = new GClientGeocoder();
	geocoder.setBaseCountryCode("uk");
	var mapType;

	function gup( name )
	{
		name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
		var regexS = "[\\?&]"+name+"=([^&#]*)";
		var regex = new RegExp( regexS );
	  var results = regex.exec( window.location.href );
	  if( results == null )
	    return "";
	  else
	    return results[1];
	}

	function validatePostCode( postCode )
	{
		var regexS_Full = "[a-zA-Z]{1,2}[0-9]{1,2}[0-9a-zA-Z]?[0-9][a-zA-Z]{2}$";
		var regexS_Half = "[a-zA-Z]{1,2}[0-9]{1,2}$";
		var regex_Full = new RegExp( regexS_Full );
		var regex_Half = new RegExp( regexS_Half );
		var cleanPostCode = postCode.replace(new RegExp(" ", "g" ), '');
	  var results1 = regex_Full.exec( cleanPostCode );
	  var results2 = regex_Half.exec( cleanPostCode );
	  if( results2 == null && results1 == null )
			return null;
		else
		  return 'valid';
	}
	
	function TextualZoomControl() {
	}
	TextualZoomControl.prototype = new GControl();
	TextualZoomControl.prototype.initialize = function(map) {
		var container = document.createElement("div");

		var panDiv = document.createElement("img");
		panDiv.src = "/static/images/functional_apps/coverage/panZoomControls.png";
		panDiv.style.width = "59px";
		panDiv.style.height = "110px";
		container.appendChild(panDiv);

		var panNdiv = document.createElement("div");
		panNdiv.style.width = "18px";
		panNdiv.style.height = "15px";
		panNdiv.style.position = "absolute";
		panNdiv.style.left = "20px";
		panNdiv.style.top = "3px";
		panNdiv.style.cursor = "pointer";
		if (navigator.appName == 'Microsoft Internet Explorer')
		{
			panNdiv.style.backgroundColor = "white";
			panNdiv.style.filter = "alpha(opacity=1)";
		}
		container.appendChild(panNdiv);
		GEvent.addDomListener(panNdiv, "click", function() {panN();});
		
		var panSdiv = document.createElement("div");
		panSdiv.style.width = "18px";
		panSdiv.style.height = "15px";
		panSdiv.style.position = "absolute";
		panSdiv.style.left = "20px";
		panSdiv.style.top = "37px";
		panSdiv.style.cursor = "pointer";
		if (navigator.appName == 'Microsoft Internet Explorer')
		{
		panSdiv.style.backgroundColor = "white";
		panSdiv.style.filter = "alpha(opacity=1)";
		}
		container.appendChild(panSdiv);
		GEvent.addDomListener(panSdiv, "click", function() {panS();});
		
		var panEdiv = document.createElement("div");
		panEdiv.style.width = "12px";
		panEdiv.style.height = "18px";
		panEdiv.style.position = "absolute";
		panEdiv.style.left = "40px";
		panEdiv.style.top = "19px";
		panEdiv.style.cursor = "pointer";
		if (navigator.appName == 'Microsoft Internet Explorer')
		{
		panEdiv.style.backgroundColor = "white";
		panEdiv.style.filter = "alpha(opacity=1)";
		}
		container.appendChild(panEdiv);
		GEvent.addDomListener(panEdiv, "click", function() {panE();});
		
		var panWdiv = document.createElement("div");
		panWdiv.style.width = "12px";
		panWdiv.style.height = "18px";
		panWdiv.style.position = "absolute";
		panWdiv.style.left = "7px";
		panWdiv.style.top = "19px";
		panWdiv.style.cursor = "pointer";
		if (navigator.appName == 'Microsoft Internet Explorer')
		{
		panWdiv.style.backgroundColor = "white";
		panWdiv.style.filter = "alpha(opacity=1)";
		}
		container.appendChild(panWdiv);
		GEvent.addDomListener(panWdiv, "click", function() {panW();});
		
		var zoomInDiv = document.createElement("div");
		zoomInDiv.style.width = "19px";
		zoomInDiv.style.height = "21px";
		zoomInDiv.style.position = "absolute";
		zoomInDiv.style.left = "20px";
		zoomInDiv.style.top = "65px";
		zoomInDiv.style.cursor = "pointer";
		if (navigator.appName == 'Microsoft Internet Explorer')
		{
		zoomInDiv.style.backgroundColor = "white";
		zoomInDiv.style.filter = "alpha(opacity=1)";
		}
		container.appendChild(zoomInDiv);
		GEvent.addDomListener(zoomInDiv, "click", function() {zoom("in");});

		var zoomOutDiv = document.createElement("div");
		zoomOutDiv.style.width = "19px";
		zoomOutDiv.style.height = "21px";
		zoomOutDiv.style.position = "absolute";
		zoomOutDiv.style.left = "20px";
		zoomOutDiv.style.top = "87px";
		zoomOutDiv.style.cursor = "pointer";
		if (navigator.appName == 'Microsoft Internet Explorer')
		{
		zoomOutDiv.style.backgroundColor = "white";
		zoomOutDiv.style.filter = "alpha(opacity=1)";
		}
		container.appendChild(zoomOutDiv);
		GEvent.addDomListener(zoomOutDiv, "click", function() {zoom("out");});

		map.getContainer().appendChild(container);
		return container;
	}
	TextualZoomControl.prototype.getDefaultPosition = function() {
		return new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(7, 7));
	}

	function initMobile(serverUrl) {
	  mapType = "mobile";
	  google.load("search", "1");
	  
	  if (serverUrl == "172.30.152.123:90")
	  {
	  	root = "www.three.co.uk:80";
	  }
	  else
	  {
	  	root = serverUrl;
	  }
		if (GBrowserIsCompatible()) {
			map = new GMap2(document.getElementById("map"));
			map.setCenter(new GLatLng(55.5, -4.0), zoom1);
			map.disableDoubleClickZoom();

			var tileLayerMobile = new GTileLayer(new GCopyrightCollection("3"), zoom1, zoom4);
			tileLayerMobile.getOpacity = function () { return 1.0; };
			tileLayerMobile.isPng = function () { return true; };
			tileLayerMobile.getTileUrl = function (tile, zoom) { 
				var ymax = 1 << zoom;
				var y = ymax - tile.y -1;
				return "http://" + root + "/static/images/functional_apps/coverage/Mobile/" + zoom + "/" + tile.x + "/" + y + ".png"; };
			tileLayerOverlayMobile = new GTileLayerOverlay(tileLayerMobile);
			map.addOverlay(tileLayerOverlayMobile);

			/* Go through the zoom levels to force some of the layers */
			map.setCenter(new GLatLng(55.5, -4.0), zoom4);
			map.setCenter(new GLatLng(55.5, -4.0), zoom3);
			map.setCenter(new GLatLng(55.5, -4.0), zoom2);
			map.setCenter(new GLatLng(55.5, -4.0), zoom1);
			map.addControl(new TextualZoomControl());
			GEvent.addListener(map, "dragstart", function() {
				closeError();
			});
		}
		setUpHelp();
  }

	function initMBB(serverUrl) {
	  mapType = "mbb";
	  google.load("search", "1");
	  
	  if (serverUrl == "172.30.152.123:90")
	  {
		root = "www.three.co.uk:80";
	  }
	  else
	  {
		root = serverUrl;
	  }
		if (GBrowserIsCompatible()) {
			map = new GMap2(document.getElementById("map"));
			map.setCenter(new GLatLng(55.5, -4.0), zoom1);
			map.disableDoubleClickZoom();
		
			var tileLayerMBB = new GTileLayer(new GCopyrightCollection("3"), zoom1, zoom4);
			tileLayerMBB.getOpacity = function () { return 1.0; };
			tileLayerMBB.isPng = function () { return true; };
			tileLayerMBB.getTileUrl = function (tile, zoom) { 
				var ymax = 1 << zoom;
				var y = ymax - tile.y -1;
				return "http://" + root + "/static/images/functional_apps/coverage/MBB/" + zoom + "/" + tile.x + "/" + y + ".png";
			};
			tileLayerOverlayMBB = new GTileLayerOverlay(tileLayerMBB);
			map.addOverlay(tileLayerOverlayMBB);
		
			/* Go through the zoom levels to force some of the layers */
			map.setCenter(new GLatLng(55.5, -4.0), zoom4);
			map.setCenter(new GLatLng(55.5, -4.0), zoom3);
			map.setCenter(new GLatLng(55.5, -4.0), zoom2);
			map.setCenter(new GLatLng(55.5, -4.0), zoom1);
			map.addControl(new TextualZoomControl());
			GEvent.addListener(map, "dragstart", function() {
				closeError();
			});
		}
		setUpHelp();
	}
    
	function zoom(direction) {
		var currentLat = map.getCenter();
		setZoomLevel(direction);
		map.setCenter(currentLat, zoomLevel);
	}
	
	function zoomTo(level) {
		map.setCenter(map.getCenter(), level);
		zoomLevel = level;
	}
	
	function setZoomLevel(direction)
	{
		//Get the map's actual zoom in case it's not at one of the four presets
		var currentZoom = map.getZoom();
		if (direction == zIn)
		{
			if (currentZoom < zoom1) {
				zoomLevel = zoom1;
			}
			else if (currentZoom < zoom2) {
				zoomLevel = zoom2;
			}
			else if (currentZoom < zoom3) {
				zoomLevel = zoom3;
			}
			else if(currentZoom < zoom4){
				zoomLevel = zoom4;
			}
			else{
				showErrorFade("It's not possible to zoom any further");
			}
		}
		else if (direction == zOut) {
			if (currentZoom > zoom4) {
				zoomLevel = zoom4;
			}
			else if (currentZoom > zoom3) {
				zoomLevel = zoom3;
			}
			else if (currentZoom > zoom2) {
				zoomLevel = zoom2;
			}
			else if (currentZoom > zoom1){
				zoomLevel = zoom1;
			}
			else{
				showErrorFade("It's not possible to zoom any further");
			}
		}
	}
    
	function panN ()
	{
		map.panDirection(0,+1);
	}
    
	function panS ()
	{
		map.panDirection(0,-1);
	}
    
	function panE ()
	{
		map.panDirection(-1,0);
	}
    
	function panW ()
	{
		map.panDirection(+1,0);
	}

	function overlayNone() {
		currentmarker = marker;
		map.clearOverlays();

		if (marker != "temp")
		{
			map.addOverlay(currentmarker);
		}
	}

	function overlayMobile() {
		currentmarker = marker;
		map.clearOverlays();

		if (marker != "temp") {
			map.addOverlay(currentmarker);
		}
		map.addOverlay(tileLayerOverlayMobile);
	}

	function overlayMBB() {
		currentmarker = marker;
		map.clearOverlays();

		if (marker != "temp") {
			map.addOverlay(currentmarker);
		}
		map.addOverlay(tileLayerOverlayMBB);
	}

	function markPoint(point) {
		if (marker != "temp")
		{
   	  map.removeOverlay(marker);
   	}
    map.setCenter(point, zoomLevel);
		zoomTo(zoom4);
		marker = new GMarker(point);
		map.addOverlay(marker);
	}

	function showPointFromMulti(lat, lon, address) {
		var point = new GLatLng(lat, lon);
		markPoint(point);
		document.getElementById("multi-addresses").style.display="none";
		document.getElementById("multi-addresses").innerHTML="";
		geocoder.getLocations(point,function(jsonResp) {
			var partialPostcode = jsonResp.Placemark[0].AddressDetails.Country.AdministrativeArea.SubAdministrativeArea.Locality.PostalCode.PostalCodeNumber;
			executeMaintenanceLookup(partialPostcode,address);
		});
	}

	function showAddress(address) {
		document.getElementById("multi-addresses").style.display="none";
		document.getElementById("error-text").style.display="none";
		document.getElementById("addressfld").value=address;
		document.getElementById("postcodefld").value="";
		if (geocoder) {
			geocoder.getLocations(address + ",uk",function(response) {
				var addresses = "";
				var point;
				if (response && response.Status.code == 200) {
					if (response.Placemark.length == 1) {
						point = new GLatLng(response.Placemark[0].Point.coordinates[1], 
						response.Placemark[0].Point.coordinates[0]);
						markPoint(point);
						geocoder.getLocations(point,function(jsonResp) {
							var partialPostcode = jsonResp.Placemark[0].AddressDetails.Country.AdministrativeArea.SubAdministrativeArea.Locality.PostalCode.PostalCodeNumber;
							executeMaintenanceLookup(partialPostcode,address);
							eraseCookie("CoverageAddress");
							eraseCookie("CoveragePostcode");
							createCookie("CoverageAddress",address,0);
						});
					} else {
						for (var i=0;i<response.Placemark.length;i++) {
							addresses += "<a href=\"#\" onclick=\"javascript:showPointFromMulti(" + 
							response.Placemark[i].Point.coordinates[1] + "," +
							response.Placemark[i].Point.coordinates[0] + ",'"+address+"')\" >" +
							response.Placemark[i].address + "</a><br/>";
						}
						document.getElementById("multi-addresses").innerHTML=addresses;
						$('#multi-addresses').fadeIn();
					}
				} else {
					showError("Address not found");
				}
			});
		}
	}    

	function showPostcode(postcode) {
    document.getElementById("multi-addresses").style.display="none";
	  document.getElementById("error-text").style.display="none";
	  document.getElementById("addressfld").value="";
	  document.getElementById("postcodefld").value=postcode;
		localSearch = new google.search.LocalSearch();
		localSearch.setSearchCompleteCallback(null,
			function() {
				if (localSearch.results[0]) {    
					var resultLat = localSearch.results[0].lat;
					var resultLng = localSearch.results[0].lng;
					var point = new GLatLng(resultLat,resultLng);
					markPoint(point);
					executeMaintenanceLookup(postcode,null);
					eraseCookie("CoverageAddress");
					eraseCookie("CoveragePostcode");
					createCookie("CoveragePostcode",postcode,0);
				}else{
					geocoder.getLatLng(
						postcode + ",uk",
						function(point) {
							if (point) {
								markPoint(point);
								executeMaintenanceLookup(postcode,null);
								eraseCookie("CoverageAddress");
								eraseCookie("CoveragePostcode");
								createCookie("CoveragePostcode",postcode,0);
							}
							else {
								showError("Postcode not found");
							}
						}
					);
				}
			}
		);
		if (validatePostCode( postcode) == 'valid') {
			postcode = postcode.replace(/^\s*|\s*$/,"");
			localSearch.execute(postcode + ",uk");
		} else {
			showError("Please enter a valid postcode");
		}
	}

	function showError(msg)
	{
		document.getElementById("error-text").innerHTML=msg;
		$('#error-text').fadeIn();
	}
	
	function showErrorFade(msg)
	{
		$('#error-text').fadeIn();
		document.getElementById("error-text").innerHTML=msg;
		setTimeout("$('#error-text').fadeOut()", 5000);
	}
	
	function closeError()
	{
		$('#error-text').fadeOut();
	}

	function executeMaintenanceLookup(srhPostcode,address) {
		var alwaysShow = gup("alwaysShow");
		var plannedWork = "";
		var xmlPostcode;
		var startDate;
		var finishDate;
		var i = 0;
		var j = 0;
		var previousWork = "";
		var previousFlag;
		map.closeInfoWindow(); 
		$.ajax({
			type: "GET",
			url: "/maintenance/lookup?postcode="+srhPostcode,
			dataType: "xml",
			success: function(xml) {
				var status = $(xml).find('status').text();
				var congestion = $(xml).find('congestion').text();
				var congestionText = "";
				if(congestion == "true" && mapType == "mbb")
				{
					congestionText = "<span class=\'congestion_headline\'>About to get Mobile Broadband?</span><br />Lots of people are using our network in this area which will affect the service for new customers.<br /><a href=\"/Help_Support/Coverage/Mobile_Broadband_coverage/Your_area\">What does this mean for you now?</a><br /><br />";
				}
				
				xmlPostcode = $(xml).find('planned').attr('postcode');
				if (status == "0") {
					$(xml).find('maintenance').each(function(){i++});
					$(xml).find('maintenance').each(function(){
						j++;
						previousFlag = $(this).attr('previous');
						if(previousFlag == 'true')
						{
							if (previousWork != "" && i == j) {
							previousWork += ' and ';
							} else if (previousWork != "") {
								previousWork += ', ';
							}
							startDate = $(this).attr('start');
							finishDate = $(this).attr('finish');
							if (startDate == finishDate) {
								previousWork += ' on '+ finishDate;
							} else {
								previousWork += ' between '+ startDate + ' and ' + finishDate;
							}
						}
						else 
						{
							if (plannedWork != "" && i == j) {
							plannedWork += ' and ';
							} else if (plannedWork != "") {
								plannedWork += ', ';
							}
							startDate = $(this).attr('start');
							finishDate = $(this).attr('finish');
							if (startDate == finishDate) {
								plannedWork += ' on '+ finishDate;
							} else {
								plannedWork += ' between '+ startDate + ' and ' + finishDate;
							}
						}
					});
					if(congestionText != "")
					{
						congestionText += "<div class='coverageInfoSplit'><img height='1' src='/static/images/clear.gif'></div>";
					}
					if(address != null)
					{
						xmlPostcode = address.substr(0,1).toUpperCase().concat(address.substr(1));
					}
					
					if(plannedWork != "" && previousWork != "")
					{
						map.openInfoWindowHtml(map.getCenter(), '<div class=\"infoWindow\">'+congestionText+'We carried out work in ' + xmlPostcode + ' last week and are planning more ' + plannedWork + '. This may affect your normal network service, but should only last for about 6-8 hours.</div>', {maxWidth:240} );
					}
					else if(plannedWork != "")
					{
						map.openInfoWindowHtml(map.getCenter(), '<div class=\"infoWindow\">'+congestionText+'Work is planned in ' + xmlPostcode + plannedWork + '. This may affect your normal network service, but should only last for about 6-8 hours.</div>', {maxWidth:240} );
					}
					else if(previousWork != "")
					{
						map.openInfoWindowHtml(map.getCenter(), '<div class=\"infoWindow\">'+congestionText+'We carried out work in ' + xmlPostcode + previousWork + '. Apologies if your normal network service was affected.</div>', {maxWidth:240} );
					}
					else
					{
						map.openInfoWindowHtml(map.getCenter(), '<div class=\"infoWindow\">'+congestionText+'Maintenance has occurred in the past 7 days, you may find your service to be slower than usual.</div>', {maxWidth:240} );
					}
				} 
				else if (status == "1" && alwaysShow == "true") {
					
					srhPostcode = srhPostcode.toUpperCase();
					
					if(address != null)
					{
						srhPostcode = address.substr(0,1).toUpperCase().concat(address.substr(1));
					}
					
					map.openInfoWindowHtml(map.getCenter(), '<div class=\"infoWindow\">'+congestionText+'There is no work planned in ' + srhPostcode + ' over the next few days.</div>', {maxWidth:222} );
				}
				else if(congestion == "true" && mapType == "mbb")
				{
					map.openInfoWindowHtml(map.getCenter(), '<div class=\"infoWindow\">'+congestionText+'</div>', {maxWidth:240} );
				}
			}
		});
	}
	
	function setUpHelp() {
		$('.Functional_App-CoverageChecker .helpLink a').click(function(){
			$('#content-boxed').prepend("<div id='help-shroud'></div>");
			$('#help-shroud').css({
				'background-color' : '#000',
				'opacity' : 0.7,
				'color' : 'rgb(0,40,244)',
				'width' : '763px',
				'height' : '510px',
				'position' : 'absolute',
				'zIndex' : 970,
				'left' : 0,
				'display' : 'none'
			});
			$('#content-boxed').prepend("<a href='#' title='close the help overlay' id='help-close'><img src='/static/images/functional_apps/coverage/overlay-close.gif' alt='close'></a>");
			
			$('#help-close').click(function(){
				$('.helpMarker').fadeOut();
				$('.helpText').fadeOut();
				$('#help-shroud').fadeOut();
				$('#help-close').remove();
				return false;
			});

			$("#helpMarker1").click(function () {
				$('#helpText5').fadeOut();
				$('#helpText2').fadeOut();
				$('#helpText3').fadeOut();
				$('#helpText4').fadeOut();
				$('#helpText1').fadeIn();
			});
			$("#helpMarker2").click(function () {
				$('#helpText1').fadeOut();
				$('#helpText5').fadeOut();
				$('#helpText3').fadeOut();
				$('#helpText4').fadeOut();
				$('#helpText2').fadeIn();
			});
			$("#helpMarker3").click(function () {
				$('#helpText1').fadeOut();
				$('#helpText2').fadeOut();
				$('#helpText5').fadeOut();
				$('#helpText4').fadeOut();
				$('#helpText3').fadeIn();
			});
			$("#helpMarker4").click(function () {
				$('#helpText1').fadeOut();
				$('#helpText2').fadeOut();
				$('#helpText3').fadeOut();
				$('#helpText5').fadeOut();
				$('#helpText4').fadeIn();
			});
			$("#helpMarker5").click(function () {
				$('#helpText1').fadeOut();
				$('#helpText2').fadeOut();
				$('#helpText3').fadeOut();
				$('#helpText4').fadeOut();
				$('#helpText5').fadeIn();
			});
			
			$("#helpText1 a.close").click(function () {
				$('#helpText1').fadeOut();
				return false;
			});
			$("#helpText2 a.close").click(function () {
				$('#helpText2').fadeOut();
				return false;
			});
			$("#helpText3 a.close").click(function () {
				$('#helpText3').fadeOut();
				return false;
			});
			$("#helpText4 a.close").click(function () {
				$('#helpText4').fadeOut();
				return false;
			});
			$("#helpText5 a.close").click(function () {
				$('#helpText5').fadeOut();
				return false;
			});
			$("#helpText6 a.close").click(function () {
				$('#helpText6').fadeOut();
				return false;
			});
			
			$('#help-shroud').fadeIn();
			$('#helpText6').fadeIn();
			$('.helpMarker').fadeIn();
			
			return false;
		});
	}
	function createCookie(name,value,days) {
		if (days) {
			var date = new Date();
			date.setTime(date.getTime()+(days*24*60*60*1000));
			var expires = "; expires="+date.toGMTString();
		}
		else var expires = "";
		document.cookie = name+"="+value+expires+"; path=/";
	}

	function readCookie(name) {
		var nameEQ = name + "=";
		var ca = document.cookie.split(';');
		for(var i=0;i < ca.length;i++) {
			var c = ca[i];
			while (c.charAt(0)==' ') c = c.substring(1,c.length);
			if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
		}
		return null;
	}

	function eraseCookie(name) {
		createCookie(name,"",-1);
	}