/*==================================================================
	gmap.js
	
	Author: James Edgeworth (2009) (unless otherwise credited)
	
	Handles Google Maps API, and related functionality.
	
	Credit goes to Tom Anthony (http://www.tomanthony.co.uk/blog/geocoding-uk-postcodes-with-google-map-api/)
	who found a (still not perfect) solution to Google maps' locations for UK postcodes.


==================================================================*/



var map;
var localSearch = new GlocalSearch();

var iconPostcode = new GIcon();
iconPostcode.image = "http://www.google.com/mapfiles/marker.png";
iconPostcode.shadow = "http://www.google.com/mapfiles/shadow50.png";
iconPostcode.iconSize = new GSize(20, 34);
iconPostcode.iconSize = new GSize(20, 34);
iconPostcode.shadowSize = new GSize(37, 34);
iconPostcode.iconAnchor = new GPoint(10, 34);


var iconUser = new GIcon();
iconUser.image = "http://www.google.com/mapfiles/marker_yellow.png";
iconUser.shadow = "http://www.google.com/mapfiles/shadow50.png";
iconUser.iconSize = new GSize(20, 34);
iconUser.shadowSize = new GSize(37, 34);
iconUser.iconAnchor = new GPoint(10, 34);

var iconPlacement = new GIcon();
iconPlacement.image = "http://www.google.com/mapfiles/marker_green.png";
iconPlacement.shadow = "http://www.google.com/mapfiles/shadow50.png";
iconPlacement.iconSize = new GSize(20, 34);
iconPlacement.shadowSize = new GSize(37, 34);
iconPlacement.iconAnchor = new GPoint(10, 34);


var iconAccurate = new GIcon();
iconAccurate.image = "http://www.google.com/mapfiles/marker_brown.png";
iconAccurate.shadow = "http://www.google.com/mapfiles/shadow50.png";
iconAccurate.iconSize = new GSize(20, 34);
iconAccurate.shadowSize = new GSize(37, 34);
iconAccurate.iconAnchor = new GPoint(10, 34);

var sourceData;
var currentText = 'blah';


// Event ID of current event, if specified when loading map
var g_eventId;


var userMarker;
var userPoint = new GPoint();

var firstClick = true;

var placementMode = false;


// Map position and zoom
var centreLat;
var centreLng;
var centreZoom;
var mapAlreadyLoaded = false;


// Target element id's for setting lat/lng FROM a map marker
var latElementId;
var lngElementId;


/*
	setPlacementMode()
	
	Sets map into "placement mode", in which an extra map marker is
	added, which can be dragged around the map. When finished dragging,
	two document elements are set to the marker' lat/lng.
	
*/
function setPlacementMode(enabled, latElementIdArg, lngElementIdArg)
{

	placementMode = enabled;
	
	latElementId = latElementIdArg;
	lngElementId = lngElementIdArg;

}



/*
	usePointFromPostcode(STR postcode, OBJ callbackFunction)
	
	Using a postcode, finds the lat/long and then runs the callbackfunction
	with a GLatLng() object.
	
	Credit goes to Tom Anthony (http://www.tomanthony.co.uk/blog/geocoding-uk-postcodes-with-google-map-api/),
	who wrote the original function.


function usePointFromPostcode(postcode, callbackFunction)
{	
	
	localSearch.setSearchCompleteCallback(null, 
		function()
		{	
		
			if (localSearch.results[0])
			{	
			
				var resultLat = localSearch.results[0].lat;
				var resultLng = localSearch.results[0].lng;
				
				var point = new GLatLng(resultLat, resultLng);
				
				if (callbackFunction != null)
				{
					callbackFunction(point);
				}
				
			}
			
		}
	);	
		
	localSearch.execute(postcode + ", UK");

}
*/




/*
	setLatAndLong(STR postcode, STR latId, STR longId)
	
	Uses a Google Ajax query to find the latitude and longitude of a postcode.
	
	This function is typically run when the user enters a postcode, and silently
	gets the corresponding lat/long.
	
*/
function setLatAndLong(postcode, latId, longId)
{


	localSearch.setSearchCompleteCallback(null, 
		function()
		{
		
			if ( localSearch.results[0] )
			{
			
				document.getElementById(latId).value = localSearch.results[0].lat;
				document.getElementById(longId).value = localSearch.results[0].lng;
				
			}
			
		}
	);
	
	localSearch.execute(postcode + ", UK");
	
}




/*
	removeWhitespaceChildNodes()
	
	Loops over all child nodes of an XML node, and removes any which
	are whitespace nodes.

*/
function removeWhitespaceChildNodes(node)
{
	alert('here ' + node.length);
	
	var i = 0;
	
	for ( i = 0; i < node.childNodes.length; i++ )
	{
	
		alert(node.childNodes[i].nodeValue);
		
		if ( node.childNodes[i].nodeType == 3 )
		{
			node.removeChild(node.childNodes[i]);
		}
		
	}
	
}




