// global variables
var daIndex = 0;
var applications;
var selectedApplication;
var rectangle;
var progressBar;
var pageContext;
var groups;
var groupKeys;
var groupsCount = 0;

// global constants
var DA_LOAD_ALL = 0;
var DA_LOAD_DETAIL = 1;
var CENTER = 0;
var BOTTOM = 1;

function load(context) {

	pageContext = context;

	// quick check to see if GMap div is hidden (this means other conditional presentation logic on the page has found a problem with the page first)
	if (GMapUtil.getGMapDiv() == null) return;

	if (GBrowserIsCompatible()) {

		// create and setup the map
		GMapUtil.map = new GMap2(GMapUtil.getGMapDiv());
		GMapUtil.map.enableDoubleClickZoom();

		// initialise controls
		GMapUtil.map.addControl(new GLargeMapControl());
		GMapUtil.map.addControl(new GMapTypeControl());
		GMapUtil.map.addControl(new GScaleControl());
		if (pageContext == DA_LOAD_DETAIL)
			GMapUtil.map.addControl(new GOverviewMapControl());

		// load xml data into map
		GDownloadUrl("/DataSource/DANotifications/DAsOnline.xml", onLoadXml);
		
	} else {
		// browser is not compatible, take the appropriate action based on the pageContext

		switch (pageContext) {

			case DA_LOAD_ALL:
				window.location = "DAExhibition.asp";
				break;

			case DA_LOAD_DETAIL:
				GMapUtil.getGMapDiv().style.display = "none";
				break;
		}
	}
}

function unload() {
	try {
		GUnload();
	}
	catch (ex) {
		alert("**Error** : " + ex.message); 
	}
}

function onLoadXml(data, responseCode) {

	if (responseCode != 404) {

		// attempt to parse xml
		GMapUtil.xml = GXml.parse(data);
		if (GMapUtil.xml.childNodes.length == 0) {

			// no children found, an error has occured
			onLoadError("There was no content found in XML data");

		} else {

			markers = new Array();
			switch (pageContext) {
				// load all the DA's
				case DA_LOAD_ALL:

					// find the total bounds of all points, and center the map with the required zoom to fit
					// (must call map.setCenter(...) before any other map operations can be done)
					CenterMapToTotalBounds();

					// group applications
					GroupApplications();
					
					// add markers to the map
					LoadAllDAs();

					break;

				// only load the DA with the requested TPK
				case DA_LOAD_DETAIL:

					CenterMapToDetail();

					// group applications
					GroupApplications();

					// add markers to the map
					LoadDetailDA();

					break;
			}
		}
	} else {
		// response code was not normal, an error has occured
		onLoadError("data not found");
	}
}

// handle a load exception
function onLoadError(errMsg) {
	alert("There was an error loading the map XML data:\n" + errMsg);
}

function CenterMapToTotalBounds() {

	// collect all the applications
	applications = GMapUtil.xml.getElementsByTagName("Application");

	// reset the min/max lat/lng bounds
	var minLat = 100000000000;
	var maxLat = -100000000000;
	var minLng = 100000000000;
	var maxLng = -100000000000;

	// iterate through the applications
	for (var i=0; i<applications.length; i++ ) {

		// get the application
		var application = applications[i];

		// get the lat/lng values
		var lat = XmlUtil.getChildText(application, "Latitude");
		var lng = XmlUtil.getChildText(application, "Longitude");

		// skip null values
		if ((lat == "null")  | (lng == "null")) continue;

		// test for the min/max lat/lng bounds
		if (lat < minLat) minLat = lat;
		if (lat > maxLat) maxLat = lat;
		if (lng < minLng) minLng = lng;
		if (lng > maxLng) maxLng = lng;

	}

	// center the map around the bounds center, with the zoom required to fit the entire bounds
	var bounds = new GLatLngBounds(GMapUtil.getLatLng(minLat, minLng), GMapUtil.getLatLng(maxLat, maxLng));
	var zoom = GMapUtil.map.getBoundsZoomLevel(bounds);
	GMapUtil.map.setCenter(bounds.getCenter(), zoom);

	// add the rectangle and the progress bar
	InitLoadingOverlays(bounds, CENTER);
}

function InitLoadingOverlays(bounds, progressPosition) {
	// add a rectangle for debugging
	rectangle = new Rectangle(bounds, 2, "#ff6666");
	GMapUtil.map.addOverlay(rectangle);

	// add the progress bar
	var center = GMapUtil.map.fromLatLngToDivPixel(bounds.getCenter());
	var southWest = GMapUtil.map.fromLatLngToDivPixel(bounds.getSouthWest());
	var northEast = GMapUtil.map.fromLatLngToDivPixel(bounds.getNorthEast());
	var padding = 20;
	var width = (northEast.x - southWest.x) - padding;
	var height = 20;
	var y;
	switch (progressPosition) {
		case CENTER:
			y = center.y - parseInt(height / 2);
			break;
		case BOTTOM:
			y = northEast.y - (parseInt(height / 2) + padding);
			break;
	}
	progressBar = new ProgressBar(center.x - parseInt(width / 2), y, width, height, "#ff0000", "#00ff00");
	GMapUtil.map.addOverlay(progressBar);
}

