/**
 * @author: RB
 * @date: 09-01-2009
 * @version: 1.0
 * 
 * @fileoverview:
 * Provides all functionality for the loading of google maps
 * 
 */


window.gmapo = null;

// load the maps api
//google.load('maps', '2');

function initGoogleMapOverlay() {
	
	gmapo = new GoogleMapOverlay();
}


function GoogleMapOverlay() {
	
	this.Config = new GoogleMapOverlay.Config();
	
	this.Config.setDefaultCentre(this.Config.defaultCentreLat, this.Config.defaultCentreLng);
	
	this.addresses = [];
	this.points = [];
	
	this.geocoding = {};
	this.geocodeErrors = [];
}


GoogleMapOverlay.Config = function() {
	
	// settings
	this.baseCountry = 'gb';
	this.zoomLevel = 5;
	this.overlayOpacity = 0.5;
	
	this.defaultCentreLat = 53.98234051259595;
	this.defaultCentreLng = -1.5726006031036377;
	
	// text
	this.loadingMessage = 'Loading Map...';
	this.mapCaption = '';
	this.closeLinkText = 'Close Map';
	
	// element ids
	this.overlayId = 'gmapoverlay';
	this.closeLinkId = 'gmapoclose';
	this.loadingMessageId = 'gmapoloadingmsg';
	this.mapCapContainerId = 'gmapomapcap';
	this.mapContainerId = 'gmapomap';
	this.capContainerId = 'gmapocap';
}


GoogleMapOverlay.Config.prototype.setMapCentre = function(lat, lng) {
	
	this.mapCentre = new google.maps.LatLng(lat, lng);
}


GoogleMapOverlay.Config.prototype.setDefaultCentre = function(lat, lng) {
	
	this.defaultCentre = new google.maps.LatLng(lat, lng);
}


GoogleMapOverlay.prototype.addAddress = function(caption, address) {
	
	this.addresses.push({caption: caption, address: address});
}


GoogleMapOverlay.prototype.addLatLng = function(caption, lat, lng) {
	
	var point = new google.maps.LatLng(lat, lng);
	this.addPoint(caption, point);
}


GoogleMapOverlay.prototype.addPoint = function(caption, point) {
	
	this.points.push({caption: caption, point: point});
}


GoogleMapOverlay.prototype.geocode = function(address) {
	
	var addressCaption = address.caption;
	var addressAdd = address.address;
	
	this.geocoding[addressAdd] = 1;
	
	var thisref = this;
	
    var gcGeocoder = new google.maps.ClientGeocoder();
    if (this.Config.baseCountry != '') gcGeocoder.setBaseCountryCode(this.Config.baseCountry);
    gcGeocoder.getLatLng(address.address, geocodeCallback);
    
    function geocodeCallback(point) {
    	
    	if(!point) {
    		// record geocoding error
    		thisref.geocodeErrors.push({caption: addressCaption, address: addressAdd});
    		thisref.geocoding[addressAdd] = 0;
    	}
    	else {
			thisref.addPoint(addressCaption, point);
			thisref.geocoding[addressAdd] = 0;
    	}
    }
}


