// -------------------------------------------------------------------------------------------
//
// AVIA GOOGLE MAPS API - loads the google maps api asynchronously
//
// afterwards applies the map to the container
//
// -------------------------------------------------------------------------------------------
(function($)
{
    "use strict";

	$.AviaMapsAPI = function(options, container)
	{
		if(typeof window.av_google_map == 'undefined')
		{
			$.avia_utilities.log('Map creation stopped, var av_google_map not found');
			return;
		}

		// gather container and map data
		this.container	= container;
		this.$container	= $( container );
		this.$body  	= $('body');
		this.$mapid		= this.$container.data('mapid');
		this.$data		= window.av_google_map[this.$mapid];
		this.retina 	= window.devicePixelRatio > 1;

		// set up the whole api object
		this._init( options );
	};

	$.AviaMapsAPI.apiFiles =
	{
		loading: false,
		finished: false,
		src: ''
	};

  	$.AviaMapsAPI.prototype =
    {
    	_init: function()
    	{
			if( this.$body.hasClass( 'av-gmaps-no-google-fonts' ) )
			{
				var head = document.getElementsByTagName('head')[0];
				var insertBefore = head.insertBefore;

				head.insertBefore = function( newElement, referenceElement )
				{
					if( newElement.href && (
						newElement.href.indexOf('//fonts.googleapis.com/css?family=Roboto') > -1
						|| newElement.href.indexOf('//fonts.googleapis.com/css?family=Google+Sans+Text') > -1
					))
					{
						console.info( 'Prevented gMaps from loading gFonts!' );
						return;
					}

					insertBefore.call( head, newElement, referenceElement );
				};
			}

			if( 'undefined' == typeof avia_framework_globals.gmap_maps_loaded || avia_framework_globals.gmap_maps_loaded == '' )
			{
						//	this is only a fallback setting - should never be used
				var gmap_version = 'string' == typeof avia_framework_globals.gmap_version ? avia_framework_globals.gmap_version : 'weekly';
				$.AviaMapsAPI.apiFiles.src = 'https://maps.googleapis.com/maps/api/js?loading=async&libraries=marker&v=' + gmap_version + '&callback=aviaOnGoogleMapsLoaded';
				if( typeof avia_framework_globals.gmap_api != 'undefined' && avia_framework_globals.gmap_api != "" )
				{
					$.AviaMapsAPI.apiFiles.src += "&key=" + avia_framework_globals.gmap_api;
				}
			}
			else
			{
				$.AviaMapsAPI.apiFiles.src = avia_framework_globals.gmap_maps_loaded;
			}

    		this._bind_execution();
    		this._getAPI();
    	},

    	_getAPI: function()
		{
			//make sure the api file is loaded only once
			if((typeof window.google == 'undefined' || typeof window.google.maps == 'undefined') && $.AviaMapsAPI.apiFiles.loading == false)
			{
				$.AviaMapsAPI.apiFiles.loading = true;

				var script = document.createElement('script');

				script.id = 'av-google-maps-api';
				script.type = 'text/javascript';
				script.src = $.AviaMapsAPI.apiFiles.src;

      			document.body.appendChild(script);
			}
			else if((typeof window.google != 'undefined' && typeof window.google.maps != 'undefined') || $.AviaMapsAPI.apiFiles.loading == false)
			//else if($.AviaMapsAPI.apiFiles.finished === true)
			{
				this._applyMap();
			}
		},

		_bind_execution: function()
		{
			this.$body.on( 'av-google-maps-api-loaded', this._applyMap.bind( this ) );
		},

		_applyMap: function()
		{
			if( typeof this.map != 'undefined' )
			{
				return;
			}

			if( ! this.$data.marker || ! this.$data.marker[0] || ! this.$data.marker[0].lat || ! this.$data.marker[0].long )
			{
				$.avia_utilities.log('Latitude or Longitude missing. Make sure you did not only enter an address. You need to fetch the coordinates too.', 'map-error');
				return;
			}

			var _self = this,
				mobile_drag = $.avia_utilities.isMobile ? this.$data.mobile_drag_control : true,
				zoomValue 	= this.$data.zoom == "auto" ? 10 : this.$data.zoom;

			var mapTypeControl = false;
			var mapTypeId = google.maps.MapTypeId.ROADMAP;
			var mapTypeControlOptions = google.maps.MapTypeControlStyle.DROPDOWN_MENU;

			switch( this.$data.maptype_control )
			{
				case 'dropdown':
					mapTypeControl = true;
					mapTypeControlOptions = google.maps.MapTypeControlStyle.DROPDOWN_MENU;
					break;
				case 'horizontal':
					mapTypeControl = true;
					mapTypeControlOptions = google.maps.MapTypeControlStyle.HORIZONTAL_BAR;
					break;
				case 'default':
					mapTypeControl = true;
					mapTypeControlOptions = google.maps.MapTypeControlStyle.DEFAULT;
					break;
				default:
					mapTypeControl = false;
					mapTypeControlOptions = google.maps.MapTypeControlStyle.DROPDOWN_MENU;
					break;
			}

			switch( this.$data.maptype_id )
			{
				case 'SATELLITE':
					mapTypeId = google.maps.MapTypeId.SATELLITE;
					break;
				case 'HYBRID':
					mapTypeId = google.maps.MapTypeId.HYBRID;
					break;
				case 'TERRAIN':
					mapTypeId = google.maps.MapTypeId.TERRAIN;
					break;
				default:
					mapTypeId = google.maps.MapTypeId.ROADMAP;
			}

			if( 'undefined' == typeof this.$data.scrollwheel ) {this.$data.scrollwheel = false; }
			if( 'undefined' == typeof this.$data.gestureHandling ) {this.$data.gestureHandling = 'cooperative'; }
			if( 'undefined' == typeof this.$data.backgroundColor ) {this.$data.backgroundColor = 'transparent'; }
			if( 'undefined' == typeof this.$data.styles ) {this.$data.styles = [{featureType: "poi", elementType: "labels", stylers: [ { visibility: "off" }] }]; };


			this.mapVars = {
//				mapId: 'DEMO_MAP_ID',  //this.$mapid,
				mapMaker: false, //mapmaker tiles are user generated content maps. might hold more info but also be inaccurate
				backgroundColor: this.$data.backgroundColor,
				streetViewControl: this.$data.streetview_control,
				zoomControl: this.$data.zoom_control,
				//draggable: mobile_drag,
				gestureHandling: this.$data.gestureHandling,
				scrollwheel: this.$data.scrollwheel,
				zoom: zoomValue,
				mapTypeControl: mapTypeControl,
				mapTypeControlOptions: {style:mapTypeControlOptions},
				mapTypeId: mapTypeId,
				center: new google.maps.LatLng(this.$data.marker[0].lat, this.$data.marker[0].long),
				styles: typeof this.$data.styles === 'string' ? JSON.parse(this.$data.styles) : this.$data.styles
			};

			this.map = new google.maps.Map(this.container, this.mapVars);
			this.$container.removeClass('av_gmaps_show_delayed av_gmaps_show_unconditionally');
			this.$container.addClass('av_gmaps_map_attached');

			this._applyMapStyle();

			if(this.$data.zoom == "auto")
			{
				this._setAutoZoom();
			}

			google.maps.event.addListenerOnce(this.map, 'tilesloaded', function() {
				_self._addMarkers();
			});

			//	must triggr 'resize' because if more then 1 map on page only the first is shown after confirm
			var new_map = this.map;
			setTimeout( function(){
							google.maps.event.trigger(new_map, 'resize');
						}, 100 );
		},

		_setAutoZoom: function()
		{
			var bounds = new google.maps.LatLngBounds();

			for (var key in this.$data.marker)
			{
				bounds.extend( new google.maps.LatLng (this.$data.marker[key].lat , this.$data.marker[key].long) );
			}

			this.map.fitBounds(bounds);
		},

		_applyMapStyle: function()
		{
			var stylers = [], style = [], mapType, style_color = "";

			if(this.$data.hue != "") stylers.push({hue: this.$data.hue});
			if(this.$data.saturation != "") stylers.push({saturation: this.$data.saturation});

			if(stylers.length)
			{
				style = [{
					      featureType: "all",
					      elementType: "all",
					      stylers: stylers
					    }, {
					      featureType: "poi",
					      stylers: [
						  	{ visibility: "off" }
					      ]
					    }];


				if(this.$data.saturation == "fill")
				{
					style_color = this.$data.hue || "#242424";

					var c = style_color.substring(1);      // strip #
					var rgb = parseInt(c, 16);   // convert rrggbb to decimal
					var r = (rgb >> 16) & 0xff;  // extract red
					var g = (rgb >>  8) & 0xff;  // extract green
					var b = (rgb >>  0) & 0xff;  // extract blue

					var luma = 0.2126 * r + 0.7152 * g + 0.0722 * b; // per ITU-R BT.709
					var lightness = 1;
					var street_light = 2;

					if (luma > 60) {
					    lightness = -1;
					    street_light = 3;
					}
					if (luma > 220) {
					    lightness = -2;
					    street_light = -2;
					}

				style = [
{"featureType":"all","elementType":"all","stylers":[{"color":style_color},{"lightness":0}]},
{"featureType":"all","elementType":"labels.text.fill","stylers":[{"color":style_color},{"lightness":(25 * street_light)}]},
{"featureType":"all","elementType":"labels.text.stroke","stylers":[{"visibility":"on"},{"color":style_color},{"lightness":3}]},
{"featureType":"all","elementType":"labels.icon","stylers":[{"visibility":"off"}]},
{"featureType":"administrative","elementType":"geometry.fill","stylers":[{"color":style_color},{"lightness":30}]},
{"featureType":"administrative","elementType":"geometry.stroke","stylers":[{"color":style_color},{"lightness":30},{"weight":1.2}]},
{"featureType":"landscape","elementType":"geometry","stylers":[{visibility: 'simplified'},{"color":style_color},{"lightness":3}]},
{"featureType":"poi","elementType":"geometry","stylers":[{ "visibility": "off" }]},
{"featureType":"road.highway","elementType":"geometry.fill","stylers":[{"color":style_color},{"lightness":-3}]},
{"featureType":"road.highway","elementType":"geometry.stroke","stylers":[{"color":style_color},{"lightness":2},{"weight":0.2}]},
{"featureType":"road.arterial","elementType":"geometry","stylers":[{"color":style_color},{"lightness":-3}]},
{"featureType":"road.local","elementType":"geometry","stylers":[{"color":style_color},{"lightness":-3}]},
{"featureType":"transit","elementType":"geometry","stylers":[{"color":style_color},{"lightness":-3}]},
{"featureType":"water","elementType":"geometry","stylers":[{"color":style_color},{"lightness":-20}]}
						];
				}

				mapType = new google.maps.StyledMapType(style, { name:"av_map_style" });
				this.map.mapTypes.set('av_styled_map', mapType);
				this.map.setMapTypeId('av_styled_map');
			}
		},

		_addMarkers: function()
		{
			var _self = this;

			for( var key in this.$data.marker )
			{
				(function( key, _self )
				{
					setTimeout( function()
					{
							var marker = "",
								map = _self.map;

							if(!_self.$data.marker[key] || !_self.$data.marker[key].lat || !_self.$data.marker[key].long)
							{
								$.avia_utilities.log('Latitude or Longitude for single marker missing', 'map-error');
								return;
							}

							_self.$data.LatLng = new google.maps.LatLng(_self.$data.marker[key].lat, _self.$data.marker[key].long);

							var markerArgs = {
//									map,
									map: _self.map,
									flat: false,
									position: _self.$data.LatLng,
									animation: google.maps.Animation.BOUNCE,
									title: _self.$data.marker[key].address,
									optimized: false
								};

						    //set a custom marker image if available. also set the size and reduce the marker on retina size so its sharp
						    if(_self.$data.marker[key].icon && _self.$data.marker[key].imagesize)
						    {
						    	var size = _self.$data.marker[key].imagesize, half = "", full = "";

						    	if(_self.retina && size > 40) size = 40;			//retina downsize to at least half the px size
						    	half = new google.maps.Point(size / 2, size ) ; 	//used to position the marker
						    	full = new google.maps.Size(size , size ) ; 		//marker size
						    	markerArgs.icon = new google.maps.MarkerImage(_self.$data.marker[key].icon, null, null, half, full);
						    }

			        		marker = new google.maps.Marker(markerArgs);
//							marker = new google.maps.marker.AdvancedMarkerElement(markerArgs);

			        		setTimeout(function(){ marker.setAnimation(null); _self._infoWindow(_self.map, marker, _self.$data.marker[key]); },500);

		        	},200 * (parseInt(key,10) + 1));

		        }(key, _self));
    		}

			_self._show_close_icon();
		},

		//	fix that maps scroll to marker info on pageload since version > 3.45 - we hide close icon with CSS
		//	https://kriesi.at/support/topic/page-scrolls-to-google-maps-automatically-when-text-marker-is-shown/
		_show_close_icon: function()
		{
			var _self = this;

			setTimeout( function()
			{
				$('body').find('.gm-ui-hover-effect:not(.avia-show-gm-notice)').addClass('avia-show-gm-notice');
				_self._show_close_icon();
			}, 500 );

		},

		_infoWindow: function( map, marker, data)
		{
			var info = data.content;

			if( 'string' != typeof info )
			{
				return;
			}

			info = info.trim();

			if( info != '' )
			{
				var infowindow = new google.maps.InfoWindow({
					content: info
				});

				google.maps.event.addListener( marker, 'click', function()
				{
				    infowindow.open( { anchor: marker, map, shouldFocus: false } );
				});

				if( data.tooltip_display )
				{
					infowindow.open( { anchor: marker, map, shouldFocus: false } );
				}
			}
		}
    };

    //simple wrapper to call the api. makes sure that the api data is not applied twice
    $.fn.aviaMaps = function( options )
    {
    	return this.each(function()
    	{
    		var self = $.data( this, 'aviaMapsApi' );

    		if( ! self )
    		{
    			self = $.data( this, 'aviaMapsApi', new $.AviaMapsAPI( options, this ) );
    		}
    	});
    };


    // this function is executed once the api file is loaded
	window.aviaOnGoogleMapsLoaded = function()
	{
		$('body').trigger('av-google-maps-api-loaded');
		$.AviaMapsAPI.apiFiles.finished = true;
	};


	$('body').trigger('avia-google-maps-api-script-loaded');

})( jQuery );