/*
	getNonWhiteSpaceChildNodeValue()
	
	Most browsers treat whitespace characters in XML as a seperate node.
	This function checks the node type of the first child, and if it is 
	a whitespace node, returns the second child (which would be the text).
	
*/
function getNonWhiteSpaceChildNodeValue(node)
{

	// nodeType 3 means the node is a whitespace node
	if (node.childNodes[0].nodeType != 3)
	{
		return node.childNodes[0].nodeValue;
	}
	else
	{
		return node.childNodes[1].nodeValue;
	}
	
}



var allMarkers = [];


/*
	addMarkersFromXML()
	
	The callback function of sendAndLoadXML(), initiated by
	loadMarkers(). This will initialise the google map, fill in
	a status element above the map, then loop over all markers,
	and add them to the map.
	
	If placement mode is set, then it will also add another marker
	which can be dragged around.
	
*/
function addMarkersFromXML()
{

	var center;
	
	
	var responseNode 	= sourceXML		.getElementsByTagName('response')[0];
	var statusNode		= responseNode	.getElementsByTagName('status')[0];
	var centreNode		= responseNode	.getElementsByTagName('center')[0];
	var markersRoot 	= responseNode	.getElementsByTagName('markers')[0];
	var marker 			= markersRoot	.getElementsByTagName('marker');
	
	var results			= statusNode	.getAttribute('count');
	var status 			= getNonWhiteSpaceChildNodeValue(statusNode);
	
	var centreLat		= centreNode.getElementsByTagName('latitude')[0].firstChild.nodeValue;
	var centreLng		= centreNode.getElementsByTagName('longitude')[0].firstChild.nodeValue;
	var centreZoom		= centreNode.getAttribute('zoom');
	
	
	// Centre in on centre coords, if first time loading map
	if( !mapAlreadyLoaded )
	{
		map.setCenter(new GLatLng(centreLat, centreLng), parseInt(centreZoom), G_HYBRID_MAP);

		center = new GLatLng(centreLat, centreLng);
		
		mapAlreadyLoaded = true;
		
	}
	
	
	document.getElementById('mapstatus').innerHTML = status;
	
	// Loop over markers and add to map
	var count = results;
	
	var html = '';
	var lat = '';
	var lng = '';
	var type = '';
	var markerId = '';
	var votes = '';
	
	for ( i = 0; i < count; i++ )
	{
	
		html 	= marker[i].getElementsByTagName('html')[0].firstChild.nodeValue;
		lat 	= marker[i].getElementsByTagName('latitude')[0].firstChild.nodeValue;
		lng 	= marker[i].getElementsByTagName('longitude')[0].firstChild.nodeValue;
		type 	= marker[i].getAttribute('type');
		markerId = marker[i].getAttribute('id');
		votes	= marker[i].getAttribute('votes');
		
		if ( type == 0 && placementMode )
		{
			html += '<br /><button onClick="voteMarker(' + markerId + ');">Marker is Accurate</button> (Votes: ' + votes + ')';
		}
		
		
		if ( lat != '0.000000' && lng != '0.000000' )
		{
		
			placeMarkerAtPoint(new GLatLng(lat, lng), html, type);
			
		}
		
	}
	 
	// If placement mode, create placement marker
	if ( placementMode )
	{
	
		userMarker = new GMarker(center, {draggable: true, icon:iconPlacement});
		
		// If user drags the icon, close any infoWindow()'s
		GEvent.addListener(userMarker, "dragstart", function(){
			map.closeInfoWindow();
		});
		
		// Once user finishes dragging, get the marker's lat/lng
		GEvent.addListener(userMarker, "dragend", function() {
		
			var latlngtmp = new GLatLng();
			latlngtmp = userMarker.getLatLng();
			
			document.getElementById(latElementId).value = latlngtmp.lat();
			document.getElementById(lngElementId).value = latlngtmp.lng();

		});
		
		// If user clicks anywhere on the map, move the placement marker there
		GEvent.addListener(map, "click", function(overlay, latlng) {
		
			placeUserMarker(latlng.lat(), latlng.lng());
		
		});
		
		map.addOverlay(userMarker);
		
	}
	
}


function voteMarker(markerId)
{
	setTopRightPopupText('');
	
	sendAndCall(voteMarkerTrigger, 'topRightId', 'marker.php', 'acc=' + markerId + '&id=' + g_eventId);
	
}



function setMarkerAccurate(markerId)
{

	setTopRightPopupText('');

	var post = 'marker_id=' + markerId;
	post += '&id=' + g_eventId;
	post += '&setAcc=1';
	
	sendAndCall(voteMarkerTrigger, 'topRightId', 'marker.php', post);
	
}


function voteMarkerTrigger()
{
	setTopRightPopupHide(6000);
}


function addUserMarker(eventId)
{

	var post = 'marker_lat=' + document.getElementById('marker_lat').value;
	post += '&marker_lng=' + document.getElementById('marker_lng').value;
	post += '&anon_name=' + document.getElementById('anon_name').value;
	post += '&id=' + eventId;
	post += '&marker_submit=Save Marker';
	
	setTopRightPopupText('');

	sendAndCall(addUserMarkerTrigger, 'topRightId', 'marker.php', post);
	
	
}




function addUserMarkerTrigger()
{

	setTopRightPopupHide(6000);
	
}


