  /**
   * Class object for the Google Map API
   * 
   * This object will correlate to the clickable regions on the map interactive.
   * When a region is clicked the center coordinates will be used to pan to the center
   * of the region, and then the map is zoomed to the level specified for the region clicked.
   * 
   * @author	John P. Giatropoulos	<jgiatropoulos@thinkinc.com>
   */
   
   var defaultMessage=null; 
   var errorMessage = null;
   var startCenterLat = '';
   var startCenterLon = '';
   var startZoom = '';
   var regions = {
   
   "asia": {
		centerLat: "42.81152174509788",
		centerLon: "89.47265625",
		zoom: 3
	},
		
   	// africa
   
   	"africa": {
		centerLat: "12.726084296948183",
		centerLon: "17.2265625",
		zoom: 3
	},
		
	// south america
	
	"samerica": {
		centerLat: "-21.943045533438166",
		centerLon: "-60.46875",
		zoom: 3
	},
	
	// europe
	
	"europe": {
		centerLat: "49.61070993807422",
		centerLon: "16.435546875",
		zoom: 4
	},
	
	"namerica": {
		centerLat: "41.11246878918085",
		centerLon: "-97.20703125",
		zoom: 3
	},
	
	"australia": {
		centerLat: "-24.206889622398023",
		centerLon: "134.82421875",
		zoom: 4
	},
	
	"mexico": {
		centerLat: "22.10599879975055",//"24.766784522874452",
		centerLon: "-88.330078125",
		zoom: 4
	},
	
	"world": {
		centerLat: "2.1088986592431382",
		centerLon: "-18.28125",
		zoom: 1
	}

   };
   
   var getMapInitParams = function(data){
	 	if( data == null){ 	// default to Europe	
			startCenterLat = 49.61070993807422; 
	 		startCenterLon = 16.435546875;
	 		startZoom = 4;				 		  		
	 	} else {
		 	startCenterLat = data.startCenterLat;
	 		startCenterLon = data.startCenterLon;
	 		startZoom = data.startZoom;
		}
  	};
   
   	// constructor
	var GoogleMap = {
	
		center:  	'',					// the center position of the map
		coords:		{long: 0, lat: 0},	// object holding longitude and latitude
		controls:	false,				// boolean, show controls or not (in top left)
		mapMarkers:	{},					// all the markers specified by attributes (name, []= coords, etc)
		mapName: 	'map',					// the name of the map (user-specified, or defaults to "map")
		o:			{},					// user supplied object with Map values 
		zoom: 		3,					// initial zoom level	
		
		/**
		 * initialize the map
		 *
		 * The user can pass in an object that will provide
		 * the GoogleMap with values for the markers, etc
		 *  If no object is passed, the map will be essentially useless.
		 */
		 
		init: function(o) {
			if( typeof(o) === 'object') {
				this.setOptions(o);		// copy the user prefs
				// start at or around Europe.
				this.map.setCenter(new GLatLng(eval(startCenterLat), eval(startCenterLon)), eval(startZoom), G_HYBRID_MAP);	
				this.setControls();		// set the controls for the map (terrain, slider, zoom)
				this.setMarkers(2);		// set the markers for the initial zoom level (2)
			} else {
				throw new Error(errorMessage)
			}
		},
		
		/**
		 * get the markers and set the map by region
		 *
		 * This method will generate the map based on the location id's in the 
		 * regions object.
		 *
		 * 1. set the center of the map
		 * 2. set the markers of the locations based on the ids in the object array
		 *
		 * @example this.getByRegion("namerica");
		 */
		 
		getByRegion: function(region) {					
				// now we have to get the center for the region, and pan and center!
					this.panMap( regions[region].centerLat, regions[region].centerLon , regions[region].zoom);
					this.setMarkers(regions[region].zoom);
		},

				
		/**
		 * this will pan the map to the specified coords.
		 */
		 
		panMap: function(lat, lon, zoom) {
			this.map.setCenter(new GLatLng(lat, lon), zoom);
		},
		
		/**
		 * get the location coordinates based on ID
		 *
		 * @param 	int		the location ID
		 * @return 	Object	the object for the location specified.
		 */
		 
		getCityCoords: function(id) {
				// loop through the cities data array
				// and return the location object specified by the id.
				for( var i = 0 ; i < cities.length; i++ ) {
					if( cities[i].id == id ) return cities[i];
				}
		},
		
		
		/**
		 * loop through the object passed to the contructor
		 * and set the values of the "o" object.
		 */
		 
		setOptions: function(o) {
			for( val in o ) {
				this[val] = o[val];
			}
		},
		
		/**
		 * set the center position for the map
		 *
		 * We must do some calculations based on the marker pool coordinates
		 *
		 * @param 	int 	lat			latitude
		 * @param 	int 	lon 		longitude
		 * @param 	int 	zoomLevel	the current zoomLevel
		 * @return 	void
		 */
		 
		setCenter: function(lat, lon, zoomLevel) {
		
			// make sure there is a viable zoom level for the map
				this.zoomLevel = (zoomLevel !== undefined) ? zoomLevel : 2;
			// calculate the center coordinates based on the pool of markers
			// that meet the current zoom level
				var calcCenterCoords = this.calculateCenterCoords();
			// set the variables for our new calculations for center.
				lat = calcCenterCoords[0];
				lon = calcCenterCoords[1];
			// now center the map with the new coords.
	 			this.map.setCenter(new GLatLng(lat, lon), this.zoomLevel);
	  	},
		
		
		/**
		 * we have to basically use the bounds to generate the coordinates for the center of the map.
		 */
		 
		 
		calculateCenterCoords: function() {
		
			// based on the markers that we have created we will grab the max and min for
			// both latitude and longitude, and then split that number in half, but make sure
			// that we retain the neg/pos value of the number
		
			var minLon = 0;
			var maxLon = 0;
			var minLat = 0;
			var maxLat = 0;
			
			// we need to get the maximum and minimum values for each long and lat.
			for( var i =0; i < this.markers.length; i++) {
				if( this.markers[i].zoom == this.zoomLevel){
					// latitude
						if( parseInt(this.markers[i].lat) < minLat ) minLat = this.markers[i].lat;
						if( parseInt(this.markers[i].lat) > maxLat ) maxLat = this.markers[i].lat;
					// longitude
						if( parseInt(this.markers[i].lon) < minLon ) minLon = this.markers[i].lon;
						if( parseInt(this.markers[i].lon) > maxLon ) maxLon = this.markers[i].lon;
				}
			}
			
			// now we have to take the difference in the two, and get the center.			
				var centerLat = ( Math.abs(maxLat) + Math.abs(minLat) ) / 2;
				var centerLon = ( Math.abs(maxLon) + Math.abs(minLon) ) / 2;
				
			// we have to make sure that we dont lose the (-) in the number.
				if( Math.abs(maxLat) <  Math.abs(minLat) ) centerLat = -(centerLat);
				if( Math.abs(maxLon) <  Math.abs(minLon) ) centerLon = -(centerLon);

				return [ centerLat, centerLon];
		},
		
		
		/**
		 * set the controls display option
		 */
		
		setControls: function() {
			if( this.controls === true) 	this.map.addControl(new GSmallMapControl());
			if( this.controls === true ) 	this.map.addControl(new GMapTypeControl()); 
		},
		
		
		/**
		 * get the center position of the map
		 */
		 
		getCenter: function() {
			return this.center;
		},
		
		/**
		 * set up the Google map initially.
		 * 
		 * This includes setting the class variable "map" if the browser is compatible.
		 */
		
		setMap: function() {
			
			if (GBrowserIsCompatible()) {		// check if the Browser is compatible with Gmaps.
				this.map = new GMap2(document.getElementById(this.mapName));	// instantiate the map
				return true;
			}else{
				return false;
			}
			
		},
		
		// generate the google icon path
		// Note: please uncomment the return line below to switch to your new
		// server for the images.
		
		/**
		 * generate the icon
		 * @param {Object} city
		 */
		
		// donated by Casey (twci)
			getIcon: function(city){
				 //return ['http://i.imwx.com/google/icons/basic/',((city.sky=='null')?'-':city.sky),'_',((city.temp=='null')?'-':city.temp),'_N.png'].join('');
				 return [googleImagePath,((city.sky=='null')?'-':city.sky),'_',((city.temp=='null')?'-':city.temp),'.png'].join('');
			},
			
			
		/**
		 * generate the "get today page" link
		 * @param {Object} city
		 */
			getTodayPage: function(city) {				
				if (city.type == '11') {
					return [travelDetailsPageURL,city.name.replace(/[^\w]/g,''),'-',city.id,':',city.type].join('');
				}
				else {
					return [travelDetailsPageURL,city.name.replace(/[^\w]/g,''),'-',city.id].join('');
				}				
			},
			
		/**
		 * set the markers on the map!
		 *
		 * @param 	int	 the zoom level to draw the coordinates.
		 */
		 
		setMarkers: function(zoomLevel) {
			
		/**
		 * logic for zoom
		 * 
		 * first lets set the current oom level, and then set the markers 
		 * for everything <= that level.
		 */
		
			// set the internal zoom level.
				this.zoomLevel = zoomLevel;
			// lets remove the markers from the entire map
			// and reset them based on the new zoom level passed in.
				this.map.clearOverlays();
			// make sure there are markers available (data).
				if ( this.markers !== null ) {
						
					// variables for the points, etc.
						var point = '';
						var marker = '';
						var name = '';
					// loop through the marker objects
						for( var i = 0, len = this.markers.length; i < len; i++) {
							// show markers less than or equal to the current zoom
							// level that was passed to this method.
								if (this.markers[i].zoom <= this.map.getZoom()) {
									// set the location marker on the map
										this.setLocationMarker(this.markers[i]);
								}
						} // end for
				}
		},
		
		/**
		 * set the individual location marker
		 *
		 * This method will set the location marker
		 * when passed the object from the cities array
		 * 
		 * called from setMarkers method.
		 *
		 */
		 
		 setLocationMarker: function(obj) {

			// object to hold the marker options (icon, lat/lng, etc)
				var opts = {};
				opts.clickable = true;
				opts.title = defaultMessage +" "+obj.name; 
				opts.temp	= obj.temp;  // this will be determined Server side.

			// Create our marker icon (little bubble with icon)
				var icon = new GIcon();
				icon.image = this.getIcon(obj);
				icon.iconSize = new GSize(65, 41); // size of our bubble icons.
				icon.iconAnchor = new GPoint(40, 41);
				icon.infoWindowAnchor = new GPoint(37, 40);
				opts.icon = icon;
			// now create our link!
				opts.travelLink = this.getTodayPage(obj);
			// more variables for the marker
				point 	= new GLatLng(obj.lat, obj.lon);
				marker 	= new GMarker(point, opts);
				marker.opts = opts;
				name 	= obj.name;
			// set the name options
				opts.name = name;
			// add the overlay (marker to the map)
				this.map.addOverlay(marker);
			// debug line.
			//console.log("Location: " + obj.name + " " + obj.lat + " " + obj.lon + " " + icon.image);
		 }
    };
	
	 
	// lets test this out by calling our map
	window.onload = function() { 
		
		// reference the data.js object "cities"
		// provided by twci.
			var markersArray = cities;
			
		// generate the map in the DIV "map"
			var map = new GMap2(document.getElementById("map"));	
		// initialize the google map object.
			GoogleMap.init({
				name: "map",
				markers: markersArray,
				controls: true,
				map: map,
				zoom: 2
			});
		
		// add the listener for the map zoom
			GEvent.addListener( GoogleMap.map, "zoomend", function(){
				// setting the markers
					GoogleMap.setMarkers(map.getZoom());
					// set the debugging zoom level
						//GoogleMap._debug("zoom: " + map.getZoom() +"<br />");
			});
		
		// add the listener for the map movement
			GEvent.addListener( GoogleMap.map, "moveend", function(){
				// handle the move of the map.
			});
			
			
		// click a ( marker, bubble -- info window) OR a point on the map
			GEvent.addListener( map, "click", function(overlay, point){
					
				// first lets check and make sure the user 
				// didnt click on the close button for the bubble info overlay.
				if( point) {
					// handle the point now!
					// this is if you double-click on the map
				} else {
					// handle the overlay (bubble, marker, etc)					
					  if(overlay.opts !== undefined) {
						// set the openInfoWindow HTML code.
						// this was commented out, but if uncommented
						// will reveal the balloon info window.
							//overlay.openInfoWindowHtml("<b>"+ overlay.opts.name + "</b><br>Current temperature: "+ overlay.opts.temp +" &#176;<br /><a href=\"" + overlay.opts.travelLink +"\" target=\"_blank\" alt=\"Click for travel details for " + overlay.opts.name + ".\" title=\"Click for travel details for " + overlay.opts.name + ".\">travel details</a>" );
							 //window.open(overlay.opts.travelLink ,'',''); // Commented out as Product wanted it to open on the same window
							 window.location = overlay.opts.travelLink;	
					  }
				 }
			}); 
			
			
			
		/**
		 * rollovers
		 */

		 	var namericaLink = document.getElementById('namericaLink').childNodes[0];
				namericaLink.onmouseover = function(){
					mouseOverHandler(this);
				}
				namericaLink.onmouseout = function(){
					mouseOutHandler(this, 'namerica');
				}
				namericaLink.onclick = function(){
					clickHandler(this, 'namerica');
				}

			var samericaLink = document.getElementById('samericaLink').childNodes[0];
				samericaLink.onmouseover = function(){
					mouseOverHandler(this);
				}
				samericaLink.onmouseout = function(){
					mouseOutHandler(this, 'samerica');
				}
				samericaLink.onclick = function(){
					clickHandler(this, 'samerica');
				}
				
			var mexicoLink = document.getElementById('mexicoLink').childNodes[0];
				mexicoLink.onmouseover = function(){
					mouseOverHandler(this);
				}
				mexicoLink.onmouseout = function(){
					mouseOutHandler(this, 'mexico');
				}
				mexicoLink.onclick = function(){
					clickHandler(this, 'mexico');
				}
				
			var europeLink = document.getElementById('europeLink').childNodes[0];
				europeLink.onmouseover = function(){
					mouseOverHandler(this);
				}
				europeLink.onmouseout = function(){
					mouseOutHandler(this, 'europe');
				}
				europeLink.onclick = function(){
					clickHandler(this, 'europe');
				}
				
			var asiaLink = document.getElementById('asiaLink').childNodes[0];
				asiaLink.onmouseover = function(){
					mouseOverHandler(this);
				}
				asiaLink.onmouseout = function(){
					mouseOutHandler(this, 'asia');
				}
				asiaLink.onclick = function(){
					clickHandler(this, 'asia');
				}
			
			var africaLink = document.getElementById('africaLink').childNodes[0];
				africaLink.onmouseover = function(){
					mouseOverHandler(this);
				}
				africaLink.onmouseout = function(){
					mouseOutHandler(this, 'africa');
				}
				africaLink.onclick = function(){	
					clickHandler(this, 'africa');
				}
								
			var australiaLink = document.getElementById('australiaLink').childNodes[0];
				australiaLink.onmouseover = function(){
					mouseOverHandler(this);
				}
				australiaLink.onmouseout = function(){
					mouseOutHandler(this, 'australia');	
				}
				australiaLink.onclick = function(){
					clickHandler(this, 'australia');					
				}
			
}

 var current = 'init';
 
 var mouseOverHandler = function (overElm) 
 {
	 //console.log('over: ' + overElm.src);
	 overElm.src =  overElm.src.replace("_over", "");
	 return overElm;
 }
 
 var mouseOutHandler = function (outElm, outRegion)
 {
	  //console.log('out: ' + outElm.src + ', ' + outRegion);
		if (current != outRegion)
		{					
			outElm.src = outElm.src.replace("_", "_over_");
		}
		return outElm;
 }
 
 var clickHandler = function (clickElm, clickRegion)
 {
	 //console.log('click: ' + clickElm.src + ', ' + clickRegion + ', current: ' + current);
	 if (current != 'init')
	 {
	 	 var previousRegion = current + 'Link';
	 	 var previousElm = document.getElementById(current + 'Link').childNodes[0];
	 	 previousElm.src = previousElm.src.replace("_", "_over_");
	 }
	 current = clickRegion;
	 clickElm.src = clickElm.src.replace("_over", "");
	 return clickElm;
 }
			
			
