//global map and layers
var osMap, vLayer, mLayer, attractionLayer,serviceLayer,fisheryLayer,townLayer, whiteLayer, structureLayer, wwayLayer, eventLayer, routeLayer;

//global controls
var wwayControl, attractionControl, serviceControl, fisheryControl, structureControl, eventControl, routeControl;
//resolutions: [2500, 1000, 500, 200, 100, 50, 25, 10, 5, 2.5, 2, 1];

var user_button_activated = new Array();
user_button_activated['wway'] = null;
user_button_activated['attr'] = null;
user_button_activated['serv'] = null;
user_button_activated['fish'] = null;
user_button_activated['stru'] = null;

var popup_open = false;
var timeoutValue = 10000;
var controls = new Array();
var chosencontrol;

var previouszoom;
var previousbounds;
var previouszoombounds;

function redrawScaleLineDiv()
{
	viewport = dojo.byId("map_OpenLayers_ViewPort");
	//searwh over child DIV's and find the ScaleLine div
	dojo.query("div", viewport).forEach(function(x) {
		//div is usually a set string plus a layer indexed number
		var regex = /^OpenLayers\.Control\.ScaleLine_[0-9]{1,}/;
		if (regex.test(x.id)) {
			//if the DIV is found, remove the default O/L class
			dojo.removeClass(x, 'olControlScaleLine');
			//get the current width of the map viewport
			viewportInfo = dojo.position(viewport, true);
			//set the new left position based on the viewport width minus max needed width for ScaleLine DIV
			newWidth = (viewportInfo.w - 115)+"px";
			//apply the new style to the ScaleLine DIV
			dojo.style(x, {top: "5px",left: newWidth, bottom: "0", right: "0", fontSize: "xx-small", height: "50px"});
		}
	});
}

//create a white background box to make map features stanbd out more
function generateWhiteBgBox(bbox)
{
	//create 4 points for boox
	tl = new OpenLayers.Geometry.Point(bbox.left, bbox.top);
	tr = new OpenLayers.Geometry.Point(bbox.right, bbox.top);
	br = new OpenLayers.Geometry.Point(bbox.right, bbox.bottom);
	bl = new OpenLayers.Geometry.Point(bbox.left, bbox.bottom);
	
	//openlayers has to cretae a LinearRing geometry
	ring = [tl, tr, br, bl, tl];
	lring = new OpenLayers.Geometry.LinearRing(ring);
	
	//finally a polygon can be created from the LinearRing
	poly = new OpenLayers.Geometry.Polygon(lring);
	wboxfeature = new OpenLayers.Feature.Vector(poly);

	whiteLayer = new OpenLayers.Layer.Vector("White", {
		resolutions: [2500, 1000, 500, 200, 100, 50, 25, 10, 5, 2.5, 2, 1],
		styleMap: whiteboxStyleMap, 
		displayInLayerSwitcher: false
		});
	whiteLayer.addFeatures(wboxfeature);
	osMap.addLayer(whiteLayer);
	osMap.raiseLayer(whiteLayer, -15);
}

function calculateZoomForWways(zoom)
{
	if (zoom == undefined) {
		//get out of processing asap
		//return lowest quality wway detail to keep rendering time down.
		return 1;
	}

	if (zoom > 1 && zoom < 6) {
		return 3;
	}

	if (zoom > 5 && zoom < 8) {
		return 6;
	}
	//return highest quality line data
	return 9;
}

function onPopupClose(evt) {
    // 'this' is the popup.
    chosencontrol.unselect(this.feature);
}

function onFeatureSelect(feature) {
	popup_open = true;
	anchored = {offset: new OpenLayers.Pixel(1,1), size: new OpenLayers.Size(5,5)};
	point = feature.geometry.getBounds().getCenterLonLat();
	popsize = setFeaturePopupSize(feature);
    popup = new OpenLayers.Popup.AnchoredBubble(
				"featurePopup",
                 point,
                 popsize,
                 generatePopupHTML(feature),
                 anchored,
                 true, 
                 onPopupClose);
    
    feature.popup = popup;
    popup.feature = feature;
    popup.panMapIfOutOfView = true;
    setFeatureBackground(feature);
    osMap.addPopup(popup);
}

function onFeatureUnselect(feature) {
//    feature = evt.feature;
    if (feature.popup) {
        popup.feature = null;
        osMap.removePopup(feature.popup);
        feature.popup.destroy();
        feature.popup = null;
    }
    popup_open = false;
}

function setFeaturePopupSize(feature)
{
	ftype = feature.attributes.featuretype;
	switch (ftype) {
	case 'attr':
		return new OpenLayers.Size(150,100);
		break;
	case 'wway':
		return new OpenLayers.Size(150,50);
		break;
		
	case 'serv':
		return new OpenLayers.Size(200,200);
		break;
		
	case 'fish':
		return new OpenLayers.Size(200,150);
		break;
		
	case 'stru':
		return new OpenLayers.Size(150,75);
		break;
		
	default:
		return new OpenLayers.Size(150,150);
		break;
	}
}

function setFeatureBackground(feature)
{
	ftype = feature.attributes.featuretype;
	popup = feature.popup;
	popup.setBorder("5px solid #000000");
	switch (ftype) {
		case 'attr':
			popup.backgroundColor = '#ffdddd';
			break;
		case 'serv':
			popup.backgroundColor = '#D9FFBF';
			break;
		case 'fish':
			popup.backgroundColor = '#ffeeaa';
			break;
		case 'wway':
			popup.backgroundColor = '#eeeeff';
			break;
		case 'stru':
			popup.backgroundColor = '#efadff';
			break;
		case 'wway_section':
			popup.backgroundColor = '#eeeeff';
			break;
		default:
			popup.backgroundColor = '#ffffff';
			break;
	}
}