GoogleMapOverlay.prototype.load = function() {
    
    if (google.maps.BrowserIsCompatible()) {
        
        if (this.addresses.length > 0) {
        	
        	for (var i = 0; i < this.addresses.length; i++) {
        		
        		//alert(JSON.stringify(this.addresses));
        		this.geocode(this.addresses[i]);
        		this.addresses.shift();
        		i--;
        	}
        }
        
        //alert(JSON.stringify(this.geocoding));
        
	    var loadAttempts = 0;
	    
	    var thisref = this;
	    
	    // create the page overlay that the map will sit within
	    this.createOverlay();
	    
	    //this.overlay.style.display = 'block';
	    this.fadeIn();
	    
		// create the map container
		this.createMapContainer();
	    
	    createMap();
    }
    
    
    function createMap() {
    	
    	loadAttempts++;
    	
		var geocoding = false;
		
		for (var attrb in thisref.geocoding) {
		
			if (thisref.geocoding[attrb] == 1) {
				geocoding = true;
				break;
			}
		}
		
		var fadeInComplete = (Element.getOpacity(thisref.overlay) == thisref.Config.overlayOpacity);
    	
    	if (!geocoding && fadeInComplete) {
    		
    		//alert(JSON.stringify(thisref.geocoding));
    		//alert(JSON.stringify(thisref.geocodeErrors));
    		
    		thisref.createMap();
    		
    		// check to see if any points couldn't be resolved
    		if (thisref.geocodeErrors.length > 0) {
    			
    			var msg = 'Could not plot location for:\n\n';
    			
    			for (var i = 0; i < thisref.geocodeErrors.length; i++) {
    				
    				msg += thisref.geocodeErrors[i].caption + ', ';
    			}
    			
    			alert(msg.substring(0, (msg.length - 2)));
    		}
    	}
    	else {
    		
			if (loadAttempts < 5000) {
				setTimeout(createMap, 10);
			}
			else {
				alert('Could not load map!');
				thisref.closeMap();
			}
    	}
    }
}


GoogleMapOverlay.prototype.createOverlay = function() {
	
	var body = document.getElementsByTagName('body')[0];
	
	var olEl = document.createElement('div');
	olEl.id = this.Config.overlayId;
	olEl.style.display = 'none';
	
	if (GoogleMapOverlay.isIe) {
		
		olEl.style.height = String(screen.availHeight) + 'px';
	}
	
	body.appendChild(olEl);
	
	var closeEl = document.createElement('div');
	closeEl.id = this.Config.closeLinkId;
	closeEl.innerHTML = '<a href="#" onclick="gmapo.closeMap()">' + this.Config.closeLinkText + '</a>';
	
	olEl.appendChild(closeEl);
	
	this.overlay = olEl;
}


GoogleMapOverlay.prototype.createMapContainer = function() {
	
	var body = document.getElementsByTagName('body')[0];
	
	var mapCapEl = document.createElement('div');
	mapCapEl.id = this.Config.mapCapContainerId;
	mapCapEl.style.visibility = 'hidden';
	
	body.appendChild(mapCapEl);
	
	var mapEl = document.createElement('div');
	mapEl.id = this.Config.mapContainerId;
	
	mapCapEl.appendChild(mapEl);
	
	var loadEl = document.createElement('div');
	loadEl.id = this.Config.loadingMessageId;
	loadEl.innerHTML = this.Config.loadingMessage;
	
	mapEl.appendChild(loadEl);
	
	// position the loading message
	loadEl.style.left = String((mapEl.offsetWidth - loadEl.offsetWidth) / 2) + 'px';
	loadEl.style.top = String((mapEl.offsetHeight - loadEl.offsetHeight) / 2) + 'px';
	
	var capEl = document.createElement('div');
	capEl.id = this.Config.capContainerId;
	capEl.innerHTML = this.Config.mapCaption;
	
	mapCapEl.appendChild(capEl);
	
	mapCapEl.style.left = String((body.offsetWidth - mapCapEl.offsetWidth) / 2) + 'px';
	
    // make the map visible
    mapCapEl.style.visibility = 'visible';
	
	this.mapcap = mapCapEl;
	this.map = mapEl;
	this.cap = capEl;
	this.loadingmsg = loadEl;
	
	/*loadingUpdateCount = 0;
	
	var thisref = this;
	
	setTimeout(updateLoadingMsg, 500);
	
	
	function updateLoadingMsg() {
		
		loadingUpdateCount++;
		
		alert(typeof(loadEl));
		
		if (loadEl) {
			
			if (loadingUpdateCount < 4) {
				
				loadEl.innerHTML += '.';
			}
			else {
				loadEl.innerHTML = thisref.Config.loadingMessage;
				loadingUpdateCount = 0;
			}
			
			setTimeout(updateLoadingMsg, 500);
		}
	}*/
	
	
	// calculate the top positioning for the map
	//var body = document.getElementsByTagName('body')[0];
	//alert(body.offsetHeight);
	//alert(screen.availHeight);
}


