/**
 * jQuery gMap
 *
 * @url		http://gmap.nurtext.de/
 * @author	Cedric Kastner <cedric@nur-text.de>
 * @version	1.0.3
 */
(function($) {
	function pixelDistance(map,latlon1, latlon2) {

		var p1=map.fromLatLngToContainerPixel(latlon1);
		var p2=map.fromLatLngToContainerPixel(latlon2);

	    return Math.sqrt(Math.pow(p1.x-p2.x,2) + Math.pow(p1.y-p2.y,2));
	}

	function cluster(map,markers,distance) {

	    clustered = array();
	    /* Loop until all markers have been compared. */
	    while (count(markers)) {
	        marker  = markers.pop();
			sourceLatLon=new GLatLng(marker.lat,marker.lon);
	        cluster = array(marker);
			var extents={
				left: marker.lon,
				right: marker.lon,
				top: marker.lat,
				bottom: marker.lat
			};
	        /* Compare against all markers which are left. */
	        for (var i=0;i<markers.length;i++) {
				target=markers[i];
				targetLatLon=new GLatLng(target.lat,target.lon);
				if (pixelDistance(map,sourceLatLon,targetLatLon)<distance) {
					/* If two markers are closer than given distance remove */
		            /* target marker from array and add it to cluster.      */
		            cluster.push(target);
					markers.slice(i,1);
					i-=1;
					extents.left=Math.min(extents.left,target.lon);
					extents.right=Math.max(extents.right,target.lon);
					extents.top=Math.max(extents.top,target.lat);
					extents.bottom=Math.min(extents.bottom,target.lat);
				};
			};
			if (cluster.length==1) {
				clustered.push(marker);
			} else {
            	clustered.push({points: cluster.length, lon: (extents.right+extents.left)/2, lat: (extents.top+extents.bottom)/2 });
			}
	    };
	    return clustered;
	}
	
	// Main plugin function
	$.fn.gMap = function(options) {
		// Check if the browser is compatible with Google Maps
		if (!window.GBrowserIsCompatible || !GBrowserIsCompatible()) return this;
		
		// Build main options before element iteration
		var opts = $.extend({}, $.fn.gMap.defaults, options);
    
		// Iterate each matched element
		return this.each(function()	{
			// Create new map and set initial options
			$gmap = new GMap2(this);
			$(this).data('gmap',$gmap);
			
			// Try to center to the first marker
			if (!opts.latitude && !opts.longitude) {
				// Check for at least one marker
				if (is_array(opts.markers) && opts.markers.length >= 1) {
					// Center to the first marker
					opts.latitude  =  opts.markers[0].latitude;
					opts.longitude =  opts.markers[0].longitude;
				} else {
					// Center Earth and lower zoom
					opts.latitude = 34.885931;
					opts.longitude = 9.84375;
					opts.zoom = 2;
				}
			}
			
			// Center the map and set the maptype
			$gmap.setCenter(new GLatLng(opts.latitude, opts.longitude), opts.zoom);
			$gmap.setMapType(opts.maptype);
			
			// Check for custom map controls
			if (opts.controls.length == 0) {
				// Default map controls
				//$gmap.setUIToDefault();
			} else {
				// Add custom map controls
				for (var i = 0; i < opts.controls.length; i++) {
					// Eval is evil - I know. ;)
					eval('$gmap.addControl(new ' + opts.controls[i] + '());');
				}
			}
			
			if (opts.logo) {
				// TODO: Allow for right/bottom placement
				var logo=opts.logo;
				$gmap.addOverlay(new GScreenOverlay(logo.src, new GScreenPoint(logo.x,logo.y), new GScreenPoint(logo.ox,logo.oy), new GScreenSize(logo.sw,logo.sh)));
			};
						
			// Check if scrollwheel should be enabled when using custom controls
			if (opts.scrollwheel == true && opts.controls.length != 0) { 
				$gmap.enableScrollWheelZoom(); 
			}
			var displayMarkers=[];
			if (opts.clustered) {
				displayMarkers=cluster($gmap,opts.markers,opts.cluster.distance);
			} else {
				displayMarkers=opts.markers;
			};
			// Add all map markers
			for (var j = 0; j < displayMarkers.length; j++) {
				// Get the options from current marker
				marker = displayMarkers[j];
			
				// Create new icon
				gicon = new GIcon();
			
				// Set icon properties from global options
				gicon.image = opts.icon.image;
				if (opts.clustered && marker.points && marker.points>1) {
					gicon.image = opts.cluster.iconbase.replace(/#/,marker.points);
				};
				gicon.shadow = opts.icon.shadow;
				gicon.iconSize = (is_array(opts.icon.iconsize)) ? new GSize(opts.icon.iconsize[0], opts.icon.iconsize[1]) : opts.icon.iconsize;
				gicon.shadowSize = (is_array(opts.icon.shadowsize)) ? new GSize(opts.icon.shadowsize[0], opts.icon.shadowsize[1]) : opts.icon.shadowsize;
				gicon.iconAnchor = (is_array(opts.icon.iconanchor)) ? new GPoint(opts.icon.iconanchor[0], opts.icon.iconanchor[1]) : opts.icon.iconanchor;
				gicon.infoWindowAnchor = (is_array(opts.icon.infowindowanchor)) ? new GPoint(opts.icon.infowindowanchor[0], opts.icon.infowindowanchor[1]) : 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(opts.html_prepend + marker.html + opts.html_append);
					jQuery(gmarker).data('html',marker.html);
				
					// 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(opts.html_prepend + marker.html + opts.html_append); }
					if (!marker.onClick) {
						GEvent.addListener(gmarker,'click',function() {
							try {
								this.openInfoWindowHtml(jQuery(this).data('html'));
							} catch(e) {
								var i=1;
							}
						 
						});
					};

				} else {
					// Add overlay marker
					if (gmarker) { $gmap.addOverlay(gmarker); }
				}
				if (marker.onClick) {
					GEvent.addListener($gmap,'click',marker.onClick);
				}
			}
		});
		
	}
	
	// Function to check if array or not
	function is_array(input) {
		return typeof(input) == 'object' && (input instanceof Array);
  	}
	
	// Set default settings
	$.fn.gMap.defaults = {
		latitude:				0,
		longitude:				0,
		zoom:					6,
		markers:				[],
		controls:				[],
		scrollwheel:			true,
		maptype:				G_NORMAL_MAP,
		html_prepend:			'<div class="gmap_marker">',
		html_append:			'</div>',
		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]
		}		
	}
	
	$.shfr = $.shfr || {};
	$.shfr.gmap = 	$.shfr.gmap || {};
	
	$.shfr.gmap.marker = function(gmap,opts) {
		
		// Icon Options
		this.iconDefaults={
			image: 'icon.png',
			shadow:				"http://www.google.com/mapfiles/shadow50.png",
			iconsize:			[20, 34],
			shadowsize:			[37, 34],
			iconanchor:			[9, 34],
			infowindowanchor:	[9, 2]
		};
		
		$.extend(this.iconDefaults,opts.icon);
		opts.icon=this.iconDefaults;
		
		// Default options
		this.defaults = {
			lat: 0,
			lon: 0,
			html: '',
			html_prepend: '',
			html_append: ''
		};
		
		// Overwrite defaults, if set
		$.extend(this.defaults,opts);

		
		opts = this.defaults;
		
		// Create new icon
		var gicon = new GIcon();
		
		// Set icon properties from global options
		gicon.image = opts.icon.image;
		gicon.shadow = opts.icon.shadow;
		gicon.iconSize = (is_array(opts.icon.iconsize)) ? new GSize(opts.icon.iconsize[0], opts.icon.iconsize[1]) : opts.icon.iconsize;
		gicon.shadowSize = (is_array(opts.icon.shadowsize)) ? new GSize(opts.icon.shadowsize[0], opts.icon.shadowsize[1]) : opts.icon.shadowsize;
		gicon.iconAnchor = (is_array(opts.icon.iconanchor)) ? new GPoint(opts.icon.iconanchor[0], opts.icon.iconanchor[1]) : opts.icon.iconanchor;
		gicon.infoWindowAnchor = (is_array(opts.icon.infowindowanchor)) ? new GPoint(opts.icon.infowindowanchor[0], opts.icon.infowindowanchor[1]) : opts.icon.infowindowanchor;
		
		// Create a new marker on the map
		this.marker = new GMarker(new GPoint(opts.lon, opts.lat), gicon);
		
		// Only display info window if the marker contains a description
		if (opts.html) {
			// Bind the info window to marker
			this.marker.bindInfoWindowHtml(opts.html_prepend + opts.html + opts.html_append);
			
			// Add overlay if marker was created and check if popup should be shown when map is loaded
			if (this.marker) { gmap.addOverlay(this.marker); }
			if (opts.popup == true) { this.marker.openInfoWindowHtml(opts.html_prepend + opts.html + opts.html_append); }
		} else {
			// Add overlay marker
			if (this.marker) { gmap.addOverlay(this.marker); }
		}
		if (opts.onClick) {
			GEvent.addListener(gmap,'click',opts.onClick);
		}
		
		
	};
	
	$.extend($.shfr.gmap.marker.prototype,{
		remove: function(marker) {
			
		}
	});
	
})(jQuery);
