var mijnMarkerBestaat;			// Controle om te zien of de "Mijn locatie"-marker al bestaat.
//var markerText;				// Wordt normaal niet meer gebruikt.
var myCoords;					// De coordinaten van de gebruiker, [0] is de Latitude en [1] is de Longitude.
var infoWindow;					// De textballon op de Google Maps, deze wordt steeds aangepast per Mouseover-event.
var adressenlijst;				// De adressenlijst voor Shopping.php.
var adresTo;					// De eindbestemming waar de gebruiker naartoe wenst te gaan.
var noGPSCoords = 99999999;		// Een globale variabele die gebruikt wordt in Shopping.php voor elke handelaar waar geen GPS coordinaten van gekend zijn in de
								// Admin. Het hoge nummer wordt gebruikt zodat, bij het sorteren van de dichtste naar verste handelaar, deze handelaars zonder
								// enige GPS helemaal op het einde van de lijst komt te staan.
var LANG;						// De Javascriptversie van de PHP-variabele $LANG. Dit is voor de vertaling naar het Frans of omgekeerd.

// Dit wordt gebruikt voor shopping.php
function startLocating(adressen, lang) {
	//alert("Bezig met zoeken.");
	if (mijnMarkerBestaat == null) mijnMarkerBestaat = false;
	adresTo = null;
	LANG = lang;
	adressenlijst = adressen.slice(0);
	tryGeolocation();
}
// Dit is voor de handelaarwebsites
function startRoutebeschrijving(lat, lon, lang) {
	if (mijnMarkerBestaat == null) mijnMarkerBestaat = false;
	adressenlijst = null;
	LANG = lang;
	adresTo = new google.maps.LatLng(lat, lon);
	tryGeolocation();
}
// Deze methode toont de animatie die getoond wordt terwijl de geolocatie gebeurt
function toonWachtAnimatie() {
	if (document.getElementById('mijnLoc1') == null) return;
	imageText = " Bezig met het zoeken van uw locatie. Even geduld...";
	imageText_fr = " Occup&eacute; de la recherche pour votre position. Patientez s'il vous plait...";
	var image = "<img src=\"/images/mobile/waiting.gif\" alt=\"" + "\" />";
	var locText = image + (LANG == 2? imageText_fr: imageText);
	var color = "#000000";
	
	var myLoc1 = document.getElementById('mijnLoc1');
	myLoc1.innerHTML = locText;
	myLoc1.style.color = color;
	
	if (document.getElementById('mijnLoc2') != null) {
		var myLoc2 = document.getElementById('mijnLoc2');
		myLoc2.innerHTML = locText;
		myLoc2.style.color = color;
	}
}
// Deze functie start het geolocating en bepaald op welke manier dit moet gebeuren volgens browser. Dit houdt ook het gedeelte van Google Gears in.
function tryGeolocation() {
	if(adresTo != null && myCoords != null) {
		maakBeschrijving();
		return;
	} else if (myCoords != null) {
		calculateDistance();
		return;
	}
	toonWachtAnimatie();
	// FIREFOX / GOOGLE CHROME
	// Zie ook: http://www.browsergeolocation.com/#browser-gelocation-support voor meer info over OPERA en SAFARI
	if (navigator.geolocation) {
	  navigator.geolocation.getCurrentPosition(positionSuccess, positionError);
 	// Als Google Gears niet geinstalleerd is...
	} else if (!window.google || !google.gears) {
		//var welcomeMsg = "Om de zoekfunctie te gebruiken heeft uw browser de hulp nodig van Google Gears.";
		var welcomeMsg = "To be able to use the Searchfunction you have to install Google Gears."; 
		location.href = "http://gears.google.com/?action=install&message="+welcomeMsg+"&return="+window.location.href;
	// IE
	} else if((typeof google != "undefined") && (typeof google.gears != "undefined")){
		var geo = google.gears.factory.create('beta.geolocation');
		// De IE callbackfunctie die een resultaat weergeeft
		function updatePosition(position) {
			var location = new google.maps.LatLng(position.latitude, position.longitude);
			myCoords = new Array(location.lat(), location.lng());
			if(adresTo != null) {
				maakBeschrijving();
			} else {
				calculateDistance();
			}
		}
		function handleError(error) {
			alert(error.message);
		}
		geo.getCurrentPosition(updatePosition, handleError);
	} else {
  		positionError(-1);
	}
}
// De callbackfunctie voor browsers die niet werken via Google Gears zoals IE doet. Deze wordt gestart wanneer updatePosition() op een fout eindigt.
function positionError(err) {
	var msg;
	switch(err.code) {
	  case err.UNKNOWN_ERROR:
	    msg = "Unable to find your location";
	    break;
	  case err.PERMISSION_DENIED:
	    msg = "Permission denied in finding your location";
	    break;
	  case err.POSITION_UNAVAILABLE:
	    msg = "Your location is currently unknown";
	    break;
	  case err.BREAK:
	    msg = "Attempt to find location took too long";
	    break;
	  default:
	    msg = "Location detection not supported in browser";
	}
	document.getElementById('mijnLoc1').innerHTML = "<b>" + msg + "</b>";
	document.getElementById('mijnLoc1').style.color = "#FF0000";
	
	if (document.getElementById('mijnLoc2') != null) {
		document.getElementById('mijnLoc2').innerHTML = "<b>" + msg + "</b>";
		document.getElementById('mijnLoc2').style.color = "#FF0000";
	}
}
// De callbackfunctie voor browsers die niet werken via Google Gears zoals IE doet. Deze wordt gestart wanneer updatePosition() succesvol eindigt.
function positionSuccess(positionFrom) {
	var coords = positionFrom.coords || positionFrom.coordinate || positionFrom;
	var tmp = coords.latitude + ". " + coords.longitude;
	myCoords = new Array(coords.latitude, coords.longitude);
	if(adresTo != null) {
		maakBeschrijving();
	} else {
		calculateDistance();
	}
}
/*
function contains(array, item) {
	for (var i = 0, I = array.length; i < I; ++i) {
		if (array[i] == item) return true;
	}
	return false;
}*/
// De "Verander mijn locatie"-functie die gebruikt wordt om uw locatie te veranderen.
// adresloc is hier de textbox waar de gebruiker zijn huidige adres intypt.
function changeMyLoc() {
	var mijnadres = document.getElementById("adresloc").value;
	if(mijnadres) {
		myCoords[0] = mijnadres;
		maakBeschrijving();
	}
}
// Routebeschrijving voor op de handdetail.php pagina. Deze wordt op verschillende manieren gebruikt. Indien de coordinaten van de gebruiker's locatie al gekend zijn dan wordt er een volledige routebeschrijving gedaan, wanneer deze parameters niet meegegeven worden dan zal deze functie enkel de locatie van de meegegeven Lat en Lon tonen op Google Maps.
function maakBeschrijving(lat, lon, lang) {
	if(lat && lon) {
		adresTo = new google.maps.LatLng(lat, lon);
		LANG = lang;
	}
	// Alles is omgezet van Google Maps V2 naar Google Maps V3
	// isNaN() controleert of de parameter GEEN nummer is. Returns true of false.
	if (myCoords && !isNaN(myCoords[0])) {
		var latLngFrom = new google.maps.LatLng(myCoords[0], myCoords[1]);
	} else if (myCoords) {
		var latLngFrom = myCoords[0];
	}

	// Dit gedeelte wordt altijd gebruikt zowel als de gebruiker's locatie geweten is of niet geweten is.
	var myOptions = {
		center: adresTo,
		zoom: 13,
		mapTypeId: google.maps.MapTypeId.ROADMAP,
		scrollwheel: false,
		mapTypeControl: true,
		mapTypeControlOptions: { style: google.maps.MapTypeControlStyle.DROPDOWN_MENU }
	}
	map = new google.maps.Map(document.getElementById("map"), myOptions);
	// Dit is de routebeschrijving.
	// myCoords[0]: Dit is de Latitude (Lengtegraad) van de gebruiker's locatie.
	//				Indien maakBeschrijving() opgeroepen werdt vanuit changeMyLoc() dan is dit een adresstring zoals: "Grote Markt 1, 1000 BE".
	// myCoords[1]: Dit is de Longitude (Breedtegraad) van de gebruiker's locatie.
	if (myCoords) {
		var directionsService = new google.maps.DirectionsService();
		var directionsRenderer = new google.maps.DirectionsRenderer();
		
		directionsRenderer.setMap(map);    
		directionsRenderer.setPanel(document.getElementById('directions'));
		document.getElementById('directions').innerHTML = "";
		var request = {
			origin: latLngFrom.toString(), 
			destination: adresTo.toString(),
			travelMode: google.maps.DirectionsTravelMode.DRIVING,
			unitSystem: google.maps.DirectionsUnitSystem.METRIC,
			provideRouteAlternatives: true
		};
		directionsService.route(request, function(result, status) {
			if (status == google.maps.DirectionsStatus.OK) {
				directionsRenderer.setDirections(result);
				geocodeMijnLoc();
				// Clear de errorparagraaf.
				if (document.getElementById("errorloc") != null) {
					document.getElementById("errorloc").innerHTML = "";
				}
			} else {
				if (document.getElementById("errorloc") != null) {
					document.getElementById("errorloc").innerHTML = "Dit is een errormessage.";
				} else {
					alert('Error: ' + status);
				}
			}
		});
		// Clear de HTML van mijnloc1.
		if (document.getElementById('mijnLoc1') != null) {
			document.getElementById('mijnLoc1').innerHTML = "";
		}
		// Wanneer de routebeschrijving klaar is dan wordt de invoerfunctie tevoorschijn gezet.
		if (document.getElementById("veranderloc"))  {
			var veranderdiv = document.getElementById("veranderloc");
			veranderdiv.setAttribute("style", "display:inline");
		}
	// Als er geen routebeschrijving gedaan werdt dan wordt een Marker geplaatst van de handelaar in kwestie.
	} else {
		mijnMarker = new google.maps.Marker({ position: adresTo });
		mijnMarker.setMap(map);
	}
}
// De hoofdfunctie voor Shopping.php. Hier wordt de afstand van de gebruiker naar elke handelaar uitgerekend, de handelaarslijst 
function calculateDistance() {
	// adressenlijst[key][0] Handelaarsnaam, 
	// adressenlijst[key][1] Url,
	// adressenlijst[key][2] Latitude,
	// adressenlijst[key][3] Longitude
	try {
		var glatlng1 = new google.maps.LatLng(myCoords[0], myCoords[1]);
		if (adressenlijst != null) {
			for(var i in adressenlijst) {
				if (adressenlijst[i][2] != "null" && adressenlijst[i][3] != "null") {
					var glatlng2 = new google.maps.LatLng(adressenlijst[i][2], adressenlijst[i][3]);
					var miledistance = distVincenty(glatlng1.lat(), glatlng1.lng(),glatlng2.lat(), glatlng2.lng());
					// kmdistance
					adressenlijst[i][5] = (miledistance / 1000).toFixed(1);
				} else {
					adressenlijst[i][5] = noGPSCoords;
				}
			}
			// Custom sorteerfunctie die de array 'adressenlijst' sorteert volgens het 2e veld (in dit geval de afstand tussen de gebruiker en de shop)	
			// x - y betekent hier dat er oplopend (groot naar klein) gesorteerd wordt	 
			adressenlijst.sort(function(a,b) {
				x = a[5];
				y = b[5];
				return x - y;
			});
			teller = 0;
			// Breidt de lijst uit op de website met de kilometers en de link naar een routebeschrijving
			ezLijst = document.getElementById('gevondenhandelaars').childNodes;
			for (var i in ezLijst) {
				if (ezLijst[i].nodeType == 1) {
					kilometers = ""; 
					if (adressenlijst[teller][5] == noGPSCoords) {
						kilometers = "N/A";
					} else {
						kilometers = adressenlijst[teller][5] + "km";
					}
					url = "handdetail.php?handid=" + adressenlijst[teller][4] + "&prodid=" + gup("prodid") + "&lat=" + myCoords[0] + "&lon=" + myCoords[1];
					if (kilometers == "N/A") {
						ezLijst[i].innerHTML = adressenlijst[teller][1] + " (" + kilometers + ")";
					} else {
						ezLijst[i].innerHTML = adressenlijst[teller][1] + " (<a href=\"" + url + "\" class=\"red-modline\" >op " + kilometers + "</a>)";
					}
					teller++;
				}
			}
		} else {
			return;
		}
		var icon = "http://maps.google.com/mapfiles/ms/micons/green.png";
		var shadow = "http://maps.google.com/mapfiles/ms/micons/msmarker.shadow.png";
		if (!mijnMarkerBestaat) {
			//var dichtsteMarker = new google.maps.LatLng(adressenlijst[0][2], adressenlijst[0][3]);
		   	myLocationMarker(glatlng1, icon, shadow);
	   	}
	   	veranderHTML(icon);
	}
	catch (error) {
		alert(error);
	}
}
// Cre�ert de 'mijn locatie'-marker
function myLocationMarker(point, icon, shadow, dichtsteMarker) {
	
	var myShadow = new google.maps.MarkerImage(shadow,
		null,
		null,
		new google.maps.Point(16, 32)
	);

	var mijnMarker = new google.maps.Marker({
   		draggable: true,
   		position: point,
		icon: icon,
		shadow: myShadow,
		zIndex: 9000
	});
	mijnMarker.setMap(map);
	infoWindow.close();
	var bounds = new google.maps.LatLngBounds();
	bounds.extend(point);
	//bounds.extend(dichtsteMarker);
	// Stelt de zoom in op de 5 dichtstbijzijnde winkels
	for (var i = 0; i < 5; i++) {
		if (i < adressenlijst.length && adressenlijst[i][5] != noGPSCoords) {
			var huidigeMarker = new google.maps.LatLng(adressenlijst[i][2], adressenlijst[i][3]);
			bounds.extend(huidigeMarker);
		}
	}
	map.fitBounds(bounds);
   	mijnMarkerBestaat = true;
	// EVENTS	
	google.maps.event.addListener(mijnMarker, "mouseover", function() {
		contentText    = "<div><b>" + "U bevindt zich hier" + "</b><br><hr>" + "Klopt dit niet? Verplaats mij naar uw exacte locatie."    + "</div>";
		contentText_fr = "<div><b>" + "Vous �tes ici" 		+ "</b><br><hr>" + "Ce n'est pas vrai? D�placez-moi � votre position exacte." + "</div>";
		window_content = (LANG == 2? contentText_fr: contentText);
		infoWindow.setContent(window_content);
		infoWindow.open(map, mijnMarker);
	});
	google.maps.event.addListener(mijnMarker, "dragstart", function() {
		infoWindow.close();
	});
	google.maps.event.addListener(mijnMarker, "dragend", function() {
		// Deze regels zijn omslachtig omdat this.getLatLng().toString().lat() wel werkt 
		// maar er is een error als ik beide coordinaten wil opvragen en doorgeven. Daardoor
		// deze omslachtige wijze van programmeren.
		var tmp = this.getPosition().toString();
		tmp= tmp.replace(" ","");
		tmp= tmp.replace("(","");
		tmp= tmp.replace(")","");
		latLon = tmp.split(",");
		alterMyLocation(latLon[0], latLon[1]);
	});
}