GoogleMapOverlay.prototype.createMap = function() {
    	
    var map = new google.maps.Map2(this.map);
    map.setCenter(this.Config.mapCentre || ((this.points && (this.points.length > 0)) ? this.points[0].point : this.Config.defaultCentre), this.Config.zoomLevel);
    
    map.addControl(new google.maps.MapTypeControl());
    map.addControl(new google.maps.LargeMapControl());
    //map.removeMapType(G_HYBRID_MAP);
    //map.removeMapType(G_SATELLITE_MAP);
    
    // Create a base icon for all of our markers that specifies the
    // shadow, icon dimensions, etc.
    var baseIcon = new google.maps.Icon();
    baseIcon.shadow = 'http://www.google.com/mapfiles/shadow50.png';
    baseIcon.iconSize = new google.maps.Size(20, 34);
    baseIcon.shadowSize = new google.maps.Size(37, 34);
    baseIcon.iconAnchor = new google.maps.Point(9, 34);
    baseIcon.infoWindowAnchor = new google.maps.Point(9, 2);
    baseIcon.infoShadowAnchor = new google.maps.Point(18, 25);        
    
    if (this.points) {
	    for (var i = 0; i < this.points.length; i++) {
	        
	        var thetext = this.points[i].caption;
	        var themarker = createMapMarker(this.points[i].point, thetext);
	        map.addOverlay(themarker);	        	
	    }
    }
    
	// remove the loading message
	this.loadingmsg.style.display = 'none';
	
	
	// Creates a marker whose info window displays the letter corresponding
	// to the given index.
    function createMapMarker(point, text) {
    	
		var letteredIcon = new google.maps.Icon(baseIcon);
		
		letteredIcon.image = 'http://www.google.com/mapfiles/marker.png';
		
		// Set up our marker options object
		markerOptions = {icon: letteredIcon};
		
		var marker = new google.maps.Marker(point, markerOptions);
		
		google.maps.Event.addListener(marker, 'click', function() {marker.openInfoWindowHtml(text);});
		
		return marker;
    }
}


GoogleMapOverlay.prototype.fadeIn = function() {
	
	Effect.Appear(this.Config.overlayId, {to: this.Config.overlayOpacity});
}


GoogleMapOverlay.prototype.fadeOut = function() {
	
	Effect.Fade(this.Config.overlayId);
}


GoogleMapOverlay.prototype.closeMap = function() {
	
	var body = document.getElementsByTagName('body')[0];
	
	google.maps.Unload();
	body.removeChild(this.mapcap);
	body.removeChild(this.overlay);
	gmapo = null;
	//this.fadeOut();
	
	/*attemptCount = 0;
	
	finishClose();
	
	function finishClose() {
		
		attemptCount++;
		
		if (Element.getOpacity(this.overlay) == 0) {
			
			body.removeChild(this.overlay);
			gmapo = null;
		}
		else {
			if (attemptCount < 500) {
				setTimeout(finishClose, 10);
			}
		}
	}*/
}



// browser identification --------------------------------------------------------------------------------------------------------

GoogleMapOverlay.agt = navigator.userAgent.toLowerCase();
GoogleMapOverlay.isIe	   = ((GoogleMapOverlay.agt.indexOf("msie") != -1) && (GoogleMapOverlay.agt.indexOf("opera") == -1));
GoogleMapOverlay.isOpera  = (GoogleMapOverlay.agt.indexOf("opera") != -1);
GoogleMapOverlay.isMac	   = (GoogleMapOverlay.agt.indexOf("mac") != -1);
GoogleMapOverlay.isMacIe = (GoogleMapOverlay.isIe && GoogleMapOverlay.isMac);
GoogleMapOverlay.isWinIe = (GoogleMapOverlay.isIe && !GoogleMapOverlay.isMac);
GoogleMapOverlay.isGecko  = (navigator.product == "Gecko");