function generatePopupHTML(feature)
{
	html = '';
	atts = feature.attributes;
	if (hasValue(atts.featuretype) && atts.featuretype == 'wway') {
		html += formatWsWebLink(atts, 'wway');
	}
	
	//waterway_section
	if (hasValue(atts.featuretype) && atts.featuretype == 'wway_section') {
		if (typeof atts.navigable != 'undefined') {
//			html += '<h4>'+atts.waterwayname+'</h4>';
			html += formatWsWebLink(atts, 'wway_section');
			html += 'Section:'+atts.name+' ['+atts.bw_functional_location+']<br />';
			html += "Affected by stoppage: " + (atts.has_stoppage ? 'Yes' : 'No') + '<br />';
		}
	}
	//structures
	if (hasValue(atts.featuretype) && atts.featuretype == 'stru') {
		html += '<h4>'+atts.name+'</h4>';
		html += '[' + atts.bw_functional_location +']';
	}
	//attractions
	if (hasValue(atts.featuretype) && atts.featuretype == 'attr') {
		html += formatWsWebLink(atts, 'attr');
		html += formatPhoneNumber(atts);
		html += formatAddress(atts);
		html += formatCategories(atts);
		html += formatAttributes(atts);
	}
	//services
	if (hasValue(atts.featuretype) && atts.featuretype == 'serv') {
		html += formatWsWebLink(atts, 'serv');
		html += formatPhoneNumber(atts);
		html += formatAddress(atts);
		html += formatCategories(atts);
		html += formatAttributes(atts);
	}
	//fisheries
	if (hasValue(atts.featuretype) && atts.featuretype == 'fish') {
		html += formatWsWebLink(atts, 'fish');
		html += formatPhoneNumber(atts);
		html += formatAddress(atts);
		html += formatCategories(atts);
		html += formatAttributes(atts);
	}
	//routes
	if (hasValue(atts.featuretype) && atts.featuretype == 'route') {
		html += '<h4>'+atts.name+'</h4>';
		html += '<strong>Waypoint:</strong> ' + atts.position+'<br />';
		html += '<strong>Easting:</strong> ' + atts.easting+'<br />';
		html += '<strong>Northing:</strong> ' + atts.northing+'<br />';
	}
	return html;
}

function formatPhoneNumber(atts)
{
	var str = '';
	if (hasValue(atts.phone_number)) {
		str += atts.phone_number+'<br />';
	}
	return str;
}

function formatAddress(atts)
{
	var str ='';
	if(hasValue(atts.address)) {
		for(ele in atts.address) {
			if (hasValue(atts.address[ele])) {
				str += atts.address[ele]+'<br />';
			}
		}
	}
	return str;
}

function formatCategories(atts)
{
	var str ='';
	if (hasValue(atts.categories) && atts.categories.length > 0) {
		str = 'Categories:<br />';
		dojo.forEach(atts.categories, function(item, idx, arr) {
			if (hasValue(item)) {
				str += item+'<br />';
			}
		});
	}
	return str;
}

function formatAttributes(atts)
{
	var str ='';
	if (hasValue(atts.attributes) &&  atts.attributes.length > 0) {
		str = 'Other services:<br />';
		dojo.forEach(atts.attributes, function(item, idx, arr) {
			if (hasValue(item)) {
				str += ' - '+item+'<br />';
			}
		});
	}
	return str;
}

function makeUrlFriendly(urlstring)
{
	name = urlstring.replace(/\s/gi,'-');
	name = name.replace(/&/gi, 'and');
	name = name.toLowerCase();
    name = urlstring.toLowerCase().replace(/\s/gi,'-').replace(/--/gi,'-').replace(/\(/gi     ,'').replace(/\)/gi,'').replace(/&/gi, 'and');
	return name;
}

function formatWsWebLink(atts, type)
{
	name = makeUrlFriendly(atts.name)
	link_name = atts.name;
	
	switch(type) {
	case 'wway':
		link = '/canals-and-rivers/';
		link += atts.urlname;
		break;
	case 'wway_section':
		link = '/canals-and-rivers/';
		link += atts.urlname;
		link_name = atts.waterwayname;
		break;
	case 'attr':
		link = '/in-your-area/';
		link += atts.address.county.toLowerCase().replace(/ /gi, '-');
		link += '/places-to-go/';
		link += atts.fid+'/';
		link += name;
		
		break;
	case 'fish':
		name = name.replace(/---/gi, '-');
		link = '/things-to-do/fishing/fisheries/'+atts.fid+'/'+name;
		break;
	default:
		link = '/services-directory/'+atts.fid+'/'+name;
	}
	
	str = '';
	str += '<h4><a href="'+link+'" target="_blank">'+link_name+'</a></h4>';
	return str;
}

function redrawMainMap(zoomend_fired)
{
	if (popup_open) {
		return;
	}
	map_evt = (hasValue(zoomend_fired)) ? zoomend_fired : false;
	if (typeof whiteLayer != 'undefined') {
		whiteLayer.destroy();
		generateWhiteBgBox(osMap.getExtent());
	}
	if (map_evt) {
		//zoom has occurred so we need more recent data
		updateMapData();
		setAvailableInfoButtons();
	} else {
		//check we have moved far enough to need to fetch more data.
		if (checkDistanceMoved(osMap.getExtent())) {
			console.log('moved');
			updateMapData();
			setAvailableInfoButtons();
		}
	}
}