function alterMyLocation(lat, lon){
	myCoords[0] = lat;
	myCoords[1] = lon;
	calculateDistance();
}

function veranderHTML(icon) {
	var innerHtmlText = "<b>Uw locatie:</b> ";
	var innerHtmlText_fr = "<b>Votre position:</b>"
	var myLoc1 = document.getElementById('mijnLoc1');
	myLoc1.innerHTML = "<br />";
	var img = document.createElement("img");
	img.setAttribute("src", icon);
	img.setAttribute("style", "float: left;");
	myLoc1.appendChild(img);
	myLoc1.innerHTML += (LANG == 2? innerHtmlText_fr: innerHtmlText);
	
	if (document.getElementById('mijnLoc2') != null) {
		var myLoc2 = document.getElementById('mijnLoc2');
		myLoc2.innerHTML = "<br />";
		var img2 = document.createElement("img");
		img2.setAttribute("src", icon);
		img2.setAttribute("style", "float: left;");
		myLoc2.appendChild(img2);
		myLoc2.innerHTML += (LANG == 2? innerHtmlText_fr: innerHtmlText);
	}
	
	locationCorrTxt = "<br /><i>Klopt dit niet? U kan dit corrigeren met de groene marker op de kaart onderaan deze pagina.</i>"
	locationCorrTxt_fr = "<br /><i>Ce n'est pas vrai? Vous pouvez corriger cela avec le marqueur vert sur la carte au bas de cette page.</i>"
	geocodeMijnLoc((LANG == 2? locationCorrTxt_fr: locationCorrTxt));
}
// Met deze functie kan je een adres op zoeken aan de hand van coordinaten. Deze functie doet ook de HTML/CSS veranderingen in shopping.php en handdetail.php van
// Elektrozine.be. 
function geocodeMijnLoc(tekst) {
	// Google Maps V3 Geocoding
	// Documentatie op: http://code.google.com/intl/nl/apis/maps/documentation/v3/services.html
	if (myCoords[0] && myCoords[1]) {
		var myLoc1 = document.getElementById('mijnLoc1');
		if (document.getElementById('mijnLoc2') != null) {
			var myLoc2 = document.getElementById('mijnLoc2');
		}
		if (myCoords) {
			var latlng = new google.maps.LatLng(myCoords[0], myCoords[1]);
		}
		var geocoder = new google.maps.Geocoder();
		
		if (!isNaN(myCoords[0])) {
			geocoder.geocode( { 'latLng' : latlng}, function(results, status) {
				if (status == google.maps.GeocoderStatus.OK) {
					var mijnAdres = results[0].formatted_address; // bijv.: results[0].formatted_address: "275-291 Bedford Ave, Brooklyn, NY 11211, USA"
					if (tekst != undefined) myLoc1.innerHTML += mijnAdres + tekst;
						else document.getElementById('adresloc').value = mijnAdres;
					if (document.getElementById('mijnLoc2') != null) {
						myLoc2.innerHTML += mijnAdres + tekst;
					}
				} else {
					alert("Geocode was not successful for the following reason: " + status);
					document.getElementById('errorloc').value = "Error 1";
				}
			});
		// Als myCoords[0] gelijk is aan een string dan wordt deze geocode uitgevoerd (zie handdetail.php van Elektrozine.be)
		} else if (isNaN(myCoords[0])) {
			geocoder.geocode( { 'address' : myCoords[0].toString()}, function(results, status) {
				if (status == google.maps.GeocoderStatus.OK) {
					var mijnAdres = results[0].formatted_address; // bijv.: results[0].formatted_address: "275-291 Bedford Ave, Brooklyn, NY 11211, USA"
					if (document.getElementById('adresloc') != null) {
						document.getElementById('adresloc').value = mijnAdres;
					}
				} else {
					alert("Geocode was not successful for the following reason: " + status);
					document.getElementById('errorloc').value = "Error 1";
				}
			});
		}
	} // END IF (myCoords[0] && myCoords[1])
}

