	
	function featuresOnLoad() {
	
	}
	

	var map;
	var layer;
	var stage3startsAt = 7;
	var beenAtStage2 = -1;
	var currentStage;
	var currentZoom = 11;
	var serviceType = 10;

	var poiFactory = new Object();
	
	var blah;
	poiFactory.getFeature = function(feature) {
		var coordinate = new GSPoint(feature.x,feature.y);

		var icon = new GSIcon();
		icon.imageSrc = "http://www.eldernet.co.nz/IM_Custom/Classes/EldernetFacilityAsset/Templates/Images/key-small.png";
		icon.imageSize = new GSDimension(5, 5);
		icon.iconOffset = new GSPoint(-2, -2);
		icon.alt = feature.name;
		
		var poi = new GSPointFeature({
			"name": feature.name,
			"coordinate": coordinate,
			"icon": icon
		});
		
		poi.addEventHandler("click",function(e) {
			
			// Zoom in on the city
			map.centerAndZoom(this.coordinate,stage3startsAt);
			GSUtil.cancelEvent(e);
		});
		
		return poi;
	}
	  

	function hidePleaseWait() {
		pleaseWaitCounter = 0;
		var please = document.getElementById('PleaseWait');
		if (please) {
			please.style.display = 'none';	
		}
	}
	
	var pleaseWaitCounter = 0;
	var pleaseWaitTimeout = null;
	function showPleaseWaitCount() {
		pleaseWaitCounter++;
		showPleaseWait();
		if (pleaseWaitTimeout != null) {
			clearTimeout(pleaseWaitTimeout);
		}
		pleaseWaitTimeout = setTimeout("hidePleaseWait()",10000);
	}
	function hidePleaseWaitCount() {
		pleaseWaitCounter--;
		if (pleaseWaitCounter <= 0) {
			hidePleaseWait();
		}
	}
	
	function showPleaseWait() {
		var please = document.getElementById('PleaseWait');
		if (please) {
			please.style.left = (GSUtil.findPosX(document.getElementById('theMap'))+170)+'px';	
			please.style.top = (GSUtil.findPosY(document.getElementById('theMap'))+200)+'px';	
			please.style.display = '';	
		}
	}

	function hideNoneFound() {
		var none = document.getElementById('NoneFound');
		if (none) {
			 none.style.display = 'none';	
		}
	}
	
	function showNoneFound() {
		var none = document.getElementById('NoneFound');
		if ( none) {
			none.style.left = (GSUtil.findPosX(document.getElementById('theMap'))+115)+'px';	
			none.style.top = (GSUtil.findPosY(document.getElementById('theMap'))+190)+'px';	
			none.style.display = '';	
		}
	}

	function hideBack() {
		var back = document.getElementById('backContainer');
		if (back) {
			back.style.display = 'none';	
		}
	}

	function showBack() {
		var back = document.getElementById('backContainer');
		if (back) {
			back.style.left = (GSUtil.findPosX(document.getElementById('theMap'))+330)+'px';	
			back.style.top = (GSUtil.findPosY(document.getElementById('theMap'))+3)+'px';	
			back.style.display = '';	
		}
	}

	function addStatus(text) {
		document.getElementById('status').innerHTML += '<br>'+text;
	}
	function setStatus(text) {
		document.getElementById('status').innerHTML = text;
	}
	
	function GridLoader(id,map,size,loadURL) {
		this.id = id;
		this.size = size;
		this.got = {};
		this.loadURL = loadURL;
		this.map = map;
		this.layer = this.map.createLayer("GridLoader_"+this.id);   
	}
	
	GridLoader.prototype.hide = function() {
		this.layer.setVisible(false);
	}
	
	GridLoader.prototype.show = function() {
		this.layer.setVisible(true);
	}
	
	GridLoader.prototype.hasGot = function(x,y) {
		var gridX = Math.floor(x/this.size);
		var gridY = Math.floor(y/this.size);
		
		if (typeof(this.got[gridX]) == 'undefined') this.got[gridX] = {};
		if (typeof(this.got[gridX][gridY]) == 'undefined') this.got[gridX][gridY] = false;
		
		return this.got[gridX][gridY];
	}
	
	GridLoader.prototype.setGot = function(x,y) {
		//addStatus('Got: '+x+','+y);
		var gridX = Math.floor(x/this.size);
		var gridY = Math.floor(y/this.size);
		
		if (typeof(this.got[gridX]) == 'undefined') this.got[gridX] = {};
		
		this.got[gridX][gridY] = true;
	}
	
	GridLoader.prototype.getPOIs = function(check) {
		var bounds = [];
		var allBounds = [];
	
		var alignedX = check.minX - (check.minX % this.size);
		var alignedY = check.minY - (check.minY % this.size);
	
		var loopMax = Math.ceil((check.maxX - check.minX) / this.size);
		
		//addStatus('Loading for: '+check.toString()+' loopMax = '+loopMax);
	
		// load the bounds we need to get POIs for
		for (var x = 0; x<=loopMax; x++) {
			for (var y = 0; y<=loopMax; y++) {
				if (!this.hasGot(alignedX+this.size*x,alignedY+this.size*y)) {
					var loadBounds = new GSBounds(
						alignedX+(this.size*x),alignedY+(this.size*y),
						alignedX+(this.size*(x+1)),alignedY+(this.size*(y+1))
					);
					
					bounds[bounds.length] = loadBounds;
				}
			}
		}
		if (bounds.length == (loopMax+1)*(loopMax+1) && bounds.length > 1) {
			// We need to load all squares, so join together
			var combinedBounds = new GSBounds(
				bounds[0].minX,bounds[0].minY,
				bounds[bounds.length-1].maxX,bounds[bounds.length-1].maxY
			);
			combinedBounds.subBounds = bounds;
			bounds = [combinedBounds];
		} 
		
		for (var i=0;i<bounds.length; i++) {
			var loadBounds = bounds[i];
			var loadURL = this.loadURL;
			loadURL += "/MinX/"+(loadBounds.minX)+"/MaxX/"+(loadBounds.maxX)+"/MinY/"+(loadBounds.minY)+"/MaxY/"+(loadBounds.maxY);

			
			
			//addStatus(loadURL);
					
			/*var loader = new GSLoader();
			loader.bounds = loadBounds;
			loader.gridLoader = this;
			loader.onload = GridLoaderOnLoadHandler;	
			loader.load(loadURL);*/
			
			var loader = new JSONscriptRequest();
			loader.bounds = loadBounds;
			loader.gridLoader = this;
			loader.onload = GridLoaderOnLoadHandler;	
			loader.load(loadURL);
			showPleaseWaitCount();
		}
		if (bounds.length == 0) {
			hidePleaseWaitCount();
		}
		
	}
	
	function GridLoaderOnLoadHandler() {
		layer.clear();
		hidePleaseWaitCount();
		if (!this.gridLoader.hasGot(this.bounds.minX,this.bounds.minY)) {
			this.gridLoader.layer.addFeaturesJson(this.data, initFeature);
			//this.gridLoader.layer.addFeatures(this.data);
			if (typeof(this.bounds.subBounds) != 'undefined') {
				for (var i in this.bounds.subBounds) {
					this.gridLoader.setGot(this.bounds.subBounds[i].minX,this.bounds.subBounds[i].minY);
				}
			} else {
				this.gridLoader.setGot(this.bounds.minX,this.bounds.minY);
			}
		}
	}      
		
	
	
	function StateStorer() {
		this.clear();
	}
	
	StateStorer.prototype.setValue = function(name,value) {
		this.values[name] = value;
	}
	
	StateStorer.prototype.hasValue = function(name) {
		return (typeof(this.values[name]) != 'undefined');
	}
	
	StateStorer.prototype.getValue = function(name) {
		if (this.hasValue(name)) {
			return this.values[name];
		} else {
			return undefined;
		}
	}
	
	StateStorer.prototype.clear = function() {
		this.values = {};
	}
	
	StateStorer.prototype.save = function() {
		var splitURL = location.href.split('#');
		var rawHref = splitURL[0];
	
		// serialize status values
		var s = '';
		for (var i in this.values) {
			if (s.length) s += '&';
			s += i+'='+escape(this.values[i]);
		}

		// store in the document's location		
		location.href = rawHref+'#'+s;
		
	}
	
	StateStorer.prototype.load = function() {
		// load the state from the url
			
		var returnVal = false;
		this.clear();
			
		// check if we have a #... ;-)
		var hashPos = location.href.indexOf('#');
		if (hashPos != -1) {
			var info = location.href.substring(hashPos+1).split('&');
			for (var i in info) {
				var attVal = info[i].split('=');
				if (attVal.length == 2) {
					var tryNumber = parseFloat(unescape(attVal[1]));
					if (isNaN(tryNumber)) {
						this.values[attVal[0]] = unescape(attVal[1]);
					} else {
						this.values[attVal[0]] = tryNumber;
					}
					returnVal = true;
				}
			}
		} 
	
		return returnVal;
	}
	
	
	
	function displayService(id) {
		// save the current state of the map		
		state.save();
		
		// go to the service details page
		document.location = currentServer+'Facilities/Service/DisplayService/FromMap/1/FaStID/'+id;
	}
	
	function initFeature(poi,data) {
		
		var icon = new GSIcon();
		icon.imageSrc = "http://www.eldernet.co.nz/IM_Custom/Classes/EldernetFacilityAsset/Templates/Images/key-"+data.type+".png";
		icon.imageSize = new GSDimension(9, 9);
		icon.iconOffset = new GSPoint(-4, -4);
		icon.alt = poi.name;

		poi.setIcon(icon);

		poi.addEventHandler("click",function(e) {
			// Display the service
			if (currentZoom < stage3startsAt) {
				displayService(this.id);
			} else {
				map.centerAndZoom(this.coordinate,stage3startsAt-2);
			}
			GSUtil.cancelEvent(e);
		});

		
	}             
	var gls = {};
	
	function loadPOIs() {
		hideNoneFound();

		if (currentStage == 1) {
			// hide POIs from other service types
			for (var i in gls) gls[i].hide();
			
			// show NZ cities
			showInitialPoints();
			hidePleaseWait();
		} else {
		
			// hide NZ cities
			hideInitialPoints();
			
			// create a gridloader for the POIs
			if (typeof(gls[serviceType]) == 'undefined') {
				gls[serviceType] = new GridLoader(serviceType,map,51456,currentServer+"Facilities/Service/GetPois/JSON/1/StID/"+serviceType);
			}
			// hide POIs from other service types
			for (var i in gls) if (gls.id != serviceType) gls[i].hide();
			
			// show any existing POIs for this service type
			gls[serviceType].show();

			var currentBounds = map.getBounds();
			
			// make sure the state knows which service type we are using and where we are on the map
			state.setValue('st',serviceType);
			state.setValue('x',(currentBounds.minX+currentBounds.maxX)/2);
			state.setValue('y',(currentBounds.minY+currentBounds.maxY)/2);
			state.setValue('z',currentZoom);
			
			gls[serviceType].getPOIs(currentBounds);
		}
		
	}   

	  
	function setServiceType(id) {
		serviceType = id;
		
		showPleaseWait();
		loadPOIs();
	}      
	  
	function setStage(i) {
		currentStage = i;
		state.setValue('cs',currentStage);
		if (i == 1) { 
			beenAtStage2 = -1;
		}
		if (i == 2) {
			beenAtStage2 = 1;
			showBack();
		}
		if (i == 3) showBack();
		
		for (var j=1; j<=3; j++) {
			if (i != j) document.getElementById('stage'+j).style.display = 'none';	
		}	
		document.getElementById('stage'+i).style.display = '';	
	}      
	  
	var nzPoints = new Array(
		{name:'Invercargill', x:2153314,y:5411046},{name:'Alexandra', x:2226650,y:5544605},{name:'Queenstown', x:2173664,y:5568214},{name:'Gore', x:2196380,y:5448770},{name:'Baclutha', x:2258502,y:5436234},{name:'Hokitika', x:2343529,y:5830219},{name:'Greymouth', x:2362679,y:5860506},{name:'Westport', x:2393963,y:5938253},{name:'Dunedin', x:2316034,y:5478517},{name:'Oamaru', x:2350553,y:5566832},{name:'Timaru', x:2369220,y:5645190},{name:'Ashburton', x:2410052,y:5700241},{name:'Christchurch', x:2480750,y:5741750},{name:'Kaikoura', x:2565953,y:5866697},{name:'Murchison', x:2453965,y:5933842},{name:'Takaka', x:2493739,y:6039121},{name:'Blenheim', x:2589460,y:5965610},{name:'Nelson', x:2530527,y:5989802},{name:'Wellington', x:2658550,y:5990700},{name:'Hutt', x:2676300,y:6003050},{name:'Waikanae', x:2683380,y:6034920},{name:'Paraparaumu', x:2677870,y:6031950},{name:'Levin', x:2703410,y:6062270},{name:'Palmerston North', x:2732230,y:6091390},{name:'Wanganui', x:2684478,y:6140273},{name:'Masterton', x:2733560,y:6024890},{name:'Waipukurau', x:2813576,y:6128342},{name:'Dannevirke', x:2773841,y:6106451},{name:'Hastings', x:2839450,y:6166980},{name:'Napier', x:2843330,y:6180430},{name:'Gisborne', x:2946800,y:6270850},{name:'Te Puia Springs', x:2975505,y:6335846},{name:'Wairoa', x:2892390,y:6231594},{name:'Whakatane', x:2860750,y:6352700},{name:'New Plymouth', x:2603210,y:6236690},{name:'Hawera', x:2619630,y:6179040},{name:'Taupo', x:2778770,y:6274270},{name:'Rotorua', x:2794680,y:6335090},{name:'Tauranga', x:2789550,y:6385150},{name:'Te Kuiti', x:2699356,y:6316607},{name:'Taumarunui', x:2706140,y:6255520},{name:'Hamilton', x:2710850,y:6378200},{name:'Thames', x:2736500,y:6447650},{name:'Whitianga', x:2751263,y:6481558},{name:'Auckland', x:2663200,y:6478600},{name:'North Shore', x:2664030,y:6508130},{name:'Dargaville', x:2588920,y:6584290},{name:'Kaikohe', x:2583680,y:6643565},{name:'Kawakawa', x:2607843,y:6646105},{name:'Kerikeri', x:2597312,y:6663293},{name:'Kaitaia', x:2534737,y:6676601},{name:'Whangarei', x:2631150,y:6606800}	
	);
	
	function hideInitialPoints() {
		layer.clear();
	}
	function showInitialPoints() {
		layer.clear();
		for (var i=0; i<nzPoints.length; i++) {
			layer.addFeature(poiFactory.getFeature(nzPoints[i]));
		}
	}

	function showNZ() {
		// clear the state
		state.clear();
		
		var coordinate = new GSPoint(2530000, 5990000);
		map.centerAndZoom(coordinate, 11);
		//showInitialPoints();
	}
	
	function goBack() {
		if (currentStage == 3 && beenAtStage2 == 1) {
			setStage(2);
		} else {
			setStage(1);
			showNZ();
		}
		
	}
	

	
	var listeners = new Object();
	listeners.mapBoundsChanged = function(map, oldBounds, newBounds) {
		loadPOIs();
	}
	listeners.mapZoomed = function(map,oldZoomLevel,newZoomLevel) {
		currentZoom = newZoomLevel;
		//setStatus(currentZoom);
		
		if (newZoomLevel <= stage3startsAt) {
			// show the facility type selection stuff
			setStage(3);
		} else {
			// hide the facility type selection stuff
			setStage(1);
		}
		loadPOIs();
		if (newZoomLevel == 11) {
			hideBack(); 
		} else {
			showBack();
		}
			
	}
	listeners.mapClicked = function(map,object) {
		if (currentStage == 1) {
			// Only zoom "onclick" if currently zoomed out (stage 1)
			map.centerAndZoom(object,stage3startsAt);
		}
	}
	

	/*******************************
	* Keyword search functionality *
	********************************/
	function checkSubmit(e) {
		var key;
		var keychar;
		
		if (window.event)
		   key = window.event.keyCode;
		else if (e)
		   key = e.which;
		else
		   return true;
		keychar = String.fromCharCode(key);
		keychar = keychar.toLowerCase();
		
		if (key == 13) {
			doMapSearch(true);
			return false;
		} else {
			return true;	
		}
		
	}

	function doMapSearch(doshow) {
		showPleaseWait();
		var keyword = document.getElementById('locationKeyword').value;
		document.getElementById('locationKeywordDisplay').innerHTML = keyword;		
		
		// get a layer to use later
		var loader = new JSONscriptRequest();
		if (doshow) {
			loader.onload = searchCompleteAndShow;
		} else {
			loader.onload = searchComplete;
		}
		
		loader.load('http://www.eldernet.co.nz/Facilities/Service/POIProxy?category[]=ADMINISTRATIVE&category[]=ROAD&category[]=SUBURB&name='+escape(keyword));
		//loader.load('http://202.27.236.84/pois.json?clientId=eldernet&category[]=ADMINISTRATIVE&category[]=ROAD&category[]=SUBURB&name='+escape(keyword));
		//loader.load('http://202.27.236.84/pois.json?clientId=eldernet&name='+escape(keyword));
		
		state.setValue('st',serviceType); 
		state.setValue('keyword',keyword);
		
	}

	var searchResults = [];
	
	function searchCompleteAndShow(data) {
		searchComplete(data);
		setStage(2);
	}
	
	function searchComplete(data) {
		hidePleaseWait();
		searchResults = data.pois.poi;
		
		// display a list of options
		var searchResultList = document.getElementById('searchResultList');

		// clear the list
		while (searchResultList.length) {
			searchResultList.options[searchResultList.options.length-1] = null;
		}
				
		var desc;
		for (var i=0; i<searchResults.length; i++) {
			var p = searchResults[i];
			desc = p.name+', '+p.suburb+', '+p.district+', '+p.region;
			searchResultList.options[searchResultList.options.length] = new Option(desc,i);	
		}
	}
	
	function zoomToSearchResult(index) {
		map.centerAndZoom(new GSPoint(searchResults[index].x,searchResults[index].y),3);
	}   

	function updateServiceTypeRadio() {
		var radios = document.forms.theForm.RadioGroup1;
		for (var j=0; j<radios.length; j++) {
			if (radios[j].value == serviceType) {
				radios[j].checked = true;	
			}
			if (radios[j].value == 'DayCare' && serviceType > 1000000) {
				radios[j].checked = true;
				var dayCareRes = document.getElementById('DayCareRes');
				for (var k=0; k< dayCareRes.options.length;k++) {
					if (dayCareRes.options[k].value == serviceType) {
						dayCareRes.selectedIndex = k;
					}	
				}
			}
		}

	}
	
	var state = new StateStorer();
	
	function initMap() {
		map = new GSMap('theMap');
		map.addControl(GSMap.MAP_CONTROL);
		
		// get a layer to use later
		layer = map.createLayer("layer");
	
		map.addListener(listeners);
		
		if (state.load()) {
			if (state.hasValue('keyword')) {
				document.getElementById('locationKeyword').value = state.getValue('keyword');
				beenAtStage2 = 1;
			}
			serviceType = state.getValue('st');
			updateServiceTypeRadio();
			
			setStage(state.getValue('cs'));
			switch (currentStage) {
				case 1: 
					showNZ();
					break;
				case 2:
					if (state.hasValue('x')) {
						var coord = new GSPoint(state.getValue('x'),state.getValue('y'));
						map.centerAndZoom(coord,state.getValue('z'));
					} else {
						showNZ();
					}
					doMapSearch(true);
					break;
				case 3:
					var coord = new GSPoint(state.getValue('x'),state.getValue('y'));
					map.centerAndZoom(coord,state.getValue('z'));
					if (state.hasValue('keyword')) doMapSearch(false);
					break;
			}
			
		} else {
			setStage(1);
			showNZ();
		}
		
	}

	
	
function escapeHTML(str) {
	var result = new String(str).replace(/&/g,"&amp;");
	result = result.replace(/</g,"&lt;");
	result = result.replace(/>/g,"&gt;");
	result = result.replace(/"/g,"&quot;");
	return result;
}      