function updateMapData()
{
	createWaterways();
	previousbounds = osMap.getExtent();
	previouszoom = osMap.getZoom();
	if (osMap.getZoom() > 3) {
		createAttractions();
	}
	if (osMap.getZoom() > 4) {
		createFisheries();
	}
	if (osMap.getZoom() > 5) {
		createServices();
	}
	if (osMap.getZoom() > 6) {
		createStructures();
	}
}

function checkDistanceMoved(newbounds)
{
	if (! hasValue(previousbounds)) {
		return;
	}
	
	oldl = previousbounds.left
	oldb = previousbounds.bottom;
	
	newl = newbounds.left;
	newb = newbounds.bottom;
	
	diffwidth = null;
	if (previousbounds.left < newbounds.left) {
		diffwidth = calcDistance(previousbounds.left, newbounds.left);
	} else {
		diffwidth = calcDistance(newbounds.left, previousbounds.left);
	}
	
	diffheight = null;
	
	if (previousbounds.bottom < newbounds.bottom) {
		diffheight = calcDistance(previousbounds.bottom, newbounds.bottom);
	} else {
		diffheight = calcDistance(newbounds.bottom, previousbounds.bottom);
	}
	
	if ( (diffwidth > (newbounds.getWidth() / 2)) || (diffheight > (newbounds.getHeight() / 2)) ) {
		return true;
	}
	return false;
}

function hasValue(val)
{
	if (val != '' && val != null && typeof val != 'undefined') {
		return true;
	}
	return false;
}

function calcDistance(lower, upper)
{
	return upper - lower;
}

function getCentrePoint(min_e, min_n,max_e,max_n)
{
	east = parseFloat((min_e + (max_e - min_e / 2)));
	north = parseFloat((min_n + (max_n - min_n) / 2));
	return [east,north];
}

function removeDefaultOSLayers()
{
	//get and remove the default Vector Layer created by OS
	vLayer = osMap.getVectorLayer();
	osMap.removeLayer(vLayer);
	vLayer.destroy();
	
	//get and remove the default Marker Layer created by OS
	mLayer = osMap.getMarkerLayer();
	osMap.removeLayer(mLayer);
	mLayer.destroy();
}

function sanitiseProperty(prop)
{
	s1 = prop.replace(/\s/gi,'_');
	s2 = s1.replace(/\+/gi,'and');
	return s2.toLowerCase();
}

function setBufferZone(bounds, divider)
{
	if (typeof divider == 'undefined') {
		divider = 3; //set 33%
	}
	extender = new OpenSpace.MapBounds();
	extender.left = (bounds.left - (bounds.getWidth() / divider));
	extender.right = (bounds.right + (bounds.getWidth() / divider));
	extender.bottom = (bounds.bottom - (bounds.getHeight() / divider));
	extender.top = (bounds.top + (bounds.getHeight() / divider));
	return extender;
}

function buildBboxUrl(bbox, zoom, category)
{
	if (! hasValue(previouszoombounds)) {
		//this var may need setting for older walks and cycle routes.
		previouszoombounds = osMap.getExtent();
	}
	
	if (typeof category != 'undefined' && category == 'section' && zoom > 7) {
		if (zoom > 8) {
			zoom = 9;
			bounds = setBufferZone(previouszoombounds, 0.5);
		} else {
			bounds = setBufferZone(bbox, 3);
			previouszoombounds = bounds;
		}
	} else {
		bounds = setBufferZone(bbox);
	}
	
	uri = [];
	uri.push('/api');
	uri.push('bbox')
	uri.push(parseInt(bounds.left));
	uri.push(parseInt(bounds.bottom));
	uri.push(parseInt(bounds.right));
	uri.push(parseInt(bounds.top));
	
	if (category !== undefined) {
		uri.push(category);
	} else {
		uri.push('section');
	}
	if (zoom === undefined) {
		uri.push(1);
	} else {
		uri.push(zoom);
	}
	var url =  uri.join('/');
	
	url += '.json';
	return url;
}

function getPointFeature(feature)
{
	if (typeof feature.geometry !== 'undefined') {
		point = new OpenLayers.Geometry.Point(feature.geometry.coordinates[0], feature.geometry.coordinates[1]);
		attributes = {
				name: feature.properties.name
		}
		return new OpenLayers.Feature.Vector(point, attributes);
	}
	return null;
}

function getPolygonFeature(feature)
{
	if (typeof feature.geometry !== 'undefined') {
		rings = [];
		dojo.forEach(feature.geometry.coordinates, function(item)
		{
			points = [];
			dojo.forEach(item, function(object) 
			{
				point = new OpenLayers.Geometry.Point(object[0], object[1]);
				points.push(point);
			});
			ring = new OpenLayers.Geometry.LinearRing(points);
			rings.push(ring);
		});
		polygon = new OpenLayers.Geometry.Polygon([rings[0]]);
		attributes = {
				name: feature.properties.name
		}
		return new OpenLayers.Feature.Vector(polygon, attributes);
	}
	return null;
}

function generateWway(item)
{
	if (typeof item['geometry']['coordinates'] !== 'undefined') {
		var points = [];
		dojo.forEach(item['geometry']['coordinates'], function(coord) {
			p = new OpenLayers.Geometry.Point(coord[0], coord[1]);
			points.push(p);
		});
		lineString = new OpenLayers.Geometry.LineString(points);
		attributes = {
				name: item.properties.name,
				bw_functional_location: item.properties.wway_code,
				urlname: item.properties.urlname,
				featuretype: 'wway'
		}
		
		if (typeof selectedWaterway != 'undefined') {
			
			if (item.properties.wway_code === selectedWaterway) {
				attributes.selected = 1;
			} else {
				attributes.selected = 0;
			}
		} else {
			attributes.selected = 0;
		}
		lineFeature = new OpenLayers.Feature.Vector(lineString,attributes);
		return lineFeature;
	}
}

