/**
 * jQuery jMap
 *
 * Forked from Original Plugin:
 * @url		http://gmap.nurtext.de/
 * @author	Cedric Kastner <cedric@nur-text.de>
 * @version	1.0.3
 *
 * jMap Branch:
 * @url 	http://jeremy-fry.com/project/jmap
 * @author	Jeremy Fry <jeremy.m.fry@gmail.com>
 * @version 1.0
 */
(function(jQuery)
{
	// Main plugin function
	jQuery.fn.jMap = function(options)
	{
		// Check if the browser is compatible with Google Maps
		if (!window.GBrowserIsCompatible || !GBrowserIsCompatible()) return this;
		
    
		// Iterate each matched element
		var maps;
		this.each(function()
		{
			// Create new map and set initial options
			gmap = new GMap2(this);
			// Build main options before element iteration
			gmap.opts = $.extend({}, jQuery.fn.jMap.defaults, options);

			gmap.currentMarkers = new Array();
			//updates the current set of markers
			
			// Create new object to geocode addresses
			gmap.geocoder = new GClientGeocoder();
			
			//Address lookup for geocoding, add determines wether to return the value or add the address to map
			gmap.AddressLookup = function lookupaddress(address,callback)
			{
				if(typeof(callback) != 'function')
				{
					gmap.geocoder.getLatLng(
				    address,
				    function(point) {
				      if (!point) {
				        alert(address + " not found");
				      } else {
				        gmap.setCenter(point, gmap.opts.zoom);
				        gmap.UpdateMarkers([{"latitude":point.x,"longitude":point.y,"html": "<p>"+address+"</p>"}]);
				      }
				    });
				}else{
					gmap.geocoder.getLatLng(
				    address,
				    function(point) {
						callback(point);
				    });
				}
			}
			
			gmap.UpdateMarkers = function update(markers)
			{
				gmap.opts.markers = markers;
				gmap.AddMarkers();
			}
			
			gmap.ClearMarkers = function clear()
			{
				//todo: build in more robust clearing options
				for (var j = 0; j < gmap.currentMarkers.length; j++)
				{
					gmap.removeOverlay(gmap.currentMarkers[j]);
				}
			}
			
			//adds markers to the map. stors them in gmap.currentMarkers[] so they can be deleted as needed
			gmap.AddMarkers = function add()
			{
				// Add all map markers
				for (var j = 0; j < gmap.opts.markers.length; j++)
				{
					// Get the options from current marker
					marker = gmap.opts.markers[j];
					
					// Create new icon
					gicon = new GIcon();
					
					// Set icon properties from global options
					gicon.image = gmap.opts.icon.image;
					gicon.shadow = gmap.opts.icon.shadow;
					gicon.iconSize = (is_array(gmap.opts.icon.iconsize)) ? new GSize(gmap.opts.icon.iconsize[0], gmap.opts.icon.iconsize[1]) : gmap.opts.icon.iconsize;
					gicon.shadowSize = (is_array(gmap.opts.icon.shadowsize)) ? new GSize(gmap.opts.icon.shadowsize[0], gmap.opts.icon.shadowsize[1]) : gmap.opts.icon.shadowsize;
					gicon.iconAnchor = (is_array(gmap.opts.icon.iconanchor)) ? new GPoint(gmap.opts.icon.iconanchor[0], gmap.opts.icon.iconanchor[1]) : gmap.opts.icon.iconanchor;
					gicon.infoWindowAnchor = (is_array(gmap.opts.icon.infowindowanchor)) ? new GPoint(gmap.opts.icon.infowindowanchor[0], gmap.opts.icon.infowindowanchor[1]) : gmap.opts.icon.infowindowanchor;
					
					if (marker.icon)
					{
						// Overwrite global options with ther marker one's
						gicon.image = marker.icon.image;
						gicon.shadow = marker.icon.shadow;
						gicon.iconSize = (is_array(marker.icon.iconsize)) ? new GSize(marker.icon.iconsize[0], marker.icon.iconsize[1]) : marker.icon.iconsize;
						gicon.shadowSize = (is_array(marker.icon.shadowsize)) ? new GSize(marker.icon.shadowsize[0], marker.icon.shadowsize[1]) : marker.icon.shadowsize;
						gicon.iconAnchor = (is_array(marker.icon.iconanchor)) ? new GPoint(marker.icon.iconanchor[0], marker.icon.iconanchor[1]) : marker.icon.iconanchor;
						gicon.infoWindowAnchor = (is_array(marker.icon.infowindowanchor)) ? new GPoint(marker.icon.infowindowanchor[0], marker.icon.infowindowanchor[1]) : marker.icon.infowindowanchor;
						
					}
									
					// Create a new marker on the map
					gmarker = new GMarker(new GPoint(marker.longitude, marker.latitude), gicon);
					
					// Only display info window if the marker contains a description
					if (marker.html)
					{
						// Bind the info window to marker
						gmarker.bindInfoWindowHtml(gmap.opts.html_prepend + marker.html + gmap.opts.html_append);
						
						// Add overlay if marker was created and check if popup should be shown when map is loaded
						if (gmarker) { gmap.addOverlay(gmarker); }
						if (marker.popup == true) { gmarker.openInfoWindowHtml(gmap.opts.html_prepend + marker.html + gmap.opts.html_append); }
						
					}
					else
					{
						// Add overlay marker
						if (gmarker) { gmap.addOverlay(gmarker); }
					}
						//Save the marker to an array
						gmap.currentMarkers[j] = gmarker;
				}
			}//end add marker
			// If traffic is turned on initialize it
			if(gmap.opts.traffic)
			{
				var trafficInfo = new GTrafficOverlay(gmap.opts.traffic_gmap.opts);
				gmap.addOverlay(trafficInfo);
			}
			// Try to center to the first marker
			if (!gmap.opts.latitude && !gmap.opts.longitude)
			{
				// Check for at least one marker
				if (is_array(gmap.opts.markers) && gmap.opts.markers.length >= 1)
				{
					// Center to the first marker
					gmap.opts.latitude  =  gmap.opts.markers[0].latitude;
					gmap.opts.longitude =  gmap.opts.markers[0].longitude;
				}
				else
				{
					// Center Earth and lower zoom
					gmap.opts.latitude = 34.885931;
					gmap.opts.longitude = 9.84375;
					gmap.opts.zoom = 2;
				}
				
			}
			
			// Center the map and set the maptype
			gmap.setCenter(new GLatLng(gmap.opts.latitude, gmap.opts.longitude), gmap.opts.zoom);
			gmap.setMapType(gmap.opts.maptype);
			
			// Check for custom map controls
			if (gmap.opts.controls.length == 0)
			{
				// Default map controls
				gmap.setUIToDefault();
				
			}
			else
			{
				// Add custom map controls
				for (var i = 0; i < gmap.opts.controls.length; i++)
				{
					// Eval is evil - I know. ;)
					eval('gmap.addControl(new ' + gmap.opts.controls[i] + '());');
				}
				
			}
			//add the initial set of markers
			gmap.AddMarkers(gmap.opts);
		
			// Check if scrollwheel should be enabled when using custom controls
			if (gmap.opts.scrollwheel == true && gmap.opts.controls.length != 0) { gmap.enableScrollWheelZoom(); }
			
			
			//Event listeners
			if(typeof(gmap.opts.events) != 'undefined')
			{
				$.each(gmap.opts.events, function(key,val)
				{
					//key is the event, val is the function to run
					GEvent.addListener(gmap,key, function(overlay, latlng)
					{
						if(typeof(val) != 'function'){return true;}
						if(typeof(latlng) == "undefined"){ latlng = gmap.getCenter(); }	
							val(latlng);
					});
					
				});
			}			
			//can't return from inside the this.each correctly so pass to global var and return
			//the map so its functions can be accessed
			maps = gmap;
		});

		return maps;

		
	}//end gmap
	

	
	// Function to check if array or not
	function is_array(input)
	{
		return typeof(input) == 'object' && (input instanceof Array);
  	}
	
	// Set default settings
	jQuery.fn.jMap.defaults =
	{
		longitude:			-83.10745239257812,
		latitude:			42.39278353804252,
		zoom:					12,
		markers:			[],
		controls:			[],
		scrollwheel:		true,
		maptype:				G_NORMAL_MAP,
		html_prepend:		'<div class="gmap_marker">',
		html_append:		'</div>',
		traffic_opts:		{incidents:true},
		traffic:				false,
		events:				[],
		icon:
		{
			image:				"http://www.google.com/mapfiles/marker.png",
			shadow:				"http://www.google.com/mapfiles/shadow50.png",
			iconsize:			[20, 34],
			shadowsize:			[37, 34],
			iconanchor:			[9, 34],
			infowindowanchor:	[9, 2]
			
		}
	}
	
})(jQuery);