function CenterMapToDetail() {
	// find the tpk from the request string (exit if not found)
	var url = window.location.href.split("?tpk=");
	if (url.length != 2) return;

	// find the application matching the given tpk
	applications = GMapUtil.xml.getElementsByTagName("Application");
	for (var i=0; i<applications.length; i++ ) {

		selectedApplication = applications[i];
		var tpk = XmlUtil.getChildText(selectedApplication, "ApplicationTPK");

		// found the application
		if (tpk == url[1]) {

			// get the latLng coords
			var lat = XmlUtil.getChildText(selectedApplication, "Latitude");
			var lng = XmlUtil.getChildText(selectedApplication, "Longitude");
			
			// skip null values
			if ((lat == "null")  | (lng == "null")) {
					alert(lat + ":" + lng);
			}

			var latLng = GMapUtil.getLatLng(lat, lng);

			// center the map around the single application
			GMapUtil.map.setCenter(latLng, 17);

			// get the rectangle and progressbar bounds coords 
			var point = GMapUtil.map.fromLatLngToDivPixel(latLng);
			var sw = GMapUtil.map.fromDivPixelToLatLng(new GPoint(point.x - 60, point.y - 50));
			var ne = GMapUtil.map.fromDivPixelToLatLng(new GPoint(point.x + 60, point.y + 50));
			var bounds = new GLatLngBounds(sw, ne);

			// return with the current application as the selected one
			return;
		}
	}

	// application was not found, default to null
	application = null;
}

function GroupApplications() {

	// initialise the groups (as an associative array - key = lat + lng, value = Array of applications)
	groups = new Array();

	// initialise the groupsIndex lookup (due to poor Javascript support for associative arrays)
	groupKeys = new Array();
	
	for (var i=0; i<applications.length; i++ ) {
		
		// take the current application
		var application = applications[i];

		// get the latLng coords
		var lat = XmlUtil.getChildText(application, "Latitude");
		var lng = XmlUtil.getChildText(application, "Longitude");
		var coords = lat + "," + lng;

		// skip nulls
		if (coords.toLowerCase().indexOf("null") > -1) continue;

		// set the group key
		groupKeys[groupsCount] = coords;
		
		// if the group key (of lat and lng) does not exist, create an array for that key
		if (groups[coords] == null) {
			groups[coords] = new Array();
			groupsCount++;
		}
		// add the application to the group key
		groups[coords].push(application);
	}
}

function GetGroup(index) {
	return groups[groupKeys[index]];
}

function GetGroupCoords(index) {
	return groupKeys[index];
}

function GetGroupLatLng(index) {
	var coords = GetGroupCoords(index);
	return GMapUtil.getLatLng(coords);
}

function LoadAllDAs() {

	// exit if past the length of the applications collection
	if (daIndex == groupsCount) {
		if (IsUsingProgress()) {
			progressBar.remove();
			rectangle.remove();
		}
		return;
	}

	// get the group
	var group = GetGroup(daIndex);

	// update the window status
	var remaining = groupsCount - (daIndex + 1);
	if (remaining == 0) {
		window.status = "All map locations loaded successfully.";
	} else {
		window.status = remaining + " map locations remaining to load...";
	}

	AddGroup(group);

	// increment the index
	daIndex++;

	if (IsUsingProgress()) {
		// update the rectangle color, fading from red to white based on complete amount
		var completed = remaining / groupsCount;
		var greenBlue = 255 - parseInt(completed * 255);
		var color = JSUtil.DecToHex(255, greenBlue, greenBlue);
		rectangle.color(color);

		// update the progressBar based on complete amount
		progressBar.value(100 - parseInt(completed * 100));
		progressBar.outerColor(color);
	}

	// add another application
	setTimeout(LoadAllDAs, 0);

}

function LoadDetailDA() {

	// if the tpk did not match any application then exit
	if (selectedApplication == null) return;

	// get the latLng coords and daNumber
	var lat = XmlUtil.getChildText(selectedApplication, "Latitude");
	var lng = XmlUtil.getChildText(selectedApplication, "Longitude");
	var daNumber = XmlUtil.getChildText(selectedApplication, "Number");

	// create the application marker
	CreateApplicationMarker(lat, lng, selectedApplication, false);

	// update the daNumber span on the details page
	DomUtil.getId("daNumber").innerHTML = daNumber;

	// load all of the other applications
	LoadAllDAs();
}