function generateSection(section)
{
	if (typeof section['geometry']['coordinates'] !== 'undefined') {
		var points = [];
		dojo.forEach(section['geometry']['coordinates'], function(coord) {
			p = new OpenLayers.Geometry.Point(coord[0], coord[1]);
			points.push(p);
		});
		lineString = new OpenLayers.Geometry.LineString(points);
		attributes = {
				name: section.properties.name,
				bw_functional_location: section.properties.bw_functional_location,
				waterwayname: section.properties.waterwayname,
				featuretype: 'wway_section',
				navigable: section.properties.navigable,
				has_stoppage: section.properties.has_stoppage,
				urlname: section.properties.urlname
		}

		if (typeof selectedWaterway != 'undefined') {
			if (section.properties.has_stoppage) {
				attributes.selected = 2;
			} else if (section.properties.wway_code === selectedWaterway) {
				attributes.selected = 1;
			} else {
				attributes.selected = 0;
			}
		} else {
			attributes.selected = 0;
		}
		lineFeature = new OpenLayers.Feature.Vector(lineString,attributes);
		return lineFeature;
	}
	return null;
}

function toggleInit(element)
{
	//remove a class that sets the background image for a selected layer.
	dojo.query('#map_controlform .layerselector').removeClass('selectedLayer');
	if (typeof element != 'undefined') {
		for (key in controls) {
			control = controls[key];
			control.deactivate();
			if (element.id == key) {
				control.activate();
				chosencontrol = control;
				//the chosen layer has been found, so set the background image for that button
				dojo.addClass(element.parentNode,'selectedLayer')
			} 
		}
	} else {
		element = dojo.byId('wwayControl')
		if(element)
		{
			element.checked = true;
			dojo.addClass(element.parentNode, 'selectedLayer');
		}
	}
}

function toggleLayer(layer)
{
	chosenLayer = osMap.getLayersByName(layer)[0];
	if (chosenLayer.visibility) {
		chosenLayer.setVisibility(false);
	} else {
		chosenLayer.setVisibility(true);
	}
}

function setAvailableInfoButtons()
{
	if(typeof(no_buttons) != "undefined" && no_buttons)
	{
		return false;
	}
		
	//do a dojo.query and loop through each button and set them as disabled
	dojo.query('#map_controlform .layerselector .controlbutton').attr('disabled', "disabled");
	//then override each class setting if the button should be available in each if() test
	//waterways layer
	if (osMap.getZoom() >= 2) {
		dojo.removeAttr(dojo.byId('wwayControl'), 'disabled');
		console.log('foo')
		dojo.addClass(dojo.byId('wwayControl'), 'wwayControl');
	} else {
		dojo.attr(dojo.byId('wwayControl'), 'disabled');
		dojo.removeClass(dojo.byId('wwayControl'), 'wwayControl');
	}
	//attractions layer
	if (osMap.getZoom() > 3) {
		if (user_button_activated['attr'] == null) {
			dojo.byId('attr_check').checked = true;
			user_button_activated['attr'] = true;
		} else if (user_button_activated['attr'] != null && dojo.byId('attr_check').checked != false) {
			dojo.byId('attr_check').checked = true;
		}
		dojo.removeAttr(dojo.byId('attractionControl'), 'disabled');
		dojo.addClass(dojo.byId('attractionControl'), 'attractionControl');
	} else {
		dojo.attr(dojo.byId('attractionControl'), 'disabled');
		dojo.removeClass(dojo.byId('attractionControl'), 'attractionControl');
		dojo.byId('attr_check').checked = false;
		user_button_activated['attr'] = null;
	}
	
	if (osMap.getZoom() >= 5) {
		if (user_button_activated['fish'] == null) {
			dojo.byId('fish_check').checked = true;
			user_button_activated['fish'] = true;
		} else if (user_button_activated['fish'] != null && dojo.byId('fish_check').checked != false) {
			dojo.byId('fish_check').checked = true;
		}
		dojo.removeAttr(dojo.byId('fisheryControl'), 'disabled');
		dojo.addClass(dojo.byId('fisheryControl'), 'fisheryControl');
	} else {
		dojo.attr(dojo.byId('fisheryControl'), 'disabled');
		dojo.removeClass(dojo.byId('fisheryControl'), 'fisheryControl');
		dojo.byId('fish_check').checked = false;
	}
	
	if (osMap.getZoom() >= 6) {
		if (user_button_activated['serv'] == null) {
			dojo.byId('serv_check').checked = true;
			user_button_activated['serv'] = true;
		} else if (user_button_activated['serv'] != null && dojo.byId('serv_check').checked != false) {
			dojo.byId('serv_check').checked = true;
		}
		dojo.removeAttr(dojo.byId('serviceControl'), 'disabled');
		dojo.addClass(dojo.byId('serviceControl'), 'serviceControl');
	} else {
		dojo.attr(dojo.byId('serviceControl'), 'disabled');
		dojo.removeClass(dojo.byId('serviceControl'), 'serviceControl');
		dojo.byId('serv_check').checked = false;
	}
	
	if (osMap.getZoom() >= 7) {
		if (user_button_activated['stru'] == null) {
			dojo.byId('stru_check').checked = true;
			user_button_activated['stru'] = true;
		} else if (user_button_activated['stru'] != null && dojo.byId('stru_check').checked != false) {
			dojo.byId('stru_check').checked = true;
		}
		dojo.removeAttr(dojo.byId('structureControl'), 'disabled');
		dojo.addClass(dojo.byId('structureControl'), 'structureControl');
	} else {
		dojo.attr(dojo.byId('structureControl'), 'disabled');
		dojo.removeClass(dojo.byId('structureControl'), 'structureControl');
		dojo.byId('stru_check').checked = false;
	}
}

