(function ($) {

	/**
	 * initMap
	 *
	 * Renders a Google Map onto the selected jQuery element
	 *
	 * @date    22/10/19
	 * @since   5.8.6
	 *
	 * @param   jQuery $el The jQuery element.
	 * @return  object The map instance.
	 */
	function initMap($el) {

		// Find marker elements within map.
		var $markers = $el.find('.marker');

		// Create gerenic map.
		var mapArgs = {
			zoom: $el.data('zoom') || 16,
			mapTypeId: google.maps.MapTypeId.ROADMAP,
			styles: $el.data('style') || [],
		};
		var map = new google.maps.Map($el[0], mapArgs);

		// Add markers.
		map.markers = [];
		$markers.each(function () {
			initMarker($(this), map);
		});

		// Center map based on markers.
		centerMap(map);

		// Return map instance.
		return map;
	}

	/**
	 * initMarker
	 *
	 * Creates a marker for the given jQuery element and map.
	 *
	 * @date    22/10/19
	 * @since   5.8.6
	 *
	 * @param   jQuery $el The jQuery element.
	 * @param   object The map instance.
	 * @return  object The marker instance.
	 */
	function initMarker($marker, map) {
		var iconData = $marker.data('marker'),
			iconImage = iconData;

		if (iconData.charAt(0) === '#') {
			var markerSvg = [
				'<?xml version="1.0"?>',
				'<svg width="64px" height="64px" viewBox="0 0 64 64" version="1.1" xmlns="http://www.w3.org/2000/svg">',
				'<path fill="' + iconData + '" d="M32,4.75c-10.401,0-18.833,8.432-18.833,18.833c0,3.345,0.898,6.474,2.428,9.195c0.254,0.452,0.52,0.897,0.809,1.325L32,61.25l15.596-27.146c0.24-0.355,0.447-0.732,0.662-1.104l0.148-0.221c1.528-2.721,2.427-5.85,2.427-9.195C50.833,13.182,42.401,4.75,32,4.75z M32,14.167c5.2,0,9.417,4.216,9.417,9.417c0,5.2-4.216,9.417-9.417,9.417s-9.417-4.216-9.417-9.417S26.799,14.167,32,14.167z M32,12c-6.501,0-11.771,5.27-11.771,11.771c0,6.5,5.27,11.771,11.771,11.771c6.5,0,11.771-5.271,11.771-11.771C43.771,17.271,38.5,12,32,12z M32,16.708c3.901,0,7.063,3.162,7.063,7.063S35.901,30.834,32,30.834s-7.063-3.162-7.063-7.063S28.099,16.708,32,16.708z"/>',
				'<path fill="#000000" fill-opacity="0.3" d="M32,12c-6.501,0-11.771,5.27-11.771,11.771c0,6.5,5.27,11.771,11.771,11.771c6.5,0,11.771-5.271,11.771-11.771C43.771,17.271,38.5,12,32,12z M32,16.708c3.901,0,7.063,3.162,7.063,7.063S35.901,30.834,32,30.834s-7.063-3.162-7.063-7.063S28.099,16.708,32,16.708z"/>',
				'</svg>'
			].join('\n');

			iconImage = 'data:image/svg+xml;charset=UTF-8,' + encodeURIComponent(markerSvg);
		}

		// Get position from marker.
		var lat = $marker.data('lat');
		var lng = $marker.data('lng');
		var icon = {
			url: iconImage,
			scaledSize: new google.maps.Size(75, 75)
		};

		var latLng = {
			lat: parseFloat(lat),
			lng: parseFloat(lng)
		};

		// Create marker instance.
		var marker = new google.maps.Marker({
			position: latLng,
			map: map,
			icon: icon
		});

		// Append to reference for later use.
		map.markers.push(marker);

		// If marker contains HTML, add it to an infoWindow.
		if ($marker.html()) {

			// Create info window.
			var infowindow = new google.maps.InfoWindow({
				content: $marker.html()
			});

			// Show info window when marker is clicked.
			google.maps.event.addListener(marker, 'click', function () {
				infowindow.open(map, marker);
			});
		}
	}

	/**
	 * centerMap
	 *
	 * Centers the map showing all markers in view.
	 *
	 * @date    22/10/19
	 * @since   5.8.6
	 *
	 * @param   object The map instance.
	 * @return  void
	 */
	function centerMap(map) {

		// Create map boundaries from all map markers.
		var bounds = new google.maps.LatLngBounds();
		map.markers.forEach(function (marker) {
			bounds.extend({
				lat: marker.position.lat(),
				lng: marker.position.lng()
			});
		});

		// Case: Single marker.
		if (map.markers.length == 1) {
			map.setCenter(bounds.getCenter());

			// Case: Multiple markers.
		} else {
			map.fitBounds(bounds);

			// or for change zoom:
			// map.setCenter( bounds.getCenter() );
			// map.setZoom( 13 );
		}
	}

	// Render maps on page load.
	$(document).ready(function () {
		$('.acf-map').each(function () {
			var map = initMap($(this));
		});
	});

})(jQuery);