function IsUsingProgress() {
	return (rectangle != null) & (progressBar != null);
}

function AddGroup(group) {
	// take the lat lng coords of the group
	var latLng = GetGroupLatLng(daIndex);

	if (selectedApplication != null)  {
		var lat = XmlUtil.getChildText(selectedApplication, "Latitude");
		var lng = XmlUtil.getChildText(selectedApplication, "Longitude");
		var selectedLatLng = GMapUtil.getLatLng(lat, lng);
		if ((latLng.lat() == selectedLatLng.lat()) & (latLng.lng() == selectedLatLng.lng()))
			return;
	}

	// initialise variables, prepare infoTabs
	var infoTabs = new Array();
	var clickable = true;
	var icon = "Icons/daNormal.png";
	if (group.length > 1)
		icon = "Icons/daMultiple_Normal.png";

	for (var i=0; i<group.length; i++ ) {

		// get the application details and content
		var application = group[i];
		var address = XmlUtil.getChildText(application, "Location");
		var danumber = XmlUtil.getChildText(application, "Number");
		var description = XmlUtil.getChildText(application, "Description");
		var tpk = XmlUtil.getChildText(application, "ApplicationTPK");
		var startDate = XmlUtil.getChildText(application, "ExhibitionStarts");
		var html = NewDAXmlDom(address, danumber, description, tpk);

		// determine the icon
		var daStartDate = new Date(Date.parse(startDate));
		var today = new Date();
		var daysDiff = Math.round(Math.abs(today.getTime() - daStartDate.getTime()) / 1000 / 60 / 60 / 24);
		if (daysDiff <= 3) {
			icon = "Icons/daCurrent.png";
			if (group.length > 1)
				icon = "Icons/daMultiple_Current.png";
		}

		// if this is the selected application, disable click
		if (application == selectedApplication)
			clickable = false;

		infoTabs.push(new GInfoWindowTab(danumber.replace("D/", ""), html));
	}

	var marker = GMapUtil.createMarker(latLng, icon, "Icons/daShadow.png", "22,20", GMapUtil.BOTTOMLEFT, clickable, (clickable ? address : "You are currently viewing this applications details."));

	GEvent.addListener(marker, "click", function() {  GMapUtil.map.openInfoWindowTabsHtml(latLng, infoTabs);});

	GMapUtil.map.addOverlay(marker);
}

function CreateApplicationMarker(lat, lng, application, clickable) {
	// create the info bubble dom
	var address = XmlUtil.getChildText(application, "Location");
	var danumber = XmlUtil.getChildText(application, "Number");
	var description = XmlUtil.getChildText(application, "Description");
	var tpk = XmlUtil.getChildText(application, "ApplicationTPK");
	var startDate = XmlUtil.getChildText(application, "ExhibitionStarts");

	// determine the icon
	var daStartDate = new Date(Date.parse(XmlUtil.getChildText(application, "ExhibitionStarts")));
	var today = new Date();
	var daysDiff = Math.round(Math.abs(today.getTime() - daStartDate.getTime()) / 1000 / 60 / 60 / 24);
	var icon = "Icons/daNormal.png";
	if (daysDiff <= 3) icon = "Icons/daCurrent.png";
	if (!clickable) icon = "Icons/daSelected.png";

	// create the marker
	var dom = NewDAXmlDom(address, danumber, description, tpk);
	var marker = GMapUtil.createMarkerDom(GMapUtil.getLatLng(lat, lng), (clickable? dom : null), icon, "Icons/daShadow.png", "22,20", GMapUtil.BOTTOMLEFT, clickable, (clickable ? address : "You are currently viewing this applications details."));

	// add the marker to the map
	GMapUtil.map.addOverlay(marker);
}

function NewDAXmlDom(address, danumber, description, tpk) {

	// create the html
	var str = "";
	str += "<div class=\"infoWindow\">";
	str += "	<div class=\"infoWindowLabel\">Address</div>";
	str += "	<div class=\"infoWindowText\">#address</div>";
	str += "	<div class=\"infoWindowLabel\">DA Number</div>";
	str += "	<div class=\"infoWindowText\">#danumber</div>";
	str += "	<div class=\"infoWindowLabel\">Description</div>";
	str += "	<div class=\"infoWindowText\">#description</div>";
	str += "</div>";
	str += "<a class=\"infoWindowLink\" href=\"details.asp?tpk=" + tpk + "\">Click here to view full details...</a>";

	// replace the dynamic regions
	str = str.replace("#address", address);
	str = str.replace("#danumber", danumber);
	str = str.replace("#description", description);

	return str;
}