var maplocelement;
function writeMapLocation(e)
{
	mp = osMap.getMapPointFromViewPortPx(e.xy);
	osloc = new OSRef(mp.getEasting(), mp.getNorthing());
	maplocelement = window.document.getElementById('map_location_details');
	maplocelement.innerHTML = "<strong>Easting:</strong> "+parseInt(mp.getEasting())+" <strong>Northing:</strong> "+parseInt(mp.getNorthing())+" <strong><br />Short National Grid Ref:</strong> "+osloc.toSixFigureString();
}

/*
 * setup the controls for each layer onto the map
 */

function setupControls()
{
	wwayControl = new OpenLayers.Control.SelectFeature(wwayLayer, {onSelect: onFeatureSelect, onUnselect: onFeatureUnselect});
	controls.wwayControl = wwayControl;
	
	attractionControl = new OpenLayers.Control.SelectFeature(attractionLayer, {onSelect: onFeatureSelect, onUnselect: onFeatureUnselect});
	controls.attractionControl = attractionControl;
	
	fisheryControl = new OpenLayers.Control.SelectFeature(fisheryLayer, {onSelect: onFeatureSelect, onUnselect: onFeatureUnselect});
	controls.fisheryControl = fisheryControl;
	
	serviceControl = new OpenLayers.Control.SelectFeature(serviceLayer, {onSelect: onFeatureSelect, onUnselect: onFeatureUnselect});
	controls.serviceControl = serviceControl;
	
	structureControl = new OpenLayers.Control.SelectFeature(structureLayer, {onSelect: onFeatureSelect, onUnselect: onFeatureUnselect});
	controls.structureControl = structureControl;
	
//	eventControl = new OpenLayers.Control.SelectFeature(eventLayer, {onSelect: onFeatureSelect, onUnselect: onFeatureUnselect});
//	controls.eventControl = eventControl;
	
	routeControl = new OpenLayers.Control.SelectFeature(routeLayer, {onSelect: onFeatureSelect, onUnselect: onFeatureUnselect});
	controls.routeControl = routeControl;
	
}

function putSelectedOnTop(features)
{
	return features.reverse();
}

/*
 * Layer data collection and population
 */

/*
 * populate the services layer;
 * this includes boat hire, pubs and bars, restaurants, moorings
 */
function createServices()
{
	var serfeatures = [];
	servurl = buildBboxUrl(osMap.getExtent(), osMap.getZoom(), 'service');
	serviceLayer.removeFeatures(serviceLayer.features);
	
	deferred = dojo.xhrGet({
		url: servurl,
		handleAs: "json",
		timeout: timeoutValue, //call the error function if nothing comes back after 5 seconds
		load: function(response, ioArgs) {
			dojo.forEach(response['features'], function(item) {
				feature = null;
				feature = getPointFeature(item);
				
				if (feature != null) {
					//additional attributes
					feature.attributes.address = item.properties.address;
					feature.attributes.categories = item.properties.category;
					feature.attributes.display_type = sanitiseProperty(item.properties.display_type);
					feature.attributes.phone_number = item.properties.phone_number;
					feature.attributes.attributes = item.properties.attributes;
					feature.attributes.fid = item.properties.fid;
					feature.attributes.featuretype = 'serv';
					feature.attributes.selected = 0;
					if (typeof selected_service != 'undefined' && item.properties.fid == selected_service) {
						feature.attributes.selected = 1;
					}
					
					if (typeof selectedWaterway != 'undefined') {
						dojo.forEach(item.properties.waterway_codes, function(serwode, idx,arr) {
							if (selectedWaterway == serwode || 'UNKNOWN' == serwode) {
								serfeatures.push(feature);
							}
						})
					} else {
						serfeatures.push(feature);
					}
				}
			})
			//add the features to the layer
			serviceLayer.addFeatures(serfeatures);
			return response;
		},
		error: function(response, ioArgs) {
			console.log('Error: ', response, ioArgs);
			return response;
		}
	})
}

function createWaterways()
{
	wwayLayer.destroyFeatures();
	wwayurl = buildBboxUrl(osMap.getExtent(), osMap.getZoom(), 'section');
	
	var sections = [];
	
	deferred = dojo.xhrGet({
		url: wwayurl,
		handleAs: "json",
		timeout: timeoutValue,
		load: function(response, ioArgs) {
			dojo.forEach(response['features'], function(item) {
				section = null;
				if (osMap.getZoom() <= 4) {
					section = generateWway(item);
				} else {
					section = generateSection(item);
				}
				if (section != null) {
					sections.push(section);
				}
			});
			wwayLayer.addFeatures(sections);
			return response;
		},
		error: function(response, ioArgs) {
			console.log(wwayurl);
			console.log('Error:', response, ioArgs);
			return response;
		}
	});
}

