addLoadEvent(function () {
	InitialiseMapping();
});

function InitialiseMapping() {

	// If Google Maps is incompatiable, stop executing function
	if (!GBrowserIsCompatible()) return;

	// Instantiate new map in #offices_map1 div
	var map = new GMap2(document.getElementById('offices_map'));

	// Define map controls and set centre point and zoom level
	map.addControl(new GLargeMapControl());
	map.addControl(new GMapTypeControl());

	// Set center over Europe
	map.setCenter(new GLatLng(47.81315451752768, 9.4921875), 3);

	// Determine z-index of markers
	function importanceOrder(marker, b) {
		return GOverlay.getZIndex(marker.getPoint().lat()) + (marker.importance * 1000000);
	}

	// Panavision Main Offices Icon
	var mainIcon = new GIcon();
	mainIcon.image  = '../images/map/green-pointer.png';
	mainIcon.shadow = '../images/map/pointer-shadow.png';
	mainIcon.iconSize = new GSize(19, 32);
	mainIcon.shadowSize = new GSize(37, 32);
	mainIcon.iconAnchor = new GPoint(9, 32);
	mainIcon.infoWindowAnchor = new GPoint(15, 0);
	mainMarkerOptions = {
		icon:mainIcon,
		zIndexProcess:importanceOrder
	}

	// Panavision Agencies Icon. Note: by passing the mainIcon as the first argument to the GIcon
	// constructor, agenciesIcon copies its properties. The second argument defines its image property
	var officesIcon = new GIcon(mainIcon, '../images/map/red-pointer.png');
	officeMarkerOptions = {
		icon:officesIcon,
		zIndexProcess:importanceOrder
	}

	var agenciesIcon = new GIcon(mainIcon, '../images/map/yellow-pointer.png');
	agencyMarkerOptions = {
		icon:agenciesIcon,
		zIndexProcess:importanceOrder
	}

	// Continent constructor
	function Continent(latitude, longitude, zoom) {
		this.latitude  = latitude;
		this.longitude = longitude;
		this.markers   = [];
		this.zoom      = zoom;
		this.showMarkers = function () {
			map.clearOverlays();
			for (var i = 0; i < this.markers.length; i++) {
				map.addOverlay(this.markers[i]);
			}
			map.setZoom(this.zoom);
			map.panTo(new GLatLng(this.latitude, this.longitude));
		}
	}

	// Define continents, passing longitude, latitude and zoom level as arguments
	var Africa			= new Continent(-13.2399454992863, 26.015625, 3),
		Asia					= new Continent(25.958044673317843, 106.5234375, 3),
		Australasia		= new Continent(-31.353636941500987, 147.216796875, 3),
		Europe				= new Continent(47.81315451752768, 9.4921875, 3),
		NorthAmerica	= new Continent(37.85750715625203, -94.5703125, 3);
		SouthAmerica	= new Continent(-19.408054128088575, -56.9296875, 3);

	// Function used to process JSON data
	function ProcessJson(jsonStr) {
		var jsonData = eval('(' + jsonStr + ')');

		// Plot the markers
		for (var j = 0; j < jsonData.markers.length; j++) {
			var markerJson		= jsonData.markers[j];
			var point					= new GLatLng(markerJson.latitude, markerJson.longitude);
			var options;
			var markerObj;
			var continentObj	= eval(markerJson.continent.replace(/ /g, ''));

			switch (markerJson.facility) {
				case 'Main'		: options = mainMarkerOptions;		break;
				case 'Office'	: options = officeMarkerOptions;	break;
				case 'Agency'	: options = agencyMarkerOptions;	break;
			}

			markerObj = new GMarker(point, options);
			markerObj.importance = (markerJson.facility == 'Main') ? 2 : 1;

			// If the marker's JSON data contains a title, populate an info window and bind it to the marker click event
			if (markerJson.title) {
				var infoWindowHtml = '<div id="offices_activeInfoWindow" style="';
				infoWindowHtml += (markerJson.infoHeight) ? 'height:' + markerJson.infoHeight + 'px;' : '';
				infoWindowHtml += (markerJson.infoWidth)  ? 'width:'  + markerJson.infoWidth  + 'px'  : '';
				infoWindowHtml += '"><strong>' + markerJson.title + '</strong><br />';
				infoWindowHtml += markerJson.address1 + '<br />';
				infoWindowHtml += markerJson.address2 + '<br />';
				infoWindowHtml += (markerJson.address3) ? markerJson.address3 + '<br />' : '';
				infoWindowHtml += (markerJson.address4) ? markerJson.address4 + '<br />' : '';
				infoWindowHtml += (markerJson.address5) ? markerJson.address5 + '<br />' : '';
				infoWindowHtml += (markerJson.address6) ? markerJson.address6 + '<br />' : '';
				infoWindowHtml += '<div id="offices_infoWindowContactDetails">';
				infoWindowHtml += (markerJson.tel)  ? '<strong>Tel:</strong> ' + markerJson.tel + '<br />' : '';
				infoWindowHtml += (markerJson.fax)  ? '<strong>Fax:</strong> ' + markerJson.fax + '<br />' : '';
				infoWindowHtml += (markerJson.link) ? '<a href="' + markerJson.link + '">' + markerJson.link + '</a><br />' : '';
				infoWindowHtml += 
					'<a href="#" id="offices_detailLink"></a>' +
					'</div></div>';

				// When the marker is clicked...
				function openInfoWindow(infoWindowHtml, markerJson, markerObj, continentObj) {
					// Open infoWindow
					markerObj.openInfoWindowHtml(infoWindowHtml);

					// Determine the function of the detail link based on zoom level and modify it accordingly
					function delayHandleViewLinkState() {
						potentialViewLink = document.getElementById('offices_detailLink');
						if (!potentialViewLink) {
							setTimeout(delayHandleViewLinkState, 100);
						}
						else {
							viewLink = potentialViewLink;
							HandleViewLinkState(markerJson, markerObj, 9, 16, continentObj);
						}
					}
					setTimeout(delayHandleViewLinkState, 100);

					// Everytime the user zooms in or out, determine the function of the detail link based on zoom level
					GEvent.addListener(map, 'zoomend', function() {
						HandleViewLinkState(markerJson, markerObj, 9, 16, continentObj, true);
					});
				}

				(function () {
					var _infoWindowHtml = infoWindowHtml;
					var _markerJson			= markerJson;
					var _markerObj			= markerObj;
					var _continentObj		=	continentObj;
					var europeLink			= document.getElementById('offices_europeLink');

					GEvent.addListener(markerObj, 'click', function () {
						openInfoWindow(_infoWindowHtml, _markerJson, _markerObj, _continentObj);
					});

					// When the 'Details' link is clicked, simulate a marker click
					if (_markerJson.continent == 'Europe' && (_markerJson.facility == 'Office' || _markerJson.facility == 'Main')) {
						var id = markerJson.title.replace(/ /g, '');

						document.getElementById('offices_link' + id).onclick = function () {
							if (europeLink.className != 'current') {
								Europe.showMarkers();

								var continentLinks = document.getElementById('offices_continentLinkList').getElementsByTagName('a');

								for (var i = 0; i < continentLinks.length; i++) {
									continentLinks[i].className = '';									
								}

								document.getElementById('offices_europeLink').className = 'current';
							}

							openInfoWindow(_infoWindowHtml, _markerJson, _markerObj, _continentObj);

							// Zoom and pan to view closer detail of marker
							map.setZoom(16);
							map.panTo(new GLatLng(_markerJson.latitude, _markerJson.longitude));

							return false;
						};
					}
				})();
			}

			// Push marker objects into continents markers array
			continentObj.markers[continentObj.markers.length] = markerObj;
		}

		// Display European markers
		Europe.showMarkers();
	}

	// Fetch JSON data and process
	GDownloadUrl("../js/offices.json.js", ProcessJson);
				
	// When the active infoWindow is closed, clear any associated zoom listeners
	GEvent.addListener(map, 'infowindowclose', function() {
		GEvent.clearListeners(map, 'zoomend');
	});

	// Determine the View Link state dependent on zoom level
	function HandleViewLinkState(markerJson, markerObj, zoomBound, detailZoomLevel, continentObj) {

		if (map.getZoom() > zoomBound) {

			// If the link is already in the correct state, stop executing function
			if (viewLink.innerHTML == markerJson.continent + ' View') return;

			// Change the link to Continent View. For example 'Europe View'
			viewLink.innerHTML = markerJson.continent + ' View';

			viewLink.onclick = function () {

				// Zoom and pan to view entire continent
				map.setZoom(continentObj.zoom);
				map.panTo(new GLatLng(continentObj.latitude, continentObj.longitude));

				// Close open infoWindow
				map.closeInfoWindow();
				
				return false;
			}
		}
		else {
			// If the link is already in the correct state, stop executing function
			if (viewLink.innerHTML == 'Detailed View') return;

			viewLink.innerHTML = 'Detailed View';

			viewLink.onclick = function () {

				// Zoom and pan to view closer detail of marker
				map.setZoom(detailZoomLevel);
				map.panTo(new GLatLng(markerJson.latitude, markerJson.longitude));

				// Execute parent function again, thus changing the link to Continent View
				HandleViewLinkState(markerJson, markerObj, zoomBound, detailZoomLevel, continentObj);
				
				return false;
			}
		}
	}

	// Show Continent Markers when Continent link is clicked, 
	var continentLinks = document.getElementById('offices_continentLinkList').getElementsByTagName('a'),
		continentLink = document.getElementById('offices_europeLink');

	for (var k = 0; k < continentLinks.length; k++) {
		continentLinks[k].onclick = function () {

			// Remove 'current' class name from previously current continent anchor
			continentLink.className = '';

			// Add 'current' class name to new current continent link and store a node reference to it
			this.className = 'current';
			continentLink = this;

			// Execute the relevant continent's showMarkers function. Fish continent name from anchor's rel attribute
			eval(this.getAttribute('rel')).showMarkers();

			// Return false, supressing default link behaviour
			return false;
		}
	}
}

// Europe/Details view link
var viewLink = false;