var map;
var mapBounds;
var baseLayer;
var baseLayerMQ;

var layers = [];
var layersJson = [];
var markers = [];
var markerIds = [];
var searchIndex;
var markersInfo = [];

var control;

var geocodeService;

function mapInvalidateSize(){
	waitForFinalEvent(function(){
		helper = $('#heightHelper').position();
		mapWrapper = $('#mapWrapper').position();
		height = helper.top - mapWrapper.top;

		$( "#map" ).css('height', height + "px");
		map.invalidateSize();
	}, 500, "resize");
}

function resizeIcons(zoom = 15){
	if(zoom <= 16){
		$('.icon div').hide();
	} else {
		$('.icon div').show();
	}
}

function map_range(value, low1, high1, low2, high2) {
	return low2 + (high2 - low2) * (value - low1) / (high1 - low1);
}

var waitForFinalEvent = (function () {
	var timers = {};
	return function (callback, ms, uniqueId) {
		if (!uniqueId) {
			uniqueId = "Don't call this twice without a uniqueId";
		}
		if (timers[uniqueId]) {
			clearTimeout (timers[uniqueId]);
		}
		timers[uniqueId] = setTimeout(callback, ms);
	};
})();

function createMarker(feature, latlng, layerId, className, iconPath, zoom = 0){
	if(typeof feature.properties.name !== 'undefined' && feature.properties.name != ""){
		myHtml = "<img src='"+iconPath+"'><div>" + feature.properties.name + "</div>";
	} else {
		myHtml = "<img src='"+iconPath+"'>";
	}

	myIcon = new L.divIcon({
		className: className + ' icon',
		html: myHtml,
		popupAnchor:  [0, -16],
		iconSize: [1,1],
		iconAnchor: [0,0]
	});

	//markers[layerId] = [];
	markers[feature.properties.id] = L.marker(latlng, {
		icon: myIcon
	});

	return markers[feature.properties.id];
}

function getJsonBounds(json, id, x1, x2, y1, y2, idOnly = false){
	//swap values if wrong order
	x1t = x1;
	x2t = x2;
	y1t = y1;
	y2t = y2;

	if(x1t > x2t){
		x1 = x2t;
		x2 = x1t;
	}

	if(y1t > y2t){
		y1 = y2t;
		y2 = y1t;
	}

	var nJson = new Array();
	var markerIds = new Array();

	for (var key in json) {
	    // skip loop if the property is from prototype
	    if (!json.hasOwnProperty(key)) continue;

	    var obj = json[key];

	    if(Array.isArray(obj) && obj.length > 0){

	    	nJson = obj.filter(function(marker){
	    		if(marker.geometry.coordinates[0] >= y1 && marker.geometry.coordinates[0] <= y2){
					if(marker.geometry.coordinates[1] >= x1 && marker.geometry.coordinates[1] <= x2){
						return true;
					}
				} else {
					return false;
				}
	    	});
	    }
	}

	var newObject = new Object();

	newObject.type = "FeatureCollection";
	newObject.features = nJson;

	return nJson;
}