//add argument of selectedWaterway (optional so need to check value)
//check each feature for waterway_code property and if it matches the selectedWaterway then add to layer
function createFisheries()
{
	var fishfeatures = [];
	fishurl = buildBboxUrl(osMap.getExtent(), osMap.getZoom(), 'fishery');
	fisheryLayer.removeFeatures(fisheryLayer.features);

	deferred = dojo.xhrGet({
		url: fishurl,
		handleAs: "json",
		timeout: timeoutValue, //call the error function if nothing comes back after 5 seconds
		load: function(response, ioArgs) {
			dojo.forEach(response['features'], function(item) {
				feature = null;
				feature = getPointFeature(item);

				if (feature != null) {
					//additional attributes
					feature.attributes.address = item.properties.address;
					feature.attributes.categories = item.properties.category;
					feature.attributes.display_type = sanitiseProperty(item.properties.display_type);
					feature.attributes.phone_number = item.properties.phone_number;
					feature.attributes.attributes = item.properties.attributes;
					feature.attributes.featuretype = 'fish';
					feature.attributes.fid = item.properties.fid;
					feature.attributes.selected = 0;
					if (typeof selected_service != 'undefined' && item.properties.fid == selected_service) {
						feature.attributes.selected = 1;
					} 
					//only show fisheries actually on the waterway.
					if (typeof selectedWaterway != 'undefined') {
						if (selectedWaterway == item.properties.waterway_code) {
							fishfeatures.push(feature);
						}
					} else {
						fishfeatures.push(feature);
					}
				}
			})
			putSelectedOnTop(fishfeatures);
			//add the features to the layer
			fisheryLayer.addFeatures(fishfeatures);
			return response;
		},
		error: function(response, ioArgs) {
			console.log('Error: ', response, ioArgs);
			return response;
		}
	});
}

function createAttractions()
{
	var attfeatures = [];
	atturl = buildBboxUrl(osMap.getExtent(), osMap.getZoom(), 'attraction');
	attractionLayer.removeFeatures(attractionLayer.features);
	deferred = dojo.xhrGet({
		url: atturl,
		handleAs: "json",
		timeout: timeoutValue, //call the error function if nothing comes back after 5 seconds
		load: function(response, ioArgs) {
			dojo.forEach(response['features'], function(item) {
				feature = null;
				feature = getPointFeature(item);
				
				if (feature != null) {
					//additional attributes
					feature.attributes.address = item.properties.address;
					feature.attributes.categories = item.properties.category;
					feature.attributes.display_type = sanitiseProperty(item.properties.display_type);
					feature.attributes.phone_number = item.properties.phone_number;
					feature.attributes.attributes = item.properties.attributes;
					feature.attributes.fid = item.properties.fid;
					feature.attributes.featuretype = 'attr';
					feature.attributes.selected = 0;
					if (typeof selected_service != 'undefined' && item.properties.fid == selected_service) {
						feature.attributes.selected = 1;
					}
					if (typeof selectedWaterway != 'undefined') {
						dojo.forEach(item.properties.waterway_codes, function(attcode, idx,arr) {
							if (selectedWaterway == attcode) {
								attfeatures.push(feature);
							}
						});
					} else {
						attfeatures.push(feature);
					}
				}
			})
			putSelectedOnTop(attfeatures);
			//add the features to the layer
			attractionLayer.addFeatures(attfeatures);
			return response;
		},
		error: function(response, ioArgs) {
			console.log('Error: ', response, ioArgs);
			return response;
		}
	});
}

function createStructures()
{
	var structfeatures = [];
	structurl = buildBboxUrl(osMap.getExtent(), osMap.getZoom(), 'structure');
	structureLayer.removeFeatures(structureLayer.features);
	
	deferred = dojo.xhrGet({
		url: structurl,
		handleAs: "json",
		timeout: timeoutValue, //call the error function if nothing comes back after 5 seconds
		load: function(response, ioArgs) {
			dojo.forEach(response['features'], function(item) {
				feature = null;	
				feature = getPointFeature(item);
				
				if (feature != null) {
					feature.attributes.bw_functional_location = item.properties.bw_functional_location;
					feature.attributes.display_type = sanitiseProperty(item.properties.display_type);
					feature.attributes.featuretype = 'stru';
					if (typeof selectedWaterway != 'undefined') {
						if (selectedWaterway == item.properties.waterway_code || selectedWaterway == item.properties.waterway_parent) {
							structfeatures.push(feature);
						}
					} else {
						structfeatures.push(feature);
					}
				}
			})
			//add the features to the layer
			structureLayer.addFeatures(structfeatures);
			return response;
		},
		error: function(response, ioArgs) {
			console.log('Error: ', response, ioArgs);
			return response;
		}
	});
}

/*
 * Stylemaps
 */

var attractionStyleMap = new OpenLayers.StyleMap({
	externalGraphic: '/media/images/site/icons/map/attraction/${display_type}.png',
	graphicWidth: 22,
	graphicHeight: 22,
	graphicOpacity: 1,
	pointRadius: 3,
	strokeColor: '#ff0000', 
	stokeOpacity: 1, 
	strokeWidth: 2, 
	fillColor: '#ff0000', 
	fillOpacity: .5,
	graphicXOffset: 10,
	graphicYOffset: 10
});
var serviceStyleMap = new OpenLayers.StyleMap({
	externalGraphic: '/media/images/site/icons/map/service/${display_type}.png',
	graphicWidth: 22,
	graphicHeight: 22,
	graphicOpacity: 1,
	pointRadius: 3, 
	strokeColor: '#00ff00', 
	strokeOpacity: 1, 
	strokeWidth: 1, 
	fillColor: '#00ff00', 
	fillOpacity: .5
});
var whiteboxStyleMap = new OpenLayers.StyleMap({
	fillColor: "#ffffff",
	fillOpacity : 0.5
});
var structureStyleMap = new OpenLayers.StyleMap({
	externalGraphic: '/media/images/site/icons/map/structure/${display_type}.png',
	graphicWidth: 22,
	graphicHeight: 22,
	graphicOpacity: 1,
	pointRadius: 5, 
	strokeColor: '#000000', 
	strokeOpacity: 1, 
	strokeWidth: 5, 
	fillColor: '#000055', 
	fillOpacity: 1
});