/*
	removeMarkers()
	
	Removes all markers from map, and resets markers array.
	
*/
function removeMarkers()
{

	for(var i = 0; i < allMarkers.length; i++)
	{
		map.removeOverlay(allMarkers[i]);
		
	}
	
	allMarkers = [];
	
}





/*
	placeMarker(STR lat, STR lng)
	
	Places a marker with a given latitude and longitude.
*/
function placeMarker(lat, lng)
{

	var point = new GLatLng(lat, lng);
	var marker = new GMarker(point, iconPostcode);
	
	map.addOverlay(marker);
	map.setCenter(point, 17);
	
}


/*
	placeUserMarker()
	
	Moves placement marker to a given lat/lng.
	
*/
function placeUserMarker(lat, lng)
{

	userMarker.setLatLng(lat, lng);
	
}


/*
	placeMarkerAtPoint(OBJ point, STR text, INT iconType)
	
	Places a marker using a GLatLng() object, and also
	sets the marker's text.
	
	IconType:
	0 = user submitted,
	1 = postcode,
	2 = Accurate
	
*/
function placeMarkerAtPoint(point, text, iconType)
{

	var newIcon = new GIcon();
	
	newIcon = iconPostcode;

	if ( iconType == 0 )
	{
		newIcon = iconUser;
	}
	else if ( iconType == 2 )
	{
		newIcon = iconAccurate;
	}

	var marker = new GMarker(point, newIcon);
	
	GEvent.addListener(marker, 'click', 
		function()
		{
			map.openInfoWindowHtml(point, text);
		}
	);
	
	// Add to allMarkers
	allMarkers.push(marker);
	
	map.addOverlay(allMarkers[allMarkers.length - 1]);
	
}



/*
	setCenterToPoint(point)
	
	Center's the map to a given GLatLng().
*/
function setCenterToPoint(point)
{
	map.setCenter(point, 17);
}



/*
	setCenterToLatLng(STR lat, STR lng)
	
	Center's the map to a given latitude/longitude.
*/
function setCenterToLatLng(lat, lng, zoom)
{
	map.setCenter(new GLatLng(lat, lng), zoom);
}



/*
	loadMarkers()
	
	The entry point for most mapping scenarios.
	
	Optionally allows different types of markers to be specified via checkboxes.
	Note that this doesn't handle specifying an event via POST - that is done via GET.
	
	Uses sendAndCallXML(), which in turn calls addMarkersFromXML().
	
*/
function loadMarkers(eventId, prepend)
{

	// Check if we already have markers, and remove them if so
	if ( allMarkers )
	{
		removeMarkers();
	}
	
	
	if( !mapAlreadyLoaded )
	{
	
		mapLoad();
	
	}
	
	if( !prepend )
	{
		var prepend = '';
	}
	
	var script = prepend + 'ajax/getmapnodesXML.php';
	
	// If set, set globally, in case of other event-specific functions
	if ( eventId && eventId > 0 )
	{
	
		g_eventId = eventId;
		script += '?eventId=' + eventId;
		
	}
	
	
	var loadPostcodeMarkers = 1;
	var loadUserMarkers 	= 1;
	var loadAccurateMarkers = 1;

	// Check which markers to load
	if ( document.getElementById('show_postcode_markers') )
	{
	
		loadPostcodeMarkers = ( document.getElementById('show_postcode_markers').checked ) 	? 1 : 0 ;
		loadUserMarkers 	= ( document.getElementById('show_user_markers').checked ) 		? 1 : 0 ;
		loadAccurateMarkers = ( document.getElementById('show_accurate_markers').checked ) 	? 1 : 0 ;
		
	}
	

	sendAndCallXML(addMarkersFromXML, 'mapstatus', script, 'postcode=' + loadPostcodeMarkers + '&user=' + loadUserMarkers + '&accurate=' + loadAccurateMarkers);
	
}





/*
	mapLoad()
	
	Loads the Google map into a DOM object with an id of "map".
	
	Should be called anytime the Google map is required(and only called once).

*/
function mapLoad()
{

	if ( GBrowserIsCompatible() && map == null )
	{
	
		map = new GMap2(document.getElementById("map"));
		map.addControl(new GLargeMapControl());
		map.addControl(new GMapTypeControl());
		map.setCenter(new GLatLng(51.665741, -1.862183), 8, G_HYBRID_MAP);
		map.enableScrollWheelZoom();
		
	}
	
}


/*
function addLoadEvent(func)
{

	var oldonload = window.onload;
	
	if ( typeof window.onload != 'function' )
	{
		window.onload = func;
	}
	else
	{
	
		window.onload = function()
		{
		
			oldonload();
			func();
			
		}
		
	}
	
}



function addUnLoadEvent(func)
{

	var oldonunload = window.onunload;
	
	if ( typeof window.onunload != 'function' )
	{
		window.onunload = func;
	}
	else
	{
	
		window.onunload = function()
		{
		
			oldonunload();
			func();
			
		}
		
	}
	
}

addLoadEvent(mapLoad);
addUnLoadEvent(GUnload);
*/