function MapApp (userSettings) {
	//TODO
		// AUTOMATISCH CENTREREN OP POI BIJ ZOOMEN VAN CITYLEVEL NAAR STREETLEVEL
		// PROVINCE CONTROLS INBRENGEN
	
	var settings = $.extend({
		canvas: $("div#mapCanvas")[0],
		dataSource:"mapAppData.php",
		totalContainer:"span#total",
		txt: {
			txtMeerinfo: "Meer info",
			txtPrijs: "Prijs",
			txtHierzoomen: "Zoom in",
			txtSluit: "Sluiten",
			txtBevat: "bevat",
			txtResultaten: "resultaten",
			txtLaden:"Bezig met laden..."
		},
		onComplete:function() {}
	}, userSettings ? userSettings: {});
	var json;
	var activeView;
	var activeCities = new Object();
	var cityMarkers = new Array();
	var poiMarkers = new Array();
	var preloader = new PreLoader();
	var filters = "";
	var zoomLevel;
	var infoWindow = new InfoWindow();
	var minZoom = 13;
	var maxZoom = 19;
	var totalPoints = 0;
	var startup = true;
	var firstLoad = true;
	
	this.map;
	var mapApp = this;

	init();

	//PUBLIC METHODS
	this.setFilters = function(_filters) {
		filters = _filters;
		filterMarkers();
	}
	this.getFilters = function () {
		return filters;	
	}
	this.getCityPsOI = function(_cName) {
		var ret = 0;
		var c = getCityBycName(_cName);
		return c == false ? 0: c.getPsOI();
	}
	this.setFocusCity = function(city) {
		var c = getCityBycName(city);
		focusMap(new GLatLng(c.lat(),c.lng()),15);
	}
	//PRIVATE METHODS
	function focusMap(p, z) {
		this.map.setCenter(p, z);
	}
	function getCityBycName (name) {
		var city = false;
		$.each(cityMarkers, function(i, value) {
			if (value.getCName() == name) {
				city = value;
				return false;
			}
		});
		return city;
	}
	function init() {
		
		$("body").bind("infoWindowZoomRequest", function(e) {
			var level = e.zoomTarget;

			if (level == "relative") {
				map.setCenter(e.zoomPoint, map.getZoom());
				$("a#mapAppIn").click();
			}
			else if (level == "city") {
				map.setCenter(e.zoomPoint, 15);
			}
			else if (level == "street") {
				map.setCenter(e.zoomPoint, 17);
			}
				
		});
		
		this.map = new GMap2(settings.canvas);
		this.map.setCenter(new GLatLng(51.22298583214561, 4.412598609924316), 16);
		this.map.disableDoubleClickZoom();
		this.map.enableContinuousZoom();
		
		activeCities.alpha = new Array();
		activeCities.zip = new Array();
		
		initMapControls();
		
		GEvent.addListener(this.map, "zoomend", function() {
			infoWindow.hideOverlay();									 
			correctMarking();
		});
		GEvent.addListener(this.map, "moveend", function() {
			correctMarking();	
		});
		GEvent.addListener(this.map, "movestart", function() {
			infoWindow.hideOverlay();
		});		
		getPsOI();
	}
	function initMapControls() {
		$("a#mapAppUit,a#mapAppIn").bind("click", mapZoomHandler);
		$("a#mapAppGem,a#mapAppStr").bind("click", mapZoomToHandler);
		
		if ($.browser.msie && $.browser.version == "6.0") {
			map.setMapType(G_HYBRID_MAP);
			$("div.viewControls a[title=sat], div.viewControls a[title=map]").hide();
			$("div#appWrapper").before("<div class='ie6Error'>Uw browser versie is verouderd, dit verhindert u om ten volle te gebruik te maken van deze website. En kan uw surfsnelheid sterk beinvloeden. <a href='http://www.microsoft.com/belux/nl/windows/internet-explorer/worldwide-sites.aspx'>Klik hier om te updaten naar de laatste versie van uw favoriete browser.</a></div>");
		}
		else {
			$("div.viewControls a").bind("click", mapTypeHandler);
		}
	}
	function mapZoomToHandler(e) {
		if (!firstLoad) {
			if ($(e.target).attr("id") === "mapAppGem") {
				map.setZoom(minZoom);
			}
			else if ($(e.target).attr("id") === "mapAppStr") {
				map.setZoom(13);
			}
		}
		else {
			firstLoad = false;	
		}
		return false;
	}
	function mapZoomHandler(event) {
		
		if ($(event.currentTarget).attr("id") === "mapAppUit") {
			zoomLevel--;
		}
		else if ($(event.currentTarget).attr("id") === "mapAppIn") {
			zoomLevel++;
		}
		zoomLevel = zoomLevel>maxZoom? maxZoom: zoomLevel;
		zoomLevel = zoomLevel<minZoom? minZoom: zoomLevel;
		map.setZoom(zoomLevel);
		return false;
	}
	function mapTypeHandler(event) {
		var mapT = $(event.currentTarget).attr("title");
		switch(mapT) {
			case "sat":
				map.setMapType(G_HYBRID_MAP);
				break;
			case "map":
				map.setMapType(G_NORMAL_MAP);
				break;
			default:
				break;
		}
		return false;
	}
	function getPsOI() {
		preloader.showPreloader();
		$.get(settings.dataSource, {"operation":"VASTGOED"},
				function(data, status) {
					createMarkers(data);
			}, "json");	
	}
	function correctMarking() {
		zoomLevel = this.map.getZoom();
		if (zoomLevel >= 12 ) {
			activeView = "street";
		}
		else if (zoomLevel < 12 && zoomLevel > 9) {
			activeView = "city";
		}
		else if (zoomLevel <= 9) {
			activeView = "city";
		}
		showMarkers();
	}
	this.zoomOnPoint = function (name) {
		$.each(poiMarkers, function(i, value) {
			if (value.getName() == name) {
				map.setCenter(new GLatLng(value.lat(), value.lng()), 17);
			}
		});	
	}
	function showMarkers() {
		
		var bounds = this.map.getBounds();
		var sw = bounds.getSouthWest();
		var ne = bounds.getNorthEast();
		var tm = 0;
		
		if (activeView === "street") {
			$.each(cityMarkers, function(i, value){
				value.kill();
			});
			$.each(poiMarkers, function(i, value) {
				var min = sw.lng();
				var max = ne.lng();
				var num = value.lng();
				var minL = sw.lat();
				var maxL = ne.lat();
				var numL = value.lat();				
				if (!(min > num || max < num) && !(minL > numL || maxL < numL) && !value.getIgnore()) {
					value.show();
				}
				else {
					value.kill();
				}
			});
		}
		else if (activeView === "city") {
			$.each(poiMarkers, function(i, value){
				value.kill();
			});
			$.each(cityMarkers, function(i, value) {
				var min = sw.lng();
				var max = ne.lng();
				var num = value.lng();
				var minL = sw.lat();
				var maxL = ne.lat();
				var numL = value.lat();				
				if (!(min > num || max < num) && !(minL > numL || maxL < numL) && !value.getIgnore()) {
					value.show();
				}
				else {
					value.kill();
				}
			});
		}
		if (startup) {	
			startup = false;
			$(settings.totalContainer).html(poiMarkers.length);
			settings.onComplete();
		}
		
		preloader.hidePreloader();
		showAdress();
	}
	function filterMarkers () {
		var fd = 0;
		infoWindow.setTypes(filters.types);
		//infoWindow.hideOverlay();
		
		$.each(poiMarkers, function(i, value) {
			var ignore = true;
			
			for (var x=0; x<filters.types.length; x++) {
				if ($.inArray(String(filters.types[x]), value.types) !== -1) {
					fd++;
					ignore = false;
					break;
					//value.setIgnore(false);
					
				}
				else {
					ignore = true;
					//value.setIgnore(true);
				}
			}
			value.setIgnore(ignore);
		});
		$("a#mapAppGem").click();
		resetCityMarkers();
	}
	function showAdress() {
		$("ul#adressen").hide();
		$("ul#adressen li").remove();
		$.each(poiMarkers, function(i, value) {
			if (!value.getIgnore() && parseInt(value.types[0])<9990) {
				$("ul#adressen").append("<li name='"+ value.getName() +"'>"+ value.adres +"</li>").find("li").bind("click", function() {
					infoWindow.showOverlay(value.getHTML(), value.getPoint(), "street");
					mapApp.zoomOnPoint($(this).attr("name"));
					return false;
				}).css("cursor", "pointer");
			}
		});
		$("ul#adressen").show();
	}
	function resetCityMarkers() {
		totalPoints = 0;
		$.each(cityMarkers, function(i, value) {
			var name = value.getName();
			var count = 0;
			$.each(poiMarkers, function(j, val){
				if (val.parentName == name && val.getIgnore() == false && val.lat() && val.lng()) {	
					count++;
				}
			});
			if (count > 0) {
				value.setPsOI(count);
				value.setIgnore(false);
			}
			else {
				value.setIgnore(true);
			}
			//getCityvals(name);
		});
		
		//reset total
		var i = 0;
		var ic = 0;
		$.each(poiMarkers, function(j, val){
			if (!val.getIgnore() && val.lat() && val.lng()) {
				totalPoints++;
			}
		});
		
		$(settings.totalContainer).html(totalPoints);
		showMarkers();
	}

	function createMarkers(json) {
		var mapke = this.map;
		$.each(json, function(name, value) {
							  
			//alle city's met succes op de kaart zetten
			//alle psoi's binnen de city's op de kaart zetten
			//vervolgens showMarkers() aanroepen -> binnen showmarkers afhankelijk van de activeview alle citymarkers of psoimarkers tonen met coordinaten binnen de viewport
			var pc = 0;
			var city = value.cName;
			if (value.vastgoed !== undefined && value.succes) {
				var PsOICount = value.vastgoed.length;
				
				$.each(value.vastgoed, function(nam, val) {
					
					var lat = val.lat;
					var lng = val.lng;
					var psoiHtml = val.props.html;
					
					if (lat && lng) {
						pc++;
						poiMarkers.push(new POIMarker(lat, lng, mapke, psoiHtml, lat + lng, val.props.type, infoWindow));
						$.each(val.props, function(i, vali){
							//alle props instellen
							
							poiMarkers[poiMarkers.length - 1][i] = vali;
						});
						poiMarkers[poiMarkers.length - 1].parentName = name;
					}
				});
				var cityHtml = "<p class=\"caps\"><strong>"+ value.cName +"<br />"+ settings.txt.txtBevat +" "+ pc +" "+ settings.txt.txtResultaten +"</p>";
				var cm = new CityMarker(value.lat, value.lng, mapke, cityHtml, name, pc, value.cName, infoWindow);
				cm.setTxtObj(settings.txt);
				cityMarkers.push(cm);
			}
		});//each
		correctMarking();
		
	}
}