var wwayStyleMap = new OpenLayers.StyleMap({
	pointRadius: 4,
	strokeColor: '#00ff00',
	strokeWidth: 3,
	fillOpacity: 0.7,
	fillColor: '#004400'
});

var fisheryStyleMap = new OpenLayers.StyleMap({
	graphicWidth: 22,
	graphicHeight: 22,
	graphicOpacity: 1,
	pointRadius: 3, 
	strokeColor: '#0000ff', 
	strokeOpacity: 1, 
	strokeWidth: 1, 
	fillColor: '#0000ff', 
	fillOpacity: .5
})
var fisherylookup = {
		1: {externalGraphic: '/media/images/site/icons/map/fishery/game.png'},
		2: {externalGraphic: '/media/images/site/icons/map/fishery/coarse.png'},
		3: {externalGraphic: '/media/images/site/icons/map/fishery/coarse_and_game.png'},
		'coarse': {externalGraphic: '/media/images/site/icons/map/fishery/coarse.png'},
		'game' : {externalGraphic: '/media/images/site/icons/map/fishery/game.png'}
}
fisheryStyleMap.addUniqueValueRules('default', 'display_type', fisherylookup);

var eventStyleMap = new OpenLayers.StyleMap({
	externalGraphic: '/media/images/site/icons/map/attraction_selected.png',
	graphicWidth: 22,
	graphicHeight: 22,
	pointRadius: 6,
	strokeColor: '#557733',
	strokeWidth: 2,
	fillColor: '#000000',
	fillOpacity: 1
});

var routeStyleMap = new OpenLayers.StyleMap({
	graphicWidth: 22,
	graphicHeight: 22,
	pointRadius: 6,
	strokeColor: '#ff0000',
	strokeWidth: 2,
	fillColor: '#000000',
	fillOpacity: 1
	
});

var route_cycling_style = new OpenLayers.Style({
	graphicWidth: 22,
	graphicHeight: 22
});

var rc1 = new OpenLayers.Rule({
	filter: new OpenLayers.Filter.Comparison({
		type: OpenLayers.Filter.Comparison.EQUAL_TO,
		property: "position",
		value: 1
	}),
	symbolizer: {
		externalGraphic: '/media/images/site/icons/map/attraction/cycling_route_1.png'
	}
});
var rc2 = new OpenLayers.Rule({
	filter: new OpenLayers.Filter.Comparison({
		type: OpenLayers.Filter.Comparison.EQUAL_TO,
		property: "position",
		value: 2
	}),
	symbolizer: {
		externalGraphic: '/media/images/site/icons/map/attraction/cycling_route_2.png'
	}
});
var rc3 = new OpenLayers.Rule({
	filter: new OpenLayers.Filter.Comparison({
		type: OpenLayers.Filter.Comparison.EQUAL_TO,
		property: "position",
		value: 3
	}),
	symbolizer: {
		externalGraphic: '/media/images/site/icons/map/attraction/cycling_route_3.png'
	}
});
var rc4 = new OpenLayers.Rule({
	filter: new OpenLayers.Filter.Comparison({
		type: OpenLayers.Filter.Comparison.EQUAL_TO,
		property: "position",
		value: 4
	}),
	symbolizer: {
		externalGraphic: '/media/images/site/icons/map/attraction/cycling_route_4.png'
	}
});
var rc5 = new OpenLayers.Rule({
	filter: new OpenLayers.Filter.Comparison({
		type: OpenLayers.Filter.Comparison.EQUAL_TO,
		property: "position",
		value: 5
	}),
	symbolizer: {
		externalGraphic: '/media/images/site/icons/map/attraction/cycling_route_5.png'
	}
});
var rc6 = new OpenLayers.Rule({
	filter: new OpenLayers.Filter.Comparison({
		type: OpenLayers.Filter.Comparison.EQUAL_TO,
		property: "position",
		value: 6
	}),
	symbolizer: {
		externalGraphic: '/media/images/site/icons/map/attraction/cycling_route_6.png'
	}
});
var rc7 = new OpenLayers.Rule({
	filter: new OpenLayers.Filter.Comparison({
		type: OpenLayers.Filter.Comparison.EQUAL_TO,
		property: "position",
		value: 7
	}),
	symbolizer: {
		externalGraphic: '/media/images/site/icons/map/attraction/cycling_route_7.png'
	}
});
var rc8 = new OpenLayers.Rule({
	filter: new OpenLayers.Filter.Comparison({
		type: OpenLayers.Filter.Comparison.EQUAL_TO,
		property: "position",
		value: 8
	}),
	symbolizer: {
		externalGraphic: '/media/images/site/icons/map/attraction/cycling_route_8.png'
	}
});
var rc9 = new OpenLayers.Rule({
	filter: new OpenLayers.Filter.Comparison({
		type: OpenLayers.Filter.Comparison.EQUAL_TO,
		property: "position",
		value: 9
	}),
	symbolizer: {
		externalGraphic: '/media/images/site/icons/map/attraction/cycling_route_end.png'
	}
});
route_cycling_style.addRules([rc1,rc2,rc3,rc4,rc5,rc6,rc7,rc8,rc9]);

var routeCyclingStyleMap = new OpenLayers.StyleMap(route_cycling_style);

