﻿// Custom 'Class' to wrap GoogleMap functionality and to add specific functionality
// required by Grosvenor sites.
function GrosvenorMap(htmlElement)
{
	//#region 'private' variables
	
	var _googleMap = null;
	var _mapOverlayManager = null;
	var _mapPlacemarkManager = null;
	var _geocoder = null;
	var _defaultCentre = null;
	var _defaultZoom = null;
	
	//#endregion 'private' variables
			
	//#region public property access methods
	
	// Returns a reference to the GMap2 instance
	this.getGoogleMap =
		function()
		{
			return _googleMap;
		};
		
	// Returns a reference to the Grosvenor Map Overlay Manager
	this.getMapOverlayManager = 
		function()
		{
			return _mapOverlayManager;
		};
		
	// Returns a reference to the Grosvenor Map Placemark Manager
	this.getMapPlacemarkManager =
		function()
		{
			return _mapPlacemarkManager;
		};
		
	//#endregion public property access methods

	//#region public methods
	
	// Sets the centre by setting the Latitude, Longitude and Zoom level
	this.setLocation = 
		function(latitude, longitude, zoom, isDefault)
		{
			var centreGLatLng = new GLatLng(latitude, longitude);
			_googleMap.setCenter(centreGLatLng, zoom);
			
			if (isDefault != null)
			{
				if (isDefault	== true)
				{
					_defaultCentre = centreGLatLng;
					_defaultZoom = zoom;
				}
			}
		};
		
	// Pans to the GLatLng position
	this.panTo = 
		function(center)
		{
			_googleMap.panTo(center);
		
		};
	
	// Immediately adds a MapControl, derived from GControl, to the Google Map
	this.addControl =
		function(googleMapControl)
		{
			_googleMap.addControl(googleMapControl);
		};
		
	// Adds a Google Marker to the Map
	this.addMarker =
		function(googleMarker)
		{
			_googleMap.addOverlay(googleMarker);
		};

	// Returns the centre (Lat, Long) of the Map		
	this.getCenter =
		function()
		{
			return _googleMap.getCenter();
		};
		
	this.getDefaultCenter =
		function()
		{
			return _defaultCentre;
		};
		
	this.getDefaultZoom = 
		function()
		{
			return _defaultZoom;
		};
		
	// Sets the Map to the defaults of its creations, namely Centre and Zoom
	this.setToDefaults =
		function()
		{
			if (_defaultCentre != null)
			{
				_googleMap.setCenter(_defaultCentre);
			}
			
			if (_defaultZoom != null)
			{
				_googleMap.setZoom(_defaultZoom);
			}
		}
				
	// Attempts to locate the exact position from an arbitary address
	// The position is returned to the callback function
	this.getGeoCodeAddress =
		function(address, callback)
		{
			InitialiseGeoCoder();
			
			_geocoder.getLatLng(address, callback);
		};

	// Attempts to locate the positions from an arbitary address.
	// Usefully when there are many places with a similar address.
	// The positions and status are returned to the callback function
	this.getGeoCodeAddresses =
		function(address, callback)
		{
			InitialiseGeoCoder();
			
			_geocoder.getLocations(address, callback);
		};
	
	//#endregion public methods
	
	//#region private methods
	
	///<summary>
	/// Creates a new GMarker and centres it.
	///	Also adds it to the mapPlacemark as a reference
	///</summary>
	function CreatePlacemark(mapPlacemark)
	{
		marker = new GMarker(_grosvenorMap.getCenter(), {draggable: true});

		GEvent.addListener(marker, "drag", function()
			{
				var position = marker.getPoint();
			});

		_grosvenorMap.addMarker(marker);
		
		mapPlacemark.GooglePlacemarkReference = marker;
	}
	
	//#endregion private methods
	
	//#region private 'event' handlers
	
	// Creates a GClientGeocoder instance only if it has not been created before.
	function InitialiseGeoCoder()
	{
		if (_geocoder == null)
		{
			_geocoder = new GClientGeocoder();
			
			//TODO: Initialise this as default, but allow property changing from .ASPX control
			// Narrow the search to Great Britain.
			_geocoder.setBaseCountryCode('GB');
		}		
	}
	
	function MapOverlayManager_OnAdd(mapOverlay)
	{
		// Only add the MapOverlay if it is visible
		AddOverlay(mapOverlay);
	}
	
	function MapOverlayManager_OnItemVisibleChange(mapOverlay)
	{
		ToggleOverlayVisiblity(mapOverlay, mapOverlay.Visible);
	}
	
	function MapPlacemarkManager_onAdd(mapPlacemark)
	{
		CreatePlacemark(mapPlacemark);
	}
	
	//#endregion private 'event' handlers
	
	//#region private methods

	// Equivalent to a Constructor	
	function Initialise()
	{
		_googleMap = new GMap2(document.getElementById(htmlElement));
		_mapOverlayManager = new MapOverlayManager();
		_mapOverlayManager.onAdd = MapOverlayManager_OnAdd;
		_mapOverlayManager.onItemVisibleChange = MapOverlayManager_OnItemVisibleChange;

		// Create new instance of MapPlacemarkManager	
		_mapPlacemarkManager = new MapPlacemarkManager();
		// Bind MapPlacemarkManager_onAdd function to the onAdd event in MapPlacemarkManager
		_mapPlacemarkManager.onAdd = MapPlacemarkManager_onAdd;
		
		this.MapOverlayManager = _mapOverlayManager;
	}
	
	
	function AddOverlay(mapOverlay)
	// Adds a Google Overlay to Google Map
	{
		// Only add the MapOverlay if it  already has a Google Map Overlay
		if (mapOverlay.GoogleOverlayReference != null)
		{
			_googleMap.addOverlay(mapOverlay.GoogleOverlayReference);
			mapOverlay.IsAddedToGoogleMap = true;
		}
	}
	
	function ToggleOverlayVisiblity(mapOverlay, visible)
	// Add/Remove a Google Overlay from the Google Map.
	// However, the Google Overlay still existings in the Grosvenor MapOverlay Manager
	{
		if (mapOverlay.GoogleOverlayReference != null)
		{
			if (visible)
			{
				// Only add overlay to Google Map if it is not already added
				if (!(mapOverlay.IsAddedToGoogleMap))
				{
					_googleMap.addOverlay(mapOverlay.GoogleOverlayReference);
					mapOverlay.IsAddedToGoogleMap = true;
				}
			}
			else
			{
				// Only remove overlay from Google Map if it is already added
				if (mapOverlay.IsAddedToGoogleMap)
				{
					_googleMap.removeOverlay(mapOverlay.GoogleOverlayReference);
					mapOverlay.IsAddedToGoogleMap = false;
				}
			}
		}	
	}
	
	//#endregion private methods
	
	// Call 'constructor'
	Initialise();
}
// General purpose utility methods
function GrosvenorUtility()
{
	// Allows capturing of DOM events to not affect
	// other methods that are bound to the same events.
	// Daisy-chained.
	this.addEvent = 
		function (obj, type, fn)
		{
			if (obj.attachEvent)
			{
				obj['e' + type + fn] = fn;
				obj[type + fn] =
					function()
					{
						obj['e' + type + fn](window.event);
					};
				obj.attachEvent('on' + type, obj[type + fn]);
			}
			else
			{
				obj.addEventListener(type, fn, false);
			}
		}
}
