/**
 * jQuery gMap - Google Maps API V3
 *
 * @url     http://github.com/marioestrada/jQuery-gMap
 * @author  Mario Estrada <me@mario.ec> based on original plugin by Cedric Kastner <cedric@nur-text.de>
 * @version 2.1.1
 */
(function($, undefined) {
	"use strict";

	// Main plugin function
	$.fn.gMap = function(options, methods_options) {
		var $this, args;
		//Asynchronously load Maps API
		if ( (!window.google || !google.maps) && !window.google_maps_api_loading) {
			$this = this;
			args = arguments;
			var cb = 'callback_' + Math.random().toString().replace('.', '');

			window.google_maps_api_loading = cb;

			window[cb] = function() {
				$.fn.gMap.apply($this, args);
				$(window).trigger('google-maps-async-loading');
				window[cb] = null;
				try {
					delete window[cb];
				} catch(e) {}
			};

			var key = window.VAMTAM_FRONT && window.VAMTAM_FRONT.gmap_api_key ? '&key=' + VAMTAM_FRONT.gmap_api_key : '';

			$.getScript(location.protocol + '//maps.googleapis.com/maps/api/js?v=3&sensor=false&callback=' + cb + key);
			return this;
		} else if ( (!window.google || !google.maps) && window.google_maps_api_loading) {
			$this = this;
			args = arguments;

			$(window).bind('google-maps-async-loading', function() {
				$.fn.gMap.apply($this, args);
			});

			return this;
		}

		// Optional methods
		switch (options) {
			case 'addMarker':
				return $(this).trigger('gMap.addMarker', [methods_options.latitude, methods_options.longitude, methods_options.content, methods_options.icon, methods_options.popup]);
			case 'centerAt':
				return $(this).trigger('gMap.centerAt', [methods_options.latitude, methods_options.longitude, methods_options.zoom]);
		}

		// Build main options before element iteration
		var opts = $.extend({}, $.fn.gMap.defaults, options);

		// Iterate through each element
		return this.each(function() {
			// Create map and set initial options
			var $gmap = new google.maps.Map(this);

			// Create new object to geocode addresses
			var $geocoder = new google.maps.Geocoder();

			// Check for address to center on
			if (opts.address) {
				// Get coordinates for given address and center the map
				$geocoder.geocode({
					address: opts.address
				}, function(gresult) {
					if (gresult && gresult.length) $gmap.setCenter(gresult[0].geometry.location);
				});
			} else {
				// Check for coordinates to center on
				if (opts.latitude && opts.longitude) {
					// Center map to coordinates given by option
					$gmap.setCenter(new google.maps.LatLng(opts.latitude, opts.longitude));
				} else {
					// Check for a marker to center on (if no coordinates given)
					if ($.isArray(opts.markers) && opts.markers.length > 0) {
						// Check if the marker has an address
						if (opts.markers[0].address) {
							// Get the coordinates for given marker address and center
							$geocoder.geocode({
								address: opts.markers[0].address
							}, function(gresult) {
								if (gresult && gresult.length > 0) $gmap.setCenter(gresult[0].geometry.location);
							});
						} else {
							// Center the map to coordinates given by marker
							$gmap.setCenter(new google.maps.LatLng(opts.markers[0].latitude, opts.markers[0].longitude));
						}
					} else {
						// Revert back to world view
						$gmap.setCenter(new google.maps.LatLng(34.885931, 9.84375));
					}
				}
			}
			$gmap.setZoom(opts.zoom);

			// Set the preferred map type
			$gmap.setMapTypeId(google.maps.MapTypeId[opts.maptype]);

			// Set scrollwheel option
			var map_options = {
				scrollwheel: opts.scrollwheel,
				disableDoubleClickZoom: !opts.doubleclickzoom
			};
			// Check for map controls
			if (opts.controls === false) {
				$.extend(map_options, {
					disableDefaultUI: true
				});
			} else if (opts.controls.length !== 0) {
				$.extend(map_options, opts.controls, {
					disableDefaultUI: true
				});
			}

			$gmap.setOptions($.extend(map_options, opts.custom));

			// Create new icon
			var gicon = new google.maps.Marker();

			// Set icon properties from global options
			var marker_icon = new google.maps.MarkerImage(opts.icon.image);
			marker_icon.size = new google.maps.Size(opts.icon.iconsize[0], opts.icon.iconsize[1]);
			marker_icon.anchor = new google.maps.Point(opts.icon.iconanchor[0], opts.icon.iconanchor[1]);
			gicon.setIcon(marker_icon);

			if (opts.icon.shadow) {
				var marker_shadow = new google.maps.MarkerImage(opts.icon.shadow);
				marker_shadow.size = new google.maps.Size(opts.icon.shadowsize[0], opts.icon.shadowsize[1]);
				marker_shadow.anchor = new google.maps.Point(opts.icon.shadowanchor[0], opts.icon.shadowanchor[1]);
				gicon.setShadow(marker_shadow);
			}

			// Bind actions
			$(this).bind('gMap.centerAt', function(e, latitude, longitude, zoom) {
				if (zoom) $gmap.setZoom(zoom);

				$gmap.panTo(new google.maps.LatLng(parseFloat(latitude), parseFloat(longitude)));
			});

			var last_infowindow;
			$(this).bind('gMap.addMarker', function(e, latitude, longitude, content, icon, popup) {
				var glatlng = new google.maps.LatLng(parseFloat(latitude), parseFloat(longitude));

				var gmarker = new google.maps.Marker({
					position: glatlng
				});

				if (icon) {
					marker_icon = new google.maps.MarkerImage(icon.image);
					marker_icon.size = new google.maps.Size(icon.iconsize[0], icon.iconsize[1]);
					marker_icon.anchor = new google.maps.Point(icon.iconanchor[0], icon.iconanchor[1]);
					gmarker.setIcon(marker_icon);

					if (icon.shadow) {
						marker_shadow = new google.maps.MarkerImage(icon.shadow);
						marker_shadow.size = new google.maps.Size(icon.shadowsize[0], icon.shadowsize[1]);
						marker_shadow.anchor = new google.maps.Point(icon.shadowanchor[0], icon.shadowanchor[1]);
						gicon.setShadow(marker_shadow);
					}
				} else {
					gmarker.setIcon(gicon.getIcon());
					gmarker.setShadow(gicon.getShadow());
				}

				if (content) {
					if (content === '_latlng') content = latitude + ', ' + longitude;

					var infowindow = new google.maps.InfoWindow({
						content: opts.html_prepend + content + opts.html_append
					});

					google.maps.event.addListener(gmarker, 'click', function() {
						if(last_infowindow)
							last_infowindow.close();
						infowindow.open($gmap, gmarker);
						last_infowindow = infowindow;
					});

					if(popup)
						infowindow.open($gmap, gmarker);
				}
				gmarker.setMap($gmap);
			});

			var addMarker = function(marker, $this) {
				return function(gresult) {
					// Create marker
					if (gresult && gresult.length > 0) {
						$($this).trigger('gMap.addMarker', [gresult[0].geometry.location.lat(), gresult[0].geometry.location.lng(), marker.html, marker.icon, marker.popup]);
					}
				};
			};

			// Loop through marker array
			for (var j = 0; j < opts.markers.length; j++) {
				// Get the options from current marker
				var marker = opts.markers[j];

				// Check if address is available
				if (marker.address) {
					// Check for reference to the marker's address
					if (marker.html === '_address') marker.html = marker.address;

					// Get the point for given address
					var $this = this;
					$geocoder.geocode({
						address: marker.address
					}, (addMarker)(marker, $this));
				} else {
					$(this).trigger('gMap.addMarker', [marker.latitude, marker.longitude, marker.html, marker.icon, marker.popup]);
				}
			}
		});

	};

	// Default settings
	$.fn.gMap.defaults = {
		address: '',
		latitude: 0,
		longitude: 0,
		zoom: 1,
		markers: [],
		controls: [],
		scrollwheel: false,
		doubleclickzoom: true,
		maptype: 'ROADMAP',
		html_prepend: '<div class="gmap_marker">',
		html_append: '</div>',
		icon: {
			image: "https://www.google.com/mapfiles/marker.png",
			shadow: "https://www.google.com/mapfiles/shadow50.png",
			iconsize: [20, 34],
			shadowsize: [37, 34],
			iconanchor: [9, 34],
			shadowanchor: [6, 34]
		}
	};

})(jQuery);