var route_walking_style = new OpenLayers.Style({
	graphicWidth: 22,
	graphicHeight: 22
});
var rw0 = new OpenLayers.Rule({
	filter: new OpenLayers.Filter.Comparison({
		type: OpenLayers.Filter.Comparison.EQUAL_TO,
		property: "position",
		value: 0
	}),
	symbolizer: {
		externalGraphic: '/media/images/site/icons/map/attraction/walking_route_1.png'
	}
});
var rw1 = new OpenLayers.Rule({
	filter: new OpenLayers.Filter.Comparison({
		type: OpenLayers.Filter.Comparison.EQUAL_TO,
		property: "position",
		value: 1
	}),
	symbolizer: {
		externalGraphic: '/media/images/site/icons/map/attraction/walking_route_1.png'
	}
});
var rw2 = new OpenLayers.Rule({
	filter: new OpenLayers.Filter.Comparison({
		type: OpenLayers.Filter.Comparison.EQUAL_TO,
		property: "position",
		value: 2  
	}),
	symbolizer: {
		externalGraphic: '/media/images/site/icons/map/attraction/walking_route_2.png'
	}
});
var rw3 = new OpenLayers.Rule({
	filter: new OpenLayers.Filter.Comparison({
		type: OpenLayers.Filter.Comparison.EQUAL_TO,
		property: "position",
		value: 3
	}),
	symbolizer: {
		externalGraphic: '/media/images/site/icons/map/attraction/walking_route_3.png'
	}
});
var rw4 = new OpenLayers.Rule({
	filter: new OpenLayers.Filter.Comparison({
		type: OpenLayers.Filter.Comparison.EQUAL_TO,
		property: "position",
		value: 4
	}),
	symbolizer: {
		externalGraphic: '/media/images/site/icons/map/attraction/walking_route_4.png'
	}
});
var rw5 = new OpenLayers.Rule({
	filter: new OpenLayers.Filter.Comparison({
		type: OpenLayers.Filter.Comparison.EQUAL_TO,
		property: "position",
		value: 5
	}),
	symbolizer: {
		externalGraphic: '/media/images/site/icons/map/attraction/walking_route_5.png'
	}
});
var rw6 = new OpenLayers.Rule({
	filter: new OpenLayers.Filter.Comparison({
		type: OpenLayers.Filter.Comparison.EQUAL_TO,
		property: "position",
		value: 6
	}),
	symbolizer: {
		externalGraphic: '/media/images/site/icons/map/attraction/walking_route_6.png'
	}
});
var rw7 = new OpenLayers.Rule({
	filter: new OpenLayers.Filter.Comparison({
		type: OpenLayers.Filter.Comparison.EQUAL_TO,
		property: "position",
		value: 7
	}),
	symbolizer: {
		externalGraphic: '/media/images/site/icons/map/attraction/walking_route_7.png'
	}
});
var rw8 = new OpenLayers.Rule({
	filter: new OpenLayers.Filter.Comparison({
		type: OpenLayers.Filter.Comparison.EQUAL_TO,
		property: "position",
		value: 8
	}),
	symbolizer: {
		externalGraphic: '/media/images/site/icons/map/attraction/walking_route_8.png'
	}
});
var rw9 = new OpenLayers.Rule({
	filter: new OpenLayers.Filter.Comparison({
		type: OpenLayers.Filter.Comparison.EQUAL_TO,
		property: "position",
		value: 9
	}),
	symbolizer: {
		externalGraphic: '/media/images/site/icons/map/attraction/walking_route_9.png'
	}
});
var rw10 = new OpenLayers.Rule({
	filter: new OpenLayers.Filter.Comparison({
		type: OpenLayers.Filter.Comparison.EQUAL_TO,
		property: "position",
		value: 10
	}),
	symbolizer: {
		externalGraphic: '/media/images/site/icons/map/attraction/walking_route_10.png'
	}
});
var rw11 = new OpenLayers.Rule({
	filter: new OpenLayers.Filter.Comparison({
		type: OpenLayers.Filter.Comparison.EQUAL_TO,
		property: "position",
		value: 11
	}),
	symbolizer: {
		externalGraphic: '/media/images/site/icons/map/attraction/walking_route_11.png'
	}
});
var rw12 = new OpenLayers.Rule({
	filter: new OpenLayers.Filter.Comparison({
		type: OpenLayers.Filter.Comparison.EQUAL_TO,
		property: "position",
		value: 12
	}),
	symbolizer: {
		externalGraphic: '/media/images/site/icons/map/attraction/walking_route_12.png'
	}
});
var rw13 = new OpenLayers.Rule({
	filter: new OpenLayers.Filter.Comparison({
		type: OpenLayers.Filter.Comparison.EQUAL_TO,
		property: "position",
		value: 13
	}),
	symbolizer: {
		externalGraphic: '/media/images/site/icons/map/attraction/walking_route_13.png'
	}
});
var rw14 = new OpenLayers.Rule({
	filter: new OpenLayers.Filter.Comparison({
		type: OpenLayers.Filter.Comparison.EQUAL_TO,
		property: "position",
		value: 14
	}),
	symbolizer: {
		externalGraphic: '/media/images/site/icons/map/attraction/walking_route_14.png'
	}
});
var rw15 = new OpenLayers.Rule({
	filter: new OpenLayers.Filter.Comparison({
		type: OpenLayers.Filter.Comparison.EQUAL_TO,
		property: "position",
		value: 15
	}),
	symbolizer: {
		externalGraphic: '/media/images/site/icons/map/attraction/walking_route_15.png'
	}
});
route_walking_style.addRules([rw1,rw2,rw3,rw4,rw5,rw6,rw7,rw8,rw9,rw10,rw11,rw12,rw13,rw14,rw15]);
var routeWalkingStyleMap = new OpenLayers.StyleMap(route_walking_style);