function refreshLayers(id, className, iconPath){
	var overlayLayers = control.getActiveOverlayLayers()
	var visibleLayers = [];
	for (var overlayId in overlayLayers) {
		visibleLayers.push(overlayLayers[overlayId].layer._leaflet_id);
	}

	layerId = layers[id]._leaflet_id;

	if(map.getZoom() >= 0){
		bounds = map.getBounds();

		var x2 = bounds.getNorth();
		var x1 = bounds.getSouth();
		var y1 = bounds.getWest();
		var y2 = bounds.getEast();

		xExdend = (x2 - x1)*0.1;
		yExdend = (y2 - y1)*0.1;

		x2 = x2 + xExdend;
		x1 = x1 - xExdend;
		y2 = y2 + yExdend;
		y1 = y1 - yExdend;

		if($.inArray(layerId, visibleLayers) > -1){
			var jsonString = '/map/'+id+'/'+map.getZoom()+'/'+x1+'/'+x2+'/'+y1+'/'+y2;
			firstRun = false;
			if(map.hasLayer(layers[id])){
				// Add this data to the jsonLayer
				json = layersJson[id];
				newJson = getJsonBounds(json, id, x1, x2, y1, y2);
				//markerIds = getJsonBounds(json, id, x1, x2, y1, y2, true);

		    	var currentMarkers = layers[id].getLayers();

				for (var key in newJson) {
				    // skip loop if the property is from prototype
				    if (!newJson.hasOwnProperty(key)) continue;

				    var f = newJson[key];

		    		//c = f.geometry.coordinates;
		    		var markerId = f.properties.id;

		    		existingMarkers = currentMarkers.filter(function(marker){
		    			// delete Marker if it isn't in the visible area
		    			if(marker._latlng.lat <= x1 || marker._latlng.lat >= x2 || marker._latlng.lng <= y1 || marker._latlng.lng >= y2){
	    					//layers[id].removeLayer(marker);
	    					deleteMarker(marker, id);
		    			}

		    			return marker.id == markerId;
		    		});

		    		if(existingMarkers.length == 0){
		    			latlng = L.latLng(f.geometry.coordinates[1], f.geometry.coordinates[0]);
		    			m = createMarker(f, latlng, id, className, iconPath, map.getZoom());
		    			m.id = markerId;
		    			if(f.properties.popupContent.length > 0){
		    				m.bindPopup("<h4>"+f.properties.name+"</h4>"+f.properties.popupContent);
		    			}

		    			layers[id].addLayer(m);
		    		}

				}

				var currentZoom = map.getZoom();
				resizeIcons(currentZoom);
			}
		}
	} else {
		if($.inArray(layerId, visibleLayers) > -1){
			bounds = map.getBounds();
			x2 = Math.ceil(bounds.getNorth()*500)/500;
			x1 = Math.floor(bounds.getSouth()*500)/500;
			y1 = Math.floor(bounds.getWest()*500)/500;
			y2 = Math.ceil(bounds.getEast()*500)/500;

			var jsonString = '/map/'+id+'/'+map.getZoom()+'/'+x1+'/'+x2+'/'+y1+'/'+y2;
			//firstRun = false;
			if(map.hasLayer(layers[id])){
				$.getJSON( jsonString, function(json){
					layers[id].clearLayers();

					for(k = 0; k < json.features.length; k++){
						f = json.features[k];

						c = f.geometry.coordinates;
			    		markerId = f.properties.id;

			    		latlng = L.latLng(f.geometry.coordinates[1], f.geometry.coordinates[0]);
			    		m = createMarker(f, latlng, id, className, iconPath, map.getZoom());

						layers[id].addLayer(m);
					}

					var currentZoom = map.getZoom();
					resizeIcons(currentZoom);
				});
			}
		}
	}
}

function deleteMarker(marker, id){
	layers[id].removeLayer(marker);
}

