/*!
 *  Copyright 2009 Mott MacDonald. All rights reserved
 */


/**
 * Define the map. The map will be displayed in a div. It is
 * reliant on the OpenLayers library.
 */
var createMap = function(mapDiv){
	
	var 
	
	// Bounding for the map
	mapBounds = new OpenLayers.Bounds(-20037508, -20037508, 20037508, 20037508.34),
	
	// Open layers maps
	map = new OpenLayers.Map(mapDiv,
							 {maxExtent: mapBounds,
        projection: new OpenLayers.Projection("EPSG:900913"),
        displayProjection: new OpenLayers.Projection("EPSG:4326"),
        units: "m",
        numZoomLevels: 18,
        controls: [],
        maxResolution: 156543.0339}),
	
    // -----------------------------------------------------------
    // RENDER LAYERS
    // -----------------------------------------------------------

    // Open Street Map
    mapnik = new OpenLayers.Layer.OSM(),

	/*
	 * A Dynamic Map Layer is the base for icon layers. 
	 *
	 * name - name of the layer
	 * iconFunction - will return the icon for the feature on the layer
	 * attrFunction - will return the attributes for the feature
	 */
	dynamicMapLayer = (function(name, iconFunction, hoverIconFunction, attrFunction) {
			
		var
	
		// All icons are of the same size, but the icon to render will be
		// determined by the supplied icon function from the subclass		 
		style = new OpenLayers.Style({
						'externalGraphic': '${getIcon}',
						'graphicHeight': 23,
						'graphicWidth' : 23
					}, 
					{
						context: {getIcon : iconFunction}				
					}),	
					
		hoverStyle = new OpenLayers.Style({
			'externalGraphic': '${getIcon}',
			'graphicHeight': 23,
			'graphicWidth' : 23
		}, 
		{
			context: {getIcon : hoverIconFunction}				
		}),	
		
	    styleMap = new OpenLayers.StyleMap({'default': style, 'select':style, 'temporary':hoverStyle}),
	    
	    layer = new OpenLayers.Layer.Vector(name, {styleMap: styleMap}),
	    
	    // features displayed on the layer
	    features = null,
	    
	    /*
	     * Adds data to the map. The data should be in json format and have
	     * at a minimum an easting and northing attribute.
	     */
	    addData = function(data) {
			
			// Remove any existing features/icons
			if (features != null)
			{
				layer.destroyFeatures(features);
			}
			
			// Add the new features/icons to the layer
			features = new Array(data.length);
			
			for (var idx=0; idx<data.length; idx++)
			{
				var item = data[idx];
				
				var itemLatLon = new OpenLayers.LonLat( item["lng"], item["lat"] );
				
				var itemXY			= itemLatLon.transform(EPSG4326, EPSG900913);
				
				features[idx] = new OpenLayers.Feature.Vector(
	                    				new OpenLayers.Geometry.Point(itemXY.lon, itemXY.lat),
	                    				attrFunction(item));
			}
			
			layer.addFeatures(features);
		};
	    
		// Public methods for the dynamic layer
	    return {
	    	
	    	/*
	    	 * Returns the OpenLayers layer 
	    	 */
			getLayer: function () {
				return layer;
			},
	    
			/*
			 * Adds the data to the layer
			 */
			addData: addData
		};    
		
	}), // end of dynamicMapLayer
	
	/*
	 * A Static Map Layer is a base for icon layers. 
	 *
	 * name - name of the layer
	 * iconFunction - will return the icon for the feature on the layer
	 * attrFunction - will return the attributes for the feature
	 */
	staticMapLayer = (function(name, xmlFile, icon, iconSize, hoverIcon, hoverIconSize) {
		var
		
		// All icons are of the same size, but the icon to render will be
		// determined by the supplied icon function from the subclass		 
		style = new OpenLayers.Style({
						'externalGraphic': icon,
						'graphicHeight': iconSize,
						'graphicWidth' : iconSize
					}), 
	
		hoverStyle = new OpenLayers.Style({
			'externalGraphic': hoverIcon,
			'graphicHeight': hoverIconSize,
			'graphicWidth' : hoverIconSize
		}), 
		
	    styleMap = new OpenLayers.StyleMap({'default': style, 'select':style, 'temporary':hoverStyle}),
	    
        layer = new OpenLayers.Layer.GML(name, xmlFile, 
                                { format: OpenLayers.Format.GeoRSS, 
                                  styleMap:styleMap,
                                  projection: new OpenLayers.Projection("EPSG:4326")});
		
		// Public methods for the static layer
	    return {
	    	
	    	/*
	    	 * Returns the OpenLayers layer 
	    	 */
			getLayer: function () {
				return layer;
			}
		};   
	}), // end of staticMapLayer

	/**
	 * Car park layer
	 */
	carParkLayer = (function() {

		var 
		
		iconFunction = function(feature) {

			if (feature.attributes.itemCount > 1) {
				return "/hop2/images/carpark_cluster.png";
			}
			else {
				return "/hop2/images/carpark.png";
			}
		},
		
		hoverIconFunction = function(feature) {
			
			if (feature.attributes.itemCount > 1) {
				return "/hop2/images/carpark_cluster_hover.png";
			}
			else {
				return "/hop2/images/carpark_hover.png";
			}
		},
		
		attrFunction = function(dataItem) {
			return {
				itemCount: dataItem["itemCount"],
				name: dataItem["name"],
				state: dataItem["state"],
				capacity: dataItem["capacity"],
				spaces: dataItem["spaces"],
				updated: dataItem["updated"],
				trend: dataItem["trend"]
			};
				
		};
		
		return dynamicMapLayer("Car Parks", iconFunction, hoverIconFunction, attrFunction);
		
	})(),

	/**
	 * Vms layer
	 */
	vmsLayer = (function() {

		var 
		
		iconFunction = function(feature) {
			
			if (feature.attributes.itemCount > 1) {
				return "/hop2/images/vms_cluster.png";
			}
			else {
				return "/hop2/images/vms.png";
			}
		},
		
		hoverIconFunction = function(feature) {
			
			if (feature.attributes.itemCount > 1) {
				return "/hop2/images/vms_cluster_hover.png";
			}
			else {
				return "/hop2/images/vms_hover.png";
			}
		},
		
		attrFunction = function(dataItem) {
			
			return {
				itemCount: dataItem["itemCount"],
				message: dataItem["message"]};
		};
		
		return dynamicMapLayer("Roadside Signs", iconFunction, hoverIconFunction, attrFunction);
		
	})(),

	/**
	 * Accident layer
	 */
	accidentLayer = (function() {

		var 
		
		iconFunction = function(feature) {
			
			if (feature.attributes.itemCount > 1) {
				return "/hop2/images/accident_cluster.png";
			}
			else {
				return "/hop2/images/accident.png";
			}
		},
		
		hoverIconFunction = function(feature) {
			
			if (feature.attributes.itemCount > 1) {
				return "/hop2/images/accident_cluster_hover.png";
			}
			else {
				return "/hop2/images/accident_hover.png";
			}
		},
		
		attrFunction = function(dataItem) {
			
			return {
				itemCount: dataItem["itemCount"],
				severity: dataItem["severity"],
				start: dataItem["start"],
				end: dataItem["end"],
				description: dataItem["description"],
				provider: dataItem["provider"],
				location: dataItem["location"]
			};
		};
		
		return dynamicMapLayer("Accidents", iconFunction, hoverIconFunction, attrFunction);
		
	})(),
	
	/**
	 * CCTV layer
	 */
	cctvLayer = (function() {

		var 
		
		iconFunction = function(feature) {
			
			if (feature.attributes.itemCount > 1) {
				return "/hop2/images/cctv_cluster.png";
			}
			else {
				return "/hop2/images/cctv.png";
			}
		},
		
		hoverIconFunction = function(feature) {
			
			if (feature.attributes.itemCount > 1) {
				return "/hop2/images/cctv_cluster_hover.png";
			}
			else {
				return "/hop2/images/cctv_hover.png";
			}
		},
		
		attrFunction = function(dataItem) {
			
			return {
				itemCount: dataItem["itemCount"],
				id: dataItem["id"],
				description: dataItem["locationDescription"]
			};
		};
		
		return dynamicMapLayer("CCTV", iconFunction, hoverIconFunction, attrFunction);
		
	})(),

	/**
	 * Train Station layer
	 */
	trainStationLayer = (function() {

		var 
		
		iconFunction = function(feature) {
			
			if (feature.attributes.itemCount > 1) {
				return "/hop2/images/railway_cluster.png";
			}
			else {
				return "/hop2/images/railway.png";
			}
		},
		
		hoverIconFunction = function(feature) {
			
			if (feature.attributes.itemCount > 1) {
				return "/hop2/images/railway_cluster_hover.png";
			}
			else {
				return "/hop2/images/railway_hover.png";
			}
		},
		
		attrFunction = function(dataItem) {
			
			return {
				itemCount: dataItem["itemCount"],
				title: dataItem["title"],
				link: dataItem["link"]
			};
		};
		
		return dynamicMapLayer("Train Stations", iconFunction, hoverIconFunction, attrFunction);
		
	})(),
	
	/**
	 * Event layer
	 */
	eventLayer = (function() {

		var 
		
		iconFunction = function(feature) {
			
			if (feature.attributes.itemCount > 1) {
				return "/hop2/images/event_cluster.png";
			}
			else {
				return "/hop2/images/event.png";
			}
		},
		
		hoverIconFunction = function(feature) {
			
			if (feature.attributes.itemCount > 1) {
				return "/hop2/images/event_cluster_hover.png";
			}
			else {
				return "/hop2/images/event_hover.png";
			}
		},
		
		attrFunction = function(dataItem) {
			
			return {
				itemCount: dataItem["itemCount"],
				severity: dataItem["severity"],
				start: dataItem["start"],
				end: dataItem["end"],
				description: dataItem["description"],
				provider: dataItem["provider"],
				location: dataItem["location"]
			};
		};
		
		return dynamicMapLayer("Events", iconFunction, hoverIconFunction, attrFunction);
		
	})(),

	/**
	 * Incident layer
	 */
	incidentLayer = (function() {

		var 
		
		iconFunction = function(feature) {
			
			if (feature.attributes.itemCount > 1) {
				return "/hop2/images/incident_cluster.png";
			}
			else {
				return "/hop2/images/incident.png";
			}
		},
		
		hoverIconFunction = function(feature) {
			
			if (feature.attributes.itemCount > 1) {
				return "/hop2/images/incident_cluster_hover.png";
			}
			else {
				return "/hop2/images/incident_hover.png";
			}
		},
		
		attrFunction = function(dataItem) {
			
			return {
				itemCount: dataItem["itemCount"],
				severity: dataItem["severity"],
				start: dataItem["start"],
				end: dataItem["end"],
				description: dataItem["description"],
				provider: dataItem["provider"],
				location: dataItem["location"]
			};
		};
		
		return dynamicMapLayer("Incidents", iconFunction, hoverIconFunction, attrFunction);
	
	})(),

	/**
	 * Roadworks layer
	 */
	roadworksLayer = (function() {

		var 
		
		iconFunction = function(feature) {
			
			if (feature.attributes.itemCount > 1) {
				return "/hop2/images/roadwork_cluster.png";
			}
			else {
				return "/hop2/images/roadwork.png";
			}
		},
		
		hoverIconFunction = function(feature) {
			
			if (feature.attributes.itemCount > 1) {
				return "/hop2/images/roadwork_cluster_hover.png";
			}
			else {
				return "/hop2/images/roadwork_hover.png";
			}
		},
		
		attrFunction = function(dataItem) {
			
			return {
				itemCount: dataItem["itemCount"],
				severity: dataItem["severity"],
				start: dataItem["start"],
				end: dataItem["end"],
				description: dataItem["description"],
				provider: dataItem["provider"],
				location: dataItem["location"]
			};
		};
		
		return dynamicMapLayer("Roadworks", iconFunction, hoverIconFunction, attrFunction);
		
	})(),

	/**
	 * Airport layer
	 */
	airportLayer = (function() {
		return staticMapLayer("Airports", "/hop2/xmlFilesStatic/airports.xml", "/hop2/images/airport.png", 23, "/hop2/images/airport_hover.png", 23);
	})(),
	
	/**
	 * National layer
	 */
	nationalLayer = (function() {
		return staticMapLayer("National Sites", "/hop2/xmlFilesStatic/uk_national.xml", "/hop2/images/hop_icon_n.png", 32, "/hop2/images/hop_icon_n.png", 40);
	})(),
	
	/**
	 * Regional layer
	 */
	regionalLayer = (function() {
		return staticMapLayer("Regional Sites", "/hop2/xmlFilesStatic/uk_unitary.xml", "/hop2/images/hop_icon_u.png", 32, "/hop2/images/hop_icon_u.png", 40);
	})(),
	
	/*
	 * The popup displayed on the map
	 */
	popup = (function() {
		 
	  var popupOnMap = null,
		
	  hide = function() {
		if (popupOnMap) {
			map.removePopup(popupOnMap);
			popupOnMap.destroy();
			popupOnMap = null;	
		}
	  },
		
	  show = function(xy, txt) {
		hide();
		popupOnMap = new OpenLayers.Popup.FramedCloud("data", xy, null, txt, null, true, null);
		map.addPopup(popupOnMap);			
	  };
	  
	  return {
	      show: show
	  };
		
	})(),

	/*
	 * Method called when we click on a feature. This will display an
	 * appropriate popup.
	 */
	 onFeatureSelected = function(evt) {
	   var selectedFeature = evt.feature;
	   var jsonData = selectedFeature.data;
	   var txt = "NO DATA";
	   // Car Parks
	   if(selectedFeature.layer==carParkLayer.getLayer())
	   {
		   if(jsonData.itemCount>1)
		   {
			   txt = "<h2>Car Parks</h2>"+
			   "<p>There are "+jsonData.itemCount+" Car Parks at this location.<br/>Zoom in for further details.</p>";
		   }
		   else
		   {
			   txt = "<h2>"+jsonData.name+"</h2>"+
			   "<table border='0'>"+
			   "<tr valign='top'><td><b>State:</b></td><td>"+jsonData.state+"</td></tr>"+
			   "<tr valign='top'><td><b>Free Spaces:&nbsp;</b></td><td>"+jsonData.spaces+"</td></tr>"+
			   "<tr valign='top'><td><b>Capacity:</b></td><td>"+jsonData.capacity+"</td></tr>"+
			   "<tr valign='top'><td><b>Trend:</b></td><td>"+jsonData.trend+"</td></tr>"+
			   "<tr valign='top'><td><b>Updated:</b></td><td>"+jsonData.updated+"</td></tr>"+
			   "</table>";
		   }
	   }
	   // Roadworks
	   else if(selectedFeature.layer==roadworksLayer.getLayer())
	   {
		   if(jsonData.itemCount>1)
		   {
			   txt = "<h2>Roadworks</h2>"+
			   "<p>There are "+jsonData.itemCount+" Roadworks at this location.<br/>Zoom in for further details.</p>";
		   }
		   else
		   {
			   txt = "<h2>Roadwork</h2>"+
			   "<table border='0' width='300'>"+
			   "<tr valign='top'><td><b>Severity:</b></td><td>"+jsonData.severity+"</td></tr>"+
			   "<tr valign='top'><td><b>Start:</b></td><td>"+jsonData.start+"</td></tr>"+
			   "<tr valign='top'><td><b>End:</b></td><td>"+jsonData.end+"</td></tr>"+
			   "<tr valign='top'><td><b>Provider:</b></td><td>"+jsonData.provider+"</td></tr>"+
			   "<tr valign='top'><td><b>Location:</b></td><td>"+jsonData.location+"</td></tr>"+
			   "<tr valign='top'><td><b>Description:&nbsp;</b></td><td>"+jsonData.description+"</td></tr>"+
			   "</table>";
		   }
	   }
	   // Incident
	   else if(selectedFeature.layer==incidentLayer.getLayer())
	   {
		   if(jsonData.itemCount>1)
		   {
			   txt = "<h2>Incidents</h2>"+
			   "<p>There are "+jsonData.itemCount+" Incidents at this location.<br/>Zoom in for further details.</p>";
		   }
		   else
		   {
			   txt = "<h2>Incident</h2>"+
			   "<table border='0' width='300'>"+
			   "<tr valign='top'><td><b>Severity:</b></td><td>"+jsonData.severity+"</td></tr>"+
			   "<tr valign='top'><td><b>Start:</b></td><td>"+jsonData.start+"</td></tr>"+
			   "<tr valign='top'><td><b>End:</b></td><td>"+jsonData.end+"</td></tr>"+
			   "<tr valign='top'><td><b>Provider:</b></td><td>"+jsonData.provider+"</td></tr>"+
			   "<tr valign='top'><td><b>Location:</b></td><td>"+jsonData.location+"</td></tr>"+
			   "<tr valign='top'><td><b>Description:&nbsp;</b></td><td>"+jsonData.description+"</td></tr>"+
			   "</table>";
		   }
	   }
	   // Event
	   else if(selectedFeature.layer==eventLayer.getLayer())
	   {
		   if(jsonData.itemCount>1)
		   {
			   txt = "<h2>Events</h2>"+
			   "<p>There are "+jsonData.itemCount+" Events at this location.<br/>Zoom in for further details.</p>";
		   }
		   else
		   {
			   txt = "<h2>Event</h2>"+
			   "<table border='0' width='300'>"+
			   "<tr valign='top'><td><b>Severity:</b></td><td>"+jsonData.severity+"</td></tr>"+
			   "<tr valign='top'><td><b>Start:</b></td><td>"+jsonData.start+"</td></tr>"+
			   "<tr valign='top'><td><b>End:</b></td><td>"+jsonData.end+"</td></tr>"+
			   "<tr valign='top'><td><b>Provider:</b></td><td>"+jsonData.provider+"</td></tr>"+
			   "<tr valign='top'><td><b>Location:</b></td><td>"+jsonData.location+"</td></tr>"+
			   "<tr valign='top'><td><b>Description:&nbsp;</b></td><td>"+jsonData.description+"</td></tr>"+
			   "</table>";
		   }
	   }
	   // Accidents
	   else if(selectedFeature.layer==accidentLayer.getLayer())
	   {
		   if(jsonData.itemCount>1)
		   {
			   txt = "<h2>Accidents</h2>"+
			   "<p>There are "+jsonData.itemCount+" Accidents at this location.<br/>Zoom in for further details.</p>";
		   }
		   else
		   {
			   txt = "<h2>Accident</h2>"+
			   "<table border='0' width='300'>"+
			   "<tr valign='top'><td><b>Severity:</b></td><td>"+jsonData.severity+"</td></tr>"+
			   "<tr valign='top'><td><b>Start:</b></td><td>"+jsonData.start+"</td></tr>"+
			   "<tr valign='top'><td><b>End:</b></td><td>"+jsonData.end+"</td></tr>"+
			   "<tr valign='top'><td><b>Provider:</b></td><td>"+jsonData.provider+"</td></tr>"+
			   "<tr valign='top'><td><b>Location:</b></td><td>"+jsonData.location+"</td></tr>"+
			   "<tr valign='top'><td><b>Description:&nbsp;</b></td><td>"+jsonData.description+"</td></tr>"+
			   "</table>";
		   }
	   }
	   // Train Stations
	   else if(selectedFeature.layer==trainStationLayer.getLayer())
	   {
		   if(jsonData.itemCount>1)
		   {
			   txt = "<h2>Train Stations</h2>"+
			   "<p>There are "+jsonData.itemCount+" Train Stations at this location.<br/>Zoom in for further details.</p>";
		   }
		   else
		   {
			   txt = "<h2>"+jsonData.title+"</h2>"+
			   "<p><a target ='_blank' href='"+jsonData.link+"'>Live departure information.</a></p>";
		   }
	   }
	   // VMS
	   else if(selectedFeature.layer==vmsLayer.getLayer())
	   {
		   if(jsonData.itemCount>1)
		   {
			   txt = "<h2>Roadside Signs</h2>"+
			   "<p>There are "+jsonData.itemCount+" Roadside Signs at this location.<br/>Zoom in for further details.</p>";
		   }
		   else
		   {
			   txt = "<h2>Roadside Sign</h2>"+
			   "<p><b>"+jsonData.message+"</b></p>";
		   }
	   }
	   // Airport
	   else if(selectedFeature.layer==airportLayer.getLayer())
	   {
		   txt = "<h2>"+jsonData.title+"</h2>"+
		   "<p>"+jsonData.description+"</p>";
	   }
	   // National Site
	   else if(selectedFeature.layer==nationalLayer.getLayer())
	   {
		   txt = "<h2>"+jsonData.title+"</h2>"+
		   "<p>"+jsonData.description+"</p>";
	   }
	   // Regional Site
	   else if(selectedFeature.layer==regionalLayer.getLayer())
	   {
		   txt = "<h2>"+jsonData.title+"</h2>"+
		   "<p>"+jsonData.description+"</p>";
	   }
	   // CCTV
	   else if(selectedFeature.layer==cctvLayer.getLayer())
	   {
		   if(jsonData.itemCount>1)
		   {
			   txt = "<h2>CCTV Cameras</h2>"+
			   "<p>There are "+jsonData.itemCount+" CCTV Cameras at this location.<br/>Zoom in for further details.</p>";
		   }
		   else
		   {
			   txt = "<h2>"+jsonData.description+" CCTV</h2>"+
			   "<p><img src='cctv.htm?i="+jsonData.id+"&t="+new Date().valueOf()+"' width='320' height='240' alt='"+jsonData.description+
			   " CCTV' title='"+jsonData.description+" CCTV'><br/>";
			   
			   String.prototype.startsWith = function(str) 
			   {return (this.match("^"+str)==str);};
			   
			   if(jsonData.id.startsWith("HACCTV"))
			   {
				   txt += "&copy; Highways Agency 2010";
			   }
			   else
			   {
				   txt += "&copy; Traffic Scotland 2010";
			   }
			   
			   txt += "</p>";
		   }
	   }
	   txt = "<div style='margin-left: 32px;'>"+txt+"</div>";
	   popup.show(selectedFeature.geometry.getBounds().getCenterLonLat(), txt);
	},
	
	// Projections for converting from LatLng to Spherical Mercator
	EPSG4326 = new OpenLayers.Projection( "EPSG:4326" ),
    EPSG900913 = new OpenLayers.Projection( "EPSG:900913" ),
    
	/*
	 * Callback when the map is moved (or we need to refresh). This will
	 * request the latest data for the current bounding box and zoom level.
	 */
    onMoveEnd = function()
	{
	    var xmlhttp=false;

	    if (!xmlhttp && typeof XMLHttpRequest!='undefined') {
	    	 
	    	try {
	          xmlhttp = new XMLHttpRequest();
	        } catch (e) {
	          xmlhttp = false;
	        }
	     
	    }
		if (xmlhttp)
		{
			var bounds = map.getExtent().toArray();
			var swXY = new OpenLayers.LonLat( bounds[0], bounds[1] );
			var neXY = new OpenLayers.LonLat( bounds[2], bounds[3] );
			
			var swLonLat = swXY.transform(EPSG900913, EPSG4326);
			var neLonLat = neXY.transform(EPSG900913, EPSG4326);
			
			var centre = map.getCenter().transform(EPSG900913, EPSG4326);
			
			// Set cookies
			createCookie("cookieLat",centre.lat,null);
			createCookie("cookieLng",centre.lon,null);
			createCookie("cookieZoom",map.getZoom(),null);

			var latSpan = neLonLat.lat - swLonLat.lat;
			var lonSpan = neLonLat.lon - swLonLat.lon;
			
			var typeString = "";
			var roadworksOn = roadworksLayer.getLayer().getVisibility();
			var trainStationsOn = trainStationLayer.getLayer().getVisibility();
			var incidentsOn = incidentLayer.getLayer().getVisibility();
			var carParksOn = carParkLayer.getLayer().getVisibility();
			var vmsOn = vmsLayer.getLayer().getVisibility();
			var eventsOn = eventLayer.getLayer().getVisibility();
			var accidentsOn = accidentLayer.getLayer().getVisibility();
			var cctvOn = cctvLayer.getLayer().getVisibility();
			
			if(carParksOn)
			{
				typeString += "1";
			}
			else if(carParkLayer.getLayer().features.length>0)
			{
				carParkLayer.getLayer().destroyFeatures(carParkLayer.getLayer().features);
			}
			if(roadworksOn)
			{
				typeString += "2";
			}
			else if(roadworksLayer.getLayer().features.length>0)
			{
				roadworksLayer.getLayer().destroyFeatures(roadworksLayer.getLayer().features);
			}
			if(vmsOn)
			{
				typeString += "3";
			}
			else if(vmsLayer.getLayer().features.length>0)
			{
				vmsLayer.getLayer().destroyFeatures(vmsLayer.getLayer().features);
			}
			if(accidentsOn)
			{
				typeString += "4";
			}
			else if(accidentLayer.getLayer().features.length>0)
			{
				accidentLayer.getLayer().destroyFeatures(accidentLayer.getLayer().features);
			}
			if(incidentsOn)
			{
				typeString += "5";
			}
			else if(incidentLayer.getLayer().features.length>0)
			{
				incidentLayer.getLayer().destroyFeatures(incidentLayer.getLayer().features);
			}
			if(eventsOn)
			{
				typeString += "6";
			}
			else if(eventLayer.getLayer().features.length>0)
			{
				eventLayer.getLayer().destroyFeatures(eventLayer.getLayer().features);
			}
			if(trainStationsOn)
			{
				typeString += "7";
			}
			else if(trainStationLayer.getLayer().features.length>0)
			{
				trainStationLayer.getLayer().destroyFeatures(trainStationLayer.getLayer().features);
			}
			if(cctvOn)
			{
				typeString += "8";
			}
			else if(cctvLayer.getLayer().features.length>0)
			{
				cctvLayer.getLayer().destroyFeatures(cctvLayer.getLayer().features);
			}
			
			if(typeString!="")
			{
				xmlhttp.open("GET", "/ihop2/website.json?1="+centre.lat+"&2="+centre.lon+"&3="+latSpan+"&4="+lonSpan+"&5="+typeString, true);
				xmlhttp.onreadystatechange=function()
				{
					if (xmlhttp.readyState==4)
					{
						var json = json_parse(xmlhttp.responseText);
	
						if(json.roadworks!=null)
						{
							roadworksLayer.addData(json.roadworks);
						}
						if(json.accidents!=null)
						{
							accidentLayer.addData(json.accidents);
						}
						if(json.incidents!=null)
						{
							incidentLayer.addData(json.incidents);
						}
						if(json.events!=null)
						{
							eventLayer.addData(json.events);
						}
						if(json.carParks!=null)
						{
							carParkLayer.addData(json.carParks);
						}
						if(json.vms!=null)
						{
							vmsLayer.addData(json.vms);
						}
						if(json.trainStations!=null)
						{
							trainStationLayer.addData(json.trainStations);
						}
						if(json.cctv!=null)
						{
							cctvLayer.addData(json.cctv);
						}
					}
				};
				xmlhttp.send(null);
			}
		}
	},	
		
    zoomCheck = function()
    {
        if(map.getZoom() < 9)
        {
        	vmsLayer.getLayer().setVisibility(false);
        	vmsLayer.getLayer().destroyFeatures(vmsLayer.getLayer().features);
        }
        else
        {
        	vmsLayer.getLayer().setVisibility(true);
        }
        if(map.getZoom() < 11)
        {
        	roadworksLayer.getLayer().setVisibility(false);
        	roadworksLayer.getLayer().destroyFeatures(roadworksLayer.getLayer().features);
        }
        else
        {
        	roadworksLayer.getLayer().setVisibility(true);
        }
        if(map.getZoom() < 12)
        {
          	trainStationLayer.getLayer().setVisibility(false);
          	trainStationLayer.getLayer().destroyFeatures(trainStationLayer.getLayer().features);
        }
        else
        {
        	trainStationLayer.getLayer().setVisibility(true);
        }
        if(map.getZoom() < 7)
        {
        	regionalLayer.getLayer().setVisibility(false);
        }
        else
        {
        	regionalLayer.getLayer().setVisibility(true);
        }
        if(map.getZoom() < 6)
        {
        	airportLayer.getLayer().setVisibility(false);
        }
        else
        {
        	airportLayer.getLayer().setVisibility(true);
        }
    },
	
    gup = function( 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];
    },
    
    
    
    
    
    createCookie = function(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=/";
    },

    readCookie = function(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;
    },

    eraseCookie = function(name) {
    	createCookie(name,"",-1);
    },
    
    
    
    
	
	/*
	 * Initialise the map
	 */
	init = function() {	

	  var 
	
	  layers = [trainStationLayer.getLayer(),
	            roadworksLayer.getLayer(),
	            incidentLayer.getLayer(),
	            vmsLayer.getLayer(),
	            airportLayer.getLayer(),
	            nationalLayer.getLayer(),
	            regionalLayer.getLayer(),
	            carParkLayer.getLayer(), 
	            eventLayer.getLayer(),
	            accidentLayer.getLayer(),
	            cctvLayer.getLayer()
	            ];	
	  
	  var lat = gup( 'lat' );
  	  var lng = gup( 'lng' );
	
	  // Add base layer to map
	  map.addLayer(mapnik);

	  var highlightCtrl;
	  
	  // Add dynamic layers to map
	  for (var idx=0; idx<layers.length; idx++)
	  {
		layers[idx].events.register("featureselected", map, onFeatureSelected);	
		
		highlightCtrl = new OpenLayers.Control.SelectFeature(layers[idx], {
		    hover: true,
		    highlightOnly: true,
		    renderIntent: "temporary"
		});
		
		map.addControl(highlightCtrl);
		highlightCtrl.activate();
		
		map.addLayer(layers[idx]);
	  }
 
	  // Enable selection on map features - note we must add this after the layers
	  // have been added to the map
	  var selectControl = new OpenLayers.Control.SelectFeature(layers);
	  map.addControl(selectControl);	
	  selectControl.activate();
		  
	  map.addControl(new OpenLayers.Control.ZoomBox());
      map.addControl(new OpenLayers.Control.Navigation());
      map.addControl(new OpenLayers.Control.PanZoomBar());
      map.addControl(new OpenLayers.Control.Attribution());
      map.addControl(new OpenLayers.Control.OverviewMap());
      map.addControl(new OpenLayers.Control.Permalink());
	  
      if (lat == "")
      {
    	  var cookieLat = readCookie("cookieLat");
    	  var cookieLng = readCookie("cookieLng");
    	  var cookieZoom = readCookie("cookieZoom");

    	  if(cookieLat!=null && cookieLng!=null && cookieZoom!=null)
    	  {
    	      	var lonLat = new OpenLayers.LonLat(cookieLng, cookieLat).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject());

    	          map.moveTo(lonLat, cookieZoom);
    	  }
    	  else
    	  {
	    	  // Show the map
	          map.zoomToExtent(
	                  new OpenLayers.Bounds(-11.60156, 58.20146, 2.74658, 49.95122)
	                  .transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject())
	          );	
    	  }
      }
      else
      {
      	var lonLat = new OpenLayers.LonLat(lng, lat).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject());

          map.moveTo(lonLat, 18);
      }
	
	  // Register events on the map
	  map.events.register("moveend", map, onMoveEnd);
	  map.events.register("zoomend", map, zoomCheck);
	  
	  // Hide layers at startup
	  zoomCheck();
	  
	  trainStationLayer.getLayer().events.register("visibilitychanged", map, onMoveEnd);
      roadworksLayer.getLayer().events.register("visibilitychanged", map, onMoveEnd);
      incidentLayer.getLayer().events.register("visibilitychanged", map, onMoveEnd);
      vmsLayer.getLayer().events.register("visibilitychanged", map, onMoveEnd);
      carParkLayer.getLayer().events.register("visibilitychanged", map, onMoveEnd); 
      eventLayer.getLayer().events.register("visibilitychanged", map, onMoveEnd);
      accidentLayer.getLayer().events.register("visibilitychanged", map, onMoveEnd);

	  // Refresh the map the first time
	  onMoveEnd();
	};

	// Initialise!
	init();
	
	// Return the public API to the map object
	return {
	  refresh: onMoveEnd
	};   
};

