// requires /js/summary-info-search-areas.js

var SearchPageName="SummaryInfo";
var Subdirectory=SearchPageName+"/";

registerInitFunction(function() {
	initAreas();
	setAreaTypeID(getInitialAreaType());
	initTextualSearch();
});

function setAreaTypeID(areaTypeID) {
	areaTypeID=setAreaTypeIDBase(areaTypeID);
	mouseoutListener();
}

function areaTypeButtonClick(inputElement) {
	setAreaTypeID(inputElement.value);
}

var map;
var polygons;
var currentPolygon=null;

function mouseoutListener() {
	if (currentPolygon) map.removeOverlay(currentPolygon);
	currentPolygon=null;
}

new function() {
	var MINIMUM_ZOOM=5;
	var MAP_CENTRE_OFFSET=[-0.8,-0.5];
	var DEFAULT_MAP_TYPE;
	var borderColor="#ff0000";

	var clickable_styler;
	var MapMessage;
	var NoMapAvailableMessage;

	registerInitFunction(function() {
		$(".NameIndex div").each(function(){
			$(this).mouseover(nameRowMouseOver);
			$(this).mouseout(nameRowMouseOut);
		});
		if (typeof(GMap2)=="undefined") {
			$("#map_canvas").html('<p style="font-weight: bold; text-align: center; margin-top: 230px">Map server is currently unavailable</p>');
			return;
		}
		if (!GBrowserIsCompatible()) return;
		DEFAULT_MAP_TYPE=G_NORMAL_MAP;
		var zoom=parseInt(getQueryStringValue("zoom"));
		var centre=null;
		var centreParam=getQueryStringValue("centre");
		if (centreParam) centre=constructGLatLng(centreParam);
		// support for summary info generated parameters:
		var latCentre=parseFloat(getQueryStringValue("LatCentre"));
		var longCentre=parseFloat(getQueryStringValue("LongCentre"));
		var latExt=parseFloat(getQueryStringValue("LatExt"));
		var lngExt=parseFloat(getQueryStringValue("LongExt"));
		if (latCentre && longCentre) centre=new GLatLng(latCentre,longCentre);
		
		var mapTypeParam=getQueryStringValue("maptype");
		var mapType=DEFAULT_MAP_TYPE;
		if (mapTypeParam) mapType=getMapType(mapTypeParam);
		GPolygon.prototype.containsLatLng=polygonContainsLatLng;
		canvas=document.getElementById("map_canvas");
		if (!canvas) throw new Error('ERROR: missing element with id="map_canvas"');
		clickable_styler=document.getElementById("clickable_styler");
		MapMessage=document.getElementById("MapMessage");
		NoMapAvailableMessage=MapMessage.firstChild.nodeValue;
		
		var getMinimumResolution=function() {return MINIMUM_ZOOM;};
		G_PHYSICAL_MAP.getMinimumResolution=getMinimumResolution; 
		G_NORMAL_MAP.getMinimumResolution=getMinimumResolution;
		G_SATELLITE_MAP.getMinimumResolution=getMinimumResolution;
		G_HYBRID_MAP.getMinimumResolution=getMinimumResolution;

		map=new GMap2(canvas);
		polygons=constructPolygons();

		addGetPolylinesPrototype(polygons[0]);

		var latlngbounds=new GLatLngBounds();
		for (var i=0; i<polygons.length; i++) extendBounds(latlngbounds,polygons[i]);

		if (!centre) {
			centre=latlngbounds.getCenter();
			centre=new GLatLng(centre.lat()+MAP_CENTRE_OFFSET[0],centre.lng()+MAP_CENTRE_OFFSET[1]);
			if (!zoom) zoom=map.getBoundsZoomLevel(latlngbounds);
		}
		if (!zoom) {
			if (latExt && lngExt) {
				zoom=map.getBoundsZoomLevel(new GLatLngBounds(new GLatLng(centre.lat()-latExt/2,centre.lng()-lngExt/2),new GLatLng(centre.lat()+latExt/2,centre.lng()+lngExt/2)));
			} else {
				zoom=MINIMUM_ZOOM;
			}
		}
		map.setCenter(centre,zoom,mapType);
		var mapUIOptions=map.getDefaultUI();
		mapUIOptions.controls.maptypecontrol=false;
		mapUIOptions.controls.menumaptypecontrol=true;
		mapUIOptions.controls.scalecontrol=false;
		map.setUI(mapUIOptions);
		map.enableContinuousZoom();

		var mapSize=new GSize(map.getSize().width-2,map.getSize().height-2); // map.getSize() incorrectly reports the size including the border of the containing div
		var backgroundSize=new GSize(mapSize.width*2,mapSize.height*2);
		initBackgrounds(latlngbounds.getCenter(),backgroundSize,5); // 5 is the "standard" zoom level (one less than the background resolution), but this is somehow affected by the canvas size so may need tweaking.
		
		GEvent.addListener(map,"click",function() {
			if (currentPolygon) window.location=currentPolygon.href;
		});

		GEvent.addListener(map,"mousemove",mousemoveListener);
		GEvent.addListener(map,"mouseout",mouseoutListener);

		refreshBackground();

		var p_areaID=getQueryStringValue("AreaID");
		if (p_areaID) {
			var area=areaMap[p_areaID];
			if (area) highlightPolygon(polygons[area.index]);
		}
	});

	function extendBounds(latlngbounds,polygon) {
		var polygonBounds=polygon.getBounds();
		if (!polygonBounds) return;
		latlngbounds.extend(polygonBounds.getSouthWest());
		latlngbounds.extend(polygonBounds.getNorthEast());
	}

	function constructPolygons() {
		var pageExtension=getSummaryInformationPageExtension();
		var polygons=[];
		for (var areaID in areaMap) {
			var area=areaMap[areaID];
			var areaName=area[1];
			var encodedMultiPolygon=area[2];
			if (!encodedMultiPolygon) encodedMultiPolygon=[];
			var areaTypeID=area.areaTypeID;
			var nameRowElement=document.getElementById("NameRow_"+areaTypeID+"_"+area.index);
			if (!nameRowElement) throw new Error('ERROR: missing element with id="NameRow_'+areaTypeID+"_"+area.index+'"');
			var aElement=getFirstElementByTagName("a",nameRowElement);
			if (!aElement) throw new Error('ERROR: row element with id="NameRow_'+areaTypeID+"_"+area.index+'" does not contain an A element');
			var polygon=constructPolygon(encodedMultiPolygon,"#ff0000",true,1);
			polygon.areaTypeID=areaTypeID;
			polygon.index=area.index;
			polygon.href=$(aElement).attr("href"); // use jquery attr() instead of getAttribute() as IE6 converts latter to absolute
			polygon.absoluteHref=aElement.href;
			polygon.name=aElement.firstChild.nodeValue;
			polygon.encodedMultiPolygon=encodedMultiPolygon;
			polygons.push(polygon);
		}
		return polygons;
	}		

	function constructPolygon(encodedMultiPolygon,colorArgument,fillArgument,weightArgument) {
		var polylinesArgument=[];
		for (var i=0; i<encodedMultiPolygon.length; i++) {
			var encodedPolygon=encodedMultiPolygon[i];
			for (var j=0; j<encodedPolygon.length; j++) {
				var encodedPolyline=encodedPolygon[j];
				polylinesArgument.push({points: encodedPolyline[0], levels: encodedPolyline[1], color: colorArgument, opacity: 1, weight: weightArgument, numLevels: 18, zoomFactor: 2});
			}
		}
		var polygon=new GPolygon.fromEncoded({polylines: polylinesArgument, outline: true, fill: fillArgument, color: colorArgument, opacity: 0.2});
		polygon.encodedMultiPolygon=encodedMultiPolygon;
		return polygon;
	}

	function nameRowMouseOver() {
		this.className="Highlighted";
		var lastUnderscorePos=this.id.lastIndexOf("_");
		if (lastUnderscorePos==-1) return;
		var polygonIndex=parseInt(this.id.substring(lastUnderscorePos+1));
		if (polygons) highlightPolygon(polygons[polygonIndex]);
	}
	
	function nameRowMouseOut() {
		this.className=null;
		highlightPolygon(null);
	}

	function getFirstElementByTagName(tagName,containerElement){
		var elements=containerElement.getElementsByTagName(tagName);
		return (elements.length==0) ? null : elements[0];
	}

	function mousemoveListener(latlng) {
		highlightPolygon(getPolygon(latlng));
	}

	function highlightPolygon(polygon) {
		if (polygon==currentPolygon) return;
		if (currentPolygon) map.removeOverlay(currentPolygon);
		currentPolygon=polygon;
		if (polygon) {
			map.addOverlay(polygon);
			MapMessage.firstChild.nodeValue=polygon.name;
			MapMessage.style.fontWeight="bold";
			window.status=polygon.absoluteHref;
			if (clickable_styler) {
				clickable_styler.className="clickable";
				clickable_styler.title=polygon.name;
			}
		} else {
			MapMessage.firstChild.nodeValue=NoMapAvailableMessage;
			MapMessage.style.fontWeight="normal";
			window.status="";
			if (clickable_styler) {
				clickable_styler.className="not_clickable";
				clickable_styler.title="";
			}
		}
	}

	function getPolygon(latlng) {
		if (currentPolygon!=null && currentPolygon.containsLatLng(latlng)) return currentPolygon;
		for (var i=0; i<polygons.length; i++) {
			var polygon=polygons[i];
			if (polygon.areaTypeID!=AreaTypeID) continue;
			if (polygon.containsLatLng(latlng)) return polygon;
		}
		return null;
	}

	function addGetPolylinesPrototype(polygon) {
		$.each(polygon,function(propertyName,propertyValue) {
			if (propertyValue instanceof Array && propertyValue.length>0) {
				var potentialPolyline=propertyValue[0];
				if (potentialPolyline.getLength) { // potentialPolyline has a function called getLength, confirming it is a GPolyline
					GPolygon.prototype.getPolylines=function() {return this[propertyName];};
					return false; // stop iterating
				}
			}
		});
	}

	// Create polygon method for collision detection
	function polygonContainsLatLng(latLng) {
		if (!this.getBounds()) return false;
		if(!this.getBounds().containsLatLng(latLng)) return false;
		if (!this.getPolylines) {
			// we were unable to find the polylines array, so we are limited to using the published API which provides access to only the first polyline.
			return containsLatLng(this,latLng);
		}
		var polylines=this.getPolylines();
		var inside=false;
		for (var i=0; i<polylines.length; i++) {
			inside=inside ^ containsLatLng(polylines[i],latLng);
		}
		return inside;
	
		function containsLatLng(polyline,latLng) {
			// Do simple calculation so we don't do more CPU-intensive calcs for obvious misses
			if(!polyline.getBounds().containsLatLng(latLng)) return false;
			var numPoints = polyline.getVertexCount();
			var inPoly = false;
			var i;
			var j = numPoints-1;
			for(var i=0; i < numPoints; i++) { 
				var vertex1 = polyline.getVertex(i);
				var vertex2 = polyline.getVertex(j);
				if (vertex1.lng() < latLng.lng() && vertex2.lng() >= latLng.lng() || vertex2.lng() < latLng.lng() && vertex1.lng() >= latLng.lng())  {
					if (vertex1.lat() + (latLng.lng() - vertex1.lng()) / (vertex2.lng() - vertex1.lng()) * (vertex2.lat() - vertex1.lat()) < latLng.lat()) inPoly = !inPoly;
				}
				j = i;
			}
			return inPoly;
		};
	}

	function constructGLatLng(urlValue) {
		// can't use GLatLng.fromUrlValue() as invalid values throw an exception that can't be caught
		var latLngArray=urlValue.split(',');
		if (latLngArray.length!=2) return null;
		var lat=parseFloat(latLngArray[0]);
		var lng=parseFloat(latLngArray[1]);
		if (isNaN(lat) || isNaN(lng)) return null;
		return new GLatLng(lat,lng);
	}

	function getMapType(urlArg) {
		var mapTypeMap={h:G_HYBRID_MAP, k:G_SATELLITE_MAP, m:G_NORMAL_MAP, p:G_PHYSICAL_MAP};
		var mapType=mapTypeMap[urlArg];
		return mapType ? mapType : DEFAULT_MAP_TYPE;
	}
}();

function initTextualSearch() {
	if (location.search && location.search.indexOf("SearchQuery")!=-1) {
		var searchQueryInputElement=document.getElementById("SearchQuery");
		searchQueryInputElement.select();
	}
}

function getSummaryInformationPageExtension() {
	var sampleJSPPageURLLink=document.getElementById("SampleJSPPageURL");
	if (!sampleJSPPageURLLink) return ".jsp";
	var sampleJSPPageURL=sampleJSPPageURLLink.href;
	return sampleJSPPageURL.substring(sampleJSPPageURL.lastIndexOf('.'));
}