function initMap(){
	helper = $('#heightHelper').position();
	mapWrapper = $('#mapWrapper').position();
	height = helper.top - mapWrapper.top;

	$( "#map" ).css('height', height + "px");

	lat = 46.8;
	lng = 8.233333;

	mapBounds = new L.LatLngBounds(
		new L.LatLng(lat - 1.1, lng - 2.43),
		new L.LatLng(lat + 1.1, lng + 2.35));
	var mapMinZoom = 10;
	var mapMaxZoom = 19;

	baseLayer = L.tileLayer('https://map{s}.brienznet.ch/osm_tiles/{z}/{x}/{y}.png', {
		minZoom: mapMinZoom, maxZoom: mapMaxZoom+1,
		//bounds: mapBounds,
		zoomSnap: 0,
		zoomDelta: 0.25,
		detectRetina: true,
		attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap contributers</a>',opacity: 0.85
	});

	baseLayerMQ = MQ.satelliteLayer({
		minZoom: mapMinZoom, maxZoom: mapMaxZoom
	});
	if(enableGeoLocation){
		geocodeService = L.esri.Geocoding.geocodeService();
	}

	initLayers();


	L.Control.Search = L.Control.extend({
	    onAdd: function(map) {
	        var search = L.DomUtil.create('div');

	        //$(search).addClass("searchBar");
	        $(search).addClass("input-group searchBar");
	        $(search).css('max-width','400px');
	        var input = $("<input autocomplete='off' class='form-control' placeholder='Suchen...' type='search' name='search' />");
	        var addon = $("<span class='input-group-addon'><i class='fa fa-search'></i></span>");
	        var searchResults = $("<div id='searchResults'></div>");

	        $(addon).click(function(e){
	        	e.stopPropagation();
	        	showResultsOnMap(input.val());
	        });


	        $(input).focus(function(e){
	        	e.stopPropagation();
	        	showResultsOnMap(input.val());
	        });

	        // Suche während Eingabe
	        $(input).keyup(function(e){
	        	e.stopPropagation();
	        	showResultsOnMap(input.val());
	        })

	        $(search).mouseover(function(){
	        	map.dragging.disable();
	        	map.doubleClickZoom.disable();
	        	map.scrollWheelZoom.disable();
	        	map.keyboard.disable();
	        	//map.click.disable();
	        });

	        $(search).mouseout(function(){
	        	map.dragging.enable();
	        	map.doubleClickZoom.enable();
	        	map.scrollWheelZoom.enable();
	        	map.keyboard.enable();
	        	//map.click.enable();
	        });

	        $(search).append(input);
	        $(search).append(addon);
	        $(search).append(searchResults);

	        return search;
	    },

	    onRemove: function(map) {
	        // Nothing to do here
	    }
	});

	L.control.search = function(opts) {
	    return new L.Control.Search(opts);
	}

	L.control.search({ position: 'bottomleft' }).addTo(map);

	$( window ).resize(function() {
		waitForFinalEvent(function(){
			helper = $('#heightHelper').position();
			mapWrapper = $('#mapWrapper').position();
			height = helper.top - mapWrapper.top;

			$( "#map" ).css('height', height + "px");
			map.invalidateSize();
			console.log(height);
		}, 500, "resize");
	});
}

// shows the search result on the searchBar and makes results clickable
function showResultsOnMap(search){
	var results = showResults(search);

	if(results.length > 0){
		$("#searchResults").show();
	} else {
		$("#searchResults").hide();
	}

	$("#searchResults").css('height', (results.length*3.25+0.25)+"em");
	$("#searchResults").css('top', (results.length*-3.25-0.25)+"em");

	$("#searchResults").html("");
	for(i = 0; i < results.length; i++){
		r2 = results[i];
		var r = $("<p style='background:url("+results[i][2]+")'><span>"+results[i][0]+"</span> - "+cleanPopupContent(results[i][1])+"</p>");
		r.click({value: r2}, function(event){
			r2 = event.data.value;
			console.log(r2);
			map.flyTo([r2[3],r2[4]], 19,{
				animate: false
			});
		})
		$("#searchResults").append(r);
	}

	//console.log(results);
}

function showResults(search){
	result = searchIndex.search(search, {
		fields: {
	        name: {boost: 4},
	        popupContent: {boost: 2, bool: "AND"},
	        layer: {boost: 1},
	        group: {boost: 1}
	    },
	    bool: "AND",
	    expand: true
	});

	mar = [];
	maxResults = 5;

	if(result.length > 0){
		for(i = 0; i < result.length && i < maxResults; i++){
			mar.push(markersInfo[result[i].ref]);
		}
	}

	return mar;
}

function searchMarker(search){
	console.log(layersJson);

	for(key in layersJson){
		var layer = layersJson[key];

		find = layer.features.filter(function(marker){
			return marker.properties.name.toLowerCase().includes(search.toLowerCase());
		});

		if(find.length > 0){
			return find;
			latlng = new L.latLng(find[0].geometry.coordinates[1], find[0].geometry.coordinates[0]);
			console.log(latlng);
			return latlng;
		}

	}

	return false;
}

function cleanPopupContent(content){
	//content = JSON.stringify(content);
	content = content.replace(/<br \/>/gi, ", ");
	content = content.replace(/<a href.*\/a>/gi, "");
	content = content.replace(/,,/gi, "");
	content = content.replace(/, $/gi, "");
	return content;
}