function getDirections(handid, prodid) {
	redirect(("handdetail.php?handid=" + handid + "&prodid=") + prodid, myCoords[0], myCoords[1]);
}

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
/* Vincenty Inverse Solution of Geodesics on the Ellipsoid (c) Chris Veness 2002-2010             */
/*                                                                                                */
/* from: Vincenty inverse formula - T Vincenty, "Direct and Inverse Solutions of Geodesics on the */
/*       Ellipsoid with application of nested equations", Survey Review, vol XXII no 176, 1975    */
/*       http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf                                             */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */

/**
 * Calculates geodetic distance between two points specified by latitude/longitude using 
 * Vincenty inverse formula for ellipsoids
 *
 * @param   {Number} lat1, lon1: first point in decimal degrees
 * @param   {Number} lat2, lon2: second point in decimal degrees
 * @returns (Number} distance in metres between points
 */
function distVincenty(lat1, lon1, lat2, lon2) {
  var a = 6378137, b = 6356752.3142,  f = 1/298.257223563;  // WGS-84 ellipsoid params
  var L = (lon2-lon1).toRad();
  var U1 = Math.atan((1-f) * Math.tan(lat1.toRad()));
  var U2 = Math.atan((1-f) * Math.tan(lat2.toRad()));
  var sinU1 = Math.sin(U1), cosU1 = Math.cos(U1);
  var sinU2 = Math.sin(U2), cosU2 = Math.cos(U2);
  
  var lambda = L, lambdaP, iterLimit = 100;
  do {
    var sinLambda = Math.sin(lambda), cosLambda = Math.cos(lambda);
    var sinSigma = Math.sqrt((cosU2*sinLambda) * (cosU2*sinLambda) + 
      (cosU1*sinU2-sinU1*cosU2*cosLambda) * (cosU1*sinU2-sinU1*cosU2*cosLambda));
    if (sinSigma==0) return 0;  // co-incident points
    var cosSigma = sinU1*sinU2 + cosU1*cosU2*cosLambda;
    var sigma = Math.atan2(sinSigma, cosSigma);
    var sinAlpha = cosU1 * cosU2 * sinLambda / sinSigma;
    var cosSqAlpha = 1 - sinAlpha*sinAlpha;
    var cos2SigmaM = cosSigma - 2*sinU1*sinU2/cosSqAlpha;
    if (isNaN(cos2SigmaM)) cos2SigmaM = 0;  // equatorial line: cosSqAlpha=0 (�6)
    var C = f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha));
    lambdaP = lambda;
    lambda = L + (1-C) * f * sinAlpha *
      (sigma + C*sinSigma*(cos2SigmaM+C*cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)));
  } while (Math.abs(lambda-lambdaP) > 1e-12 && --iterLimit>0);

  if (iterLimit==0) return NaN  // formula failed to converge

  var uSq = cosSqAlpha * (a*a - b*b) / (b*b);
  var A = 1 + uSq/16384*(4096+uSq*(-768+uSq*(320-175*uSq)));
  var B = uSq/1024 * (256+uSq*(-128+uSq*(74-47*uSq)));
  var deltaSigma = B*sinSigma*(cos2SigmaM+B/4*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)-
    B/6*cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM)));
  var s = b*A*(sigma-deltaSigma);
  
  s = s.toFixed(3); // round to 1mm precision
  return s;
}
/** extend Number object with methods for converting degrees/radians */
Number.prototype.toRad = function() {  // convert degrees to radians
  return this * Math.PI / 180;
}

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
