google.load("maps", "2");

var VDB = VDB || {};


VDB.map = new Class({
	/**
	 * Constructor function
	 * @param {Object} config Object literal with parameters for the map
	 * @param {Object} application The application that handles user interaction 
	 */
	initialize: function (config, application) {
		if (!GBrowserIsCompatible()) return false;
		this._application = application;
		this._config = config;
		this._state  = 'normal';
		this._markers = [];
		this._issuesFilter = [];
		this._issuesFilter['idea'] = false;
		this._issuesFilter['problem'] = false;
		VDB.map.handleViewPortChangeOff = false;
		this.count = 0;
		this._today = new Date();
		this._issuesToFilter = [];
		this._typesDescr = new Array(); 
		this._typesDescr['idea'] = 'Idee';
		this._typesDescr['problem'] = 'Probleem';
		this._pagetracker = false;
		this.insertionMode = 'normal';
		this.markerCacheManager = new MarkerCacheManager();
		this.viewPortChangeEvent = null;
		this.markerClusterer = null; 
		this._selectedMarkers = [];
		this._markerLookup = [];
                //this._previous_zoomlevel = null;
                this._isInitialZoomlevel = true;
		this_councilInfoTimer = null;
		this.clusterStyles = [[{
			height: 57,
			width: 57,
			opt_number: 1
      },
		{
			height: 59,
			width: 59,
			opt_number: 2
		},
		{
			height: 60,
			width: 60,
			opt_number: 3
		}]];
		// QUINCE - Constants for zoom levels
		this.COUNTRY_ZOOM_LEVEL = 11;
		this.COUNCIL_ZOOM_LEVEL = 14;
		this.NEIGHBOURHOOD_ZOOM_LEVEL = 16;			
	},

	/*
	* QUINCE
	* Sets the zoom level to country zoom level
	*/
	zoomToCountry: function(){
		this._map.clearOverlays();
		this._map.setZoom(this.COUNTRY_ZOOM_LEVEL);
	},
	/*
	* QUINCE
	* Sets the zoom level to the council zoom level
	* If center coords are given centers the map to this coordinates.
	* The center coordinates for the council can be passed as parameters
	*/
	zoomToCouncil: function(center){
		this._map.clearOverlays();
		if(!center){
			center = this._map.getCenter();
		}
		this._map.setCenter(center,this.COUNCIL_ZOOM_LEVEL);
	},
	/*
	* QUINCE
	* Sets the zoom level to the neihgbourhood zoom level
	* If center coords are given centers the map to this coordinates.
	* The center coordinates for the neihgbourhood can be passed as parameters
	*/
	zoomToNeighbourHood: function(center){
		this._map.clearOverlays();
		if(!center){
			center = this._map.getCenter();
		}
		this._map.setCenter(center,this.NEIGHBOURHOOD_ZOOM_LEVEL);
	},
	/*
	* QUINCE - 
	*/
	getZoomLevel: function(zoom_level){
		if(zoom_level >= this.COUNTRY_ZOOM_LEVEL && zoom_level <= this.NEIGHBOURHOOD_ZOOM_LEVEL){
			return zoom_level;
		} else if(zoom_level > this.NEIGHBOURHOOD_ZOOM_LEVEL){
			return this.NEIGHBOURHOOD_ZOOM_LEVEL
		} else if(zoom_level < this.COUNTRY_ZOOM_LEVEL){
			return this.COUNTRY_ZOOM_LEVEL
		}
	},
	/**
	 * Creates the map
	 * @param {Object} mapCanvas The DOM Element for the map
	 */
	startMap: function (mapCanvas, mapControls) {
		this._mapCanvas = mapCanvas;

		//make the actual map
		this._map = new GMap2(mapCanvas);
		G_PHYSICAL_MAP.getMinimumResolution = function () { return 11 }; 
		G_NORMAL_MAP.getMinimumResolution = function () { return 11 }; 
		G_SATELLITE_MAP.getMinimumResolution = function () { return 11 }; 
		G_HYBRID_MAP.getMinimumResolution = function () { return 11 }; 
		G_PHYSICAL_MAP.getMaximumResolution = function () { return 16 }; 
		G_NORMAL_MAP.getMaximumResolution = function () { return 16 }; 
		G_SATELLITE_MAP.getMaximumResolution = function () { return 16 }; 
		G_HYBRID_MAP.getMaximumResolution = function () { return 16 }; 
		
		//Center the map
		
		if (this._config.query && this._config.query.length > 0) {
			//If we had a query, it has priority
			this.trackEvent('Deeplink','Query',this._config.query)
			this.executeAddressSearch(this._config.query, false);
		} else if(this._config.lat && this._config.lon){
			//Else we go for direct lat long
			this._map.setCenter(new GLatLng(this._config.lat, this._config.lon),this.getZoomLevel(this._config.zoom));
		} else if(google.loader.ClientLocation){
			//Else we let google decide
			this._map.setCenter(new GLatLng(google.loader.ClientLocation.latitude, google.loader.ClientLocation.longitude),this.COUNTRY_ZOOM_LEVEL);
		} else {
			//Else we go hard coded for the center of Amsterdam
			this._map.setCenter(new GLatLng(52.3726647836, 4.89174842834),this.COUNTRY_ZOOM_LEVEL);
		}
		
		this._map.addControl(new GLargeMapControl());		
		this._map.addControl(new GMapTypeControl());
		this._map.addControl(new GOverviewMapControl());
		this._map.enableScrollWheelZoom();

		//move the map controls from the map_controls div into the map_canvas div
		var controls = mapControls.getChildren();
		var currentControl;

		for (var i=0; i<controls.length; i++) {
			currentControl = controls[i].dispose();
			this._mapCanvas.grab(currentControl);
		}

		$('widget-message').setStyle('width', $('widget-searchaddress').getWidth() - 12);

		mapControls.destroy();
		
		//Add listeners to listen for viewportchange
		if (!this._config.query || this._config.query == '')
			this.handleViewPortChange()
		
		//GEvent.addListener(this._map, "moveend", function(){ clearTimeout(this._intervalID); this._intervalID = setTimeout(this.handleViewPortChange.bind(this), 500)}.bind(this)); 
		//GEvent.addListener(this._map, "moveend", this.handleViewPortChange.bind(this));
		GEvent.addListener(this._map, "zoomend", this.handleViewPortChange.bind(this)); 
		GEvent.addListener(this._map, "dragend", this.handleViewPortChange.bind(this)); 
		GEvent.addListener(this._map, "zoomend", function(){ VDB.map.markerOpen = false; });
		
		//configure inital control settings
		this.initControls();
		
		//determine which state to show
		switch (this._config.state) {
			case 'info': //show the contents of an URL in a infopanel
			case 'message':
			case 'error':
				this.showMode(this._config.state, this._config);
			break;

			default:
//				if(!Cookie.read('skipwelcome') && !this._config.controls ) {
				if(!Cookie.read('skipwelcome') && (!this._config.controls || this._config.controls.welcome) ) {
					this.showMode('welcome', {url: '/welkom'});
				}
			break;
		}

		this.setMapSize();
	},
	/**
	 * Triggered when the viewPort changes
	 * Checks if data is loaded
	 * If data is not loaded it requests new data
	 */
	handleViewPortChange: function () {
		var pabel_info_display = $('panel-info').getStyle('display');
		if(this._map.getZoom() >= this.COUNTRY_ZOOM_LEVEL && this._map.getZoom() < this.COUNCIL_ZOOM_LEVEL && pabel_info_display != 'block'){
			if($('navigation')){$('widget-ticker-tape').empty();}
			this._map.clearOverlays();
			var viewport = this._map.getBounds();	
			this.loadCouncilList(viewport);
			if(this.ticker_tape){
				this.ticker_tape.stopScroll();
			}
			this._markerLookup = [];
                        this._isInitialZoomlevel = false;
			// QUINCE - Hide widgets
			$$('#widget-council-info').setStyle('display', 'none');
		} else if(this._map.getZoom() >= this.COUNCIL_ZOOM_LEVEL && this._map.getZoom() < this.NEIGHBOURHOOD_ZOOM_LEVEL && pabel_info_display != 'block'){
			if($('navigation')){$('widget-ticker-tape').empty();}
			this._map.clearOverlays();
			var viewport = this._map.getBounds();	
			this.loadNeighbourhoodList(viewport);
			this.loadCouncilInfo(viewport);
			if(this.ticker_tape){
				this.ticker_tape.stopScroll();
			}
			this._markerLookup = [];
                        this._isInitialZoomlevel = false;
			$$('#widget-council-info').setStyle('display', 'block');
		} else if(this._map.getZoom() == this.NEIGHBOURHOOD_ZOOM_LEVEL){
			//if(this._map.getZoom() != this._previous_zoomlevel)
			//	this._map.clearOverlays();
			var viewport = this._map.getBounds();
			this.requestDataPortion(viewport);	
			this.loadCouncilInfo(viewport);
			$$('#widget-council-info').setStyle('display', 'block');
		}
		//this._previous_zoomlevel = this._map.getZoom();
	},

	/**
	 * Takes bounds and adds a buffer perimeter to avoid excessive httprequest
	 */
	addBufferToViewPort: function (bounds) {
		//a square doubles in size if you add the lenght of a side to the mid 
		//hence the mid + (max - min) (length) is the new max
		var lattdiff = bounds.getNorthEast().lat() - bounds.getSouthWest().lat();
		var midlatt = bounds.getSouthWest().lat() + (lattdiff)/2;

		var longdiff = bounds.getNorthEast().lng() - bounds.getSouthWest().lng();
		var midlong = bounds.getSouthWest().lng() + (longdiff)/2;

		var maxlong = midlong + longdiff;
		var minlong = midlong - longdiff;
		var maxlatt = midlatt + lattdiff;
		var minlatt = midlatt - lattdiff;

		return new GLatLngBounds(new GLatLng(minlatt, minlong),new GLatLng(maxlatt, maxlong));
	},

	/**
	 * Gets the issues for given GLatLngBounds 
	 * 
	 */
	requestDataPortion: function (bounds) {
		if(this._map.getZoom() == this.NEIGHBOURHOOD_ZOOM_LEVEL){
			var args = "min_long=" + bounds.getSouthWest().lng() + "&min_lat=" + bounds.getSouthWest().lat() + "&max_long=" + bounds.getNorthEast().lng() + "&max_lat=" + bounds.getNorthEast().lat()  + "&from_date=" + (this._today - 90 * 24 * 60 * 60 * 1000);
			var issueRequest = new Request({
			url: '/api/issues',
			method: 'get',
			onSuccess: this.placeIssues.bind(this)
			}).send(args);
		}
	},
	
	/**
	*  Loads information of the council lying in the middle of the currentviewport
	*/
	loadCouncilInfo: function(bounds){
		//Gemeente info ophalen
		var args = "min_long=" + bounds.getSouthWest().lng() + "&min_lat=" + bounds.getSouthWest().lat() + "&max_long=" + bounds.getNorthEast().lng() + "&max_lat=" + bounds.getNorthEast().lat();		
		if($('widget-council-info')){
			if(this._map.getZoom() > 12){
				var issueRequest = new Request({
					url: '/api/councilinfo',
					method: 'get',
					onSuccess: this.showCouncilInfo.bind(this)
					}).send(args);
			}else{
				$('widget-council-info').setStyle('display', 'none');
			}
		}
	},	
	showCouncilInfo: function (councilJSON) {
		eval('var council = ' + councilJSON);
		if (council.id){
			$('widget-council-info').set('html','');
			if(council.logo){
				var logo_img=document.createElement("img");
				logo_img.setAttribute('src', council.logo);
				logo_img.setAttribute('alt', "Het wapen van " + council.name);
				logo_img.setAttribute('height', '64px');
				logo_img.setAttribute('width', '64px');			
				
				$('widget-council-info').grab(logo_img);
			}
			var councilDescription = new Element('div');
			
			var councilLink = new Element('h2');
			councilLink.grab(new Element('a',{'html': council.name, 'href': council.url, 'target': '_blank'}));
			//$('widget-council-info').grab(councilLink);			
			if(council.text){
				var councilText = new Element('span',{'html': council.text});
			}
			/*if(council.numbers){
				var councilNumbers = new Element('p',{'html': council.numbers});
			}*/
			councilDescription.grab(councilLink);
			councilDescription.grab(councilText);
			/*councilDescription.grab(councilNumbers);*/
			
			$('widget-council-info').grab(councilDescription);
			
			$('widget-council-info').setStyle('display', 'block');

		}else{
			$('widget-council-info').setStyle('display', 'none');
		}
	},
	
	/**
	* QUINCE
	* Loads list of the councils in the current viewport
	*/
	loadCouncilList: function(bounds){
		var args = "min_long=" + bounds.getSouthWest().lng() + "&min_lat=" + bounds.getSouthWest().lat() + "&max_long=" + bounds.getNorthEast().lng() + "&max_lat=" + bounds.getNorthEast().lat();		
		if(this._map.getZoom() >= this.COUNTRY_ZOOM_LEVEL && this._map.getZoom() < this.COUNCIL_ZOOM_LEVEL){
			var issueRequest = new Request({
				url: '/api/councillist',
				method: 'get',
				onSuccess: this.placeCouncilMarkers.bind(this)
				}).send(args);
		}
	},
	/**
	* QUINCE
	* Called on success for loadCouncilList function
	* places the council markers on the map
	*/	
	placeCouncilMarkers: function (councilJSON) {	
		this._map.clearOverlays();
		eval('var councils = ' + councilJSON);
		var councilCount = councils.length;
		
		var i = 0;
		for(i = 0 ; i < councilCount ; i++){
			var marker = new VDB.councilMarker(councils[i].latitude , councils[i].longitude , councils[i].name , this);
			marker.addToMap();
		}
	},
	
	/**
	* QUINCE
	* Loads list of the neighbourhoods in the current viewport
	*/
	loadNeighbourhoodList: function(bounds){
		var args = "min_long=" + bounds.getSouthWest().lng() + "&min_lat=" + bounds.getSouthWest().lat() + "&max_long=" + bounds.getNorthEast().lng() + "&max_lat=" + bounds.getNorthEast().lat();		
		if(this._map.getZoom() >= this.COUNCIL_ZOOM_LEVEL && this._map.getZoom() < this.NEIGHBOURHOOD_ZOOM_LEVEL){
			var issueRequest = new Request({
				url: '/api/neighborhoodlist',
				method: 'get',
				onSuccess: this.placeNeighbourhoodMarkers.bind(this)
				}).send(args);
		}
	},
	/**
	* QUINCE
	* Called on success for loadCouncilList function
	* places the council markers on the map
	*/	
	placeNeighbourhoodMarkers: function (neighbourhoodJSON) {	
		this._map.clearOverlays();
		eval('var neighbourhoods = ' + neighbourhoodJSON);
		var neighbourhoodCount = neighbourhoods.length;
		
		var i = 0;
		for(i = 0 ; i < neighbourhoodCount ; i++){
			var marker = new VDB.neighbourhoodMarker(neighbourhoods[i].latitude , neighbourhoods[i].longitude , neighbourhoods[i].name ,  this);
			marker.addToMap();
		}
	},

	/**
	 * Places the issues on the map
	 * @param {Array} issuesJSON An array containing all the markers to place on the map
	 */
	placeIssues: function (issuesJSON) {
		if(this.insertionMode == 'normal' && this._isInitialZoomlevel == false) {
			this._map.clearOverlays();
			this.clearIssues();
		}
                if(this._isInitialZoomlevel == true) {
                    this._isInitialZoomlevel = false;
                }
		eval('var issues = ' + issuesJSON);
		
		if(this.ticker_tape){
			this.ticker_tape.stopScroll();
		}
		
		// QUINCE - Init the ticker tape
		if($('navigation')){
	        $('widget-ticker-tape').empty();
			var ticker_wrapper = new Element('div');
			ticker_wrapper.inject($('widget-ticker-tape'));
			var issue_text = '';
			var issue_title = '';
			var issue_street = '';
			var issue_status = '';
			var issue_link = '';
		}
		
		for (var i=0; i<issues.length; i++) {	
			//set the loading message
			var msgTitle = 'Bezig...';
			var msgText  = 'Laden ' + (i+1).toString() +  ' van ' + issues.length.toString() + ' problemen en ideeën';
			this._application.setMessage(msgTitle, msgText, true);

			//create the marker
			/////// CHECK issue filter (nog in object zetten)
			if(this._issuesToFilter['idea'] == true && issues[i].type == 'idea') {
				issues[i]['hide'] = true;
			} 
			else if(this._issuesToFilter['problem'] == true && issues[i].type == 'problem') {
				issues[i]['hide'] = true;
			}
			else if(this._issuesToFilter['1'] == true && issues[i].category == '1') {
				issues[i]['hide'] = true;
			}
			else if(this._issuesToFilter['2'] == true && issues[i].category == '2') {
				issues[i]['hide'] = true;
			}
			else if(this._issuesToFilter['3'] == true && issues[i].category == '3') {
				issues[i]['hide'] = true;
			}
			else if(this._issuesToFilter['4'] == true && issues[i].category == '4') {
				issues[i]['hide'] = true;
			}
			else if(this._issuesToFilter['5'] == true && issues[i].category == '5') {
				issues[i]['hide'] = true;
			}
			else if(this._issuesToFilter['6'] == true && issues[i].category == '6') {
				issues[i]['hide'] = true;
			}
			else if(this._issuesToFilter['7'] == true && issues[i].category == '7') {
				issues[i]['hide'] = true;
			}
			else if(this._issuesToFilter['8'] == true && issues[i].category == '8') {
				issues[i]['hide'] = true;
			}
			else if(this._issuesToFilter['confirmed'] == true && issues[i].status == 'confirmed') {
				issues[i]['hide'] = true;
			}
			else if(this._issuesToFilter['open'] == true && issues[i].status == 'open') {
				issues[i]['hide'] = true;
			}
			else if(this._issuesToFilter['nosolution'] == true && issues[i].status == 'nosolution') {
				issues[i]['hide'] = true;
			}
			else if(this._issuesToFilter['closed'] == true && issues[i].status == 'closed') {
				issues[i]['hide'] = true;
			}
			else {
				issues[i]['hide'] = false;
			}
			///////
			
			this._issuesFilter.push(issues[i]);
			var marker = new VDB.marker(issues[i], false, this);
			this._markers.push(marker);
			

			//if we need to show a message about this issue, save a reference to the marker
			if (this._config.issue && this._config.issue == issues[i].id) {
				this._messageIssue = marker;
			}

			//add the marker to the map
			if(!issues[i]['hide'] && !this.issueExists(issues[i])){
				this.storeIssue(issues[i]);
				marker.addToMap();
			}
			
			// QUINCE - Fill ticker tape
			// create elements form the first 20 issues
			
			if(i < 20 && !issues[i]['hide'] && $('navigation')){
				issue_text = new Element('p');
				issue_title = new Element('span',{'class':'title'});
				issue_street = new Element('span',{'class':'street'});
				issue_status = new Element('span',{'class':'status'});
				issue_link = new Element('a',{'class':'issue-link'})
				
				// fill elements with data
				issue_title.appendText(issues[i].title);
				issue_street.appendText(' - ' + issues[i].street + ' ');
				issue_status.appendText(issues[i].status_description);
				issue_link.set('href','/melding/' + issues[i].id + '/' + issues[i].title);
				
				// add elements to the issue text element
				issue_title.inject(issue_link);
				issue_street.inject(issue_link);
				issue_status.inject(issue_link);
				
				issue_link.inject(issue_text);
				
				// add issue text to the ticker
				
				issue_text.inject(ticker_wrapper);
			}	
		}
		
		// QUINCE - Start ticker tape
		if($('navigation')){
			this.ticker_tape = new Marquoo($('widget-ticker-tape'),{speed:60,distance:2});
		}

	},

	/* issueExists is a helper function to get a high performance check if issues exist
	 *
	 */
	issueExists: function(issue){
		return(this._markerLookup[issue.id + ""] == 1);
	},

	/* store the marker in the array
	 * store the id in the lookup
	 */
	storeIssue: function(issue){
		this._markerLookup[issue.id + ""] = 1;		
	},

	/* clear all stored issues
         * 
	 */
	clearIssues: function(){
		this._markerLookup = [];		
	},
	
	/**
	 * Resizes the map holder element to make it fit in the design
	 */
	setMapSize: function () {
		//get the measurement of the <body> element
		var bodySize = VDB.utils.getBodySize();

		//make the map fit
		var mapHeight = $('navigation') ? bodySize.height - 185 -40 : bodySize.height - 12;
		var mapWidth  = $('maponly') ? bodySize.width - 12 : bodySize.width - 40;

		this._mapCanvas.setStyles({
			width: mapWidth,
			height: mapHeight
		});

		//if the GMap object exists, allow it to adjust to the resize.
		if (this._map)	this._map.checkResize();

		//if the info panel exists, resize it to fit the map 
		if ($('panel-info')) {
			if($('header')){
				headerheight = 220; 
			} else {
				headerheight = 61;
			}
			$('panel-info').setStyles({
				'height': bodySize.height - headerheight,
				'width': (bodySize.width - 50) / 2
			});

			if ($('panel-info').getElement('.panel-content'))
				$('panel-info').getElement('.panel-content').setStyle('height', bodySize.height - 246);

		}

		//if the welcome panel exists, resize it to fit the map
		if ($('panel-welcome')) {
			$('panel-welcome').setStyle('height', 'auto');
			$('panel-welcome').getElement('.panel-content').setStyle('height', 'auto');

			if ($('panel-welcome').getHeight() > bodySize.height - 205) {
				$('panel-welcome').setStyle('height', bodySize.height - 205);
				$('panel-welcome').getElement('.panel-content').setStyle('height', bodySize.height - 235);
			}

			var halfMapHeight     = Math.round(mapHeight / 2);
			var halfWelcomeHeight = Math.round($('panel-welcome').getHeight() /2);

			$('panel-welcome').setStyle('top', (halfMapHeight - halfWelcomeHeight).toInt());
		}

		//if the widget-categories exists check to see if it is to big for the map.
		//if so, resize it and show a scrollbar
		if ($('widget-categories')) {
			if (mapHeight - 149 < $('widget-categories').getHeight()) {
				$('widget-categories').setStyles({'height': mapHeight - 149, 'overflow': 'auto'});
			} else {
				$('widget-categories').setStyles({'height': 'auto', 'overflow': 'visible'});
			}
		}
	},


	/**
	 * Event handler for the address searchbar
	 */
	executeAddressSearch: function (address, showInfoWindow) {
		showInfoWindow = showInfoWindow ? true : false

		var geoCoder = new GClientGeocoder(VDB.utils.cache);

		if (address == '') {
			this._application.setMessage('', 'U heeft geen adres ingevoerd.', true);
			return;
		}
		
		if(this.addressException(address)){
			this._map.setCenter(this.addressException(address),this.getZoomLevel(this._config.zoom));                       
                        return;
		}
                	
		geoCoder.setBaseCountryCode('nl');
		this.trackEvent('Zoeken','Zoekopdracht',address)
		geoCoder.getLocations(address, (function (response) {
			this.handleAddressResult(response, false, showInfoWindow);
		}).bind(this));
	},
	
	addressException: function (address) {
		lookupTable = new Array();
		lookupTable['gilze']=new GLatLng(51.543986,4.939384);
		lookupTable['rijen']=new GLatLng(51.589016,4.919128);
		lookupTable['gilze rijen']=new GLatLng(51.565973,4.934578);
		lookupTable['gilze en rijen']=new GLatLng(51.565973,4.934578);
		lookupTable['gilze-rijen']=new GLatLng(51.565973,4.934578);
		return lookupTable[address.toLowerCase()];
	},

	/**
	 * Callback method for the address search
	 * @param {Object} response
	 */
	handleAddressResult: function (response, isRetry, showInfoWindow) {
		showInfoWindow = showInfoWindow ? true : false;
		if(response.Placemark){
			
			placemark = new PlacemarkHelper(response.Placemark[0]);
		} else {
			if(response.name) this.trackEvent('Zoeken','Onduidelijk',response.name);
			this._application.setMessage('Onduidelijk adres', 'Dit adres kon niet gevonden worden.', true);
			return;
		}
		
		//can we use this response?
		if(!placemark.CountryNameCode){
			if(response.name) this.trackEvent('Zoeken','Onduidelijk',response.name);
			this._application.setMessage('Onduidelijk adres', 'Dit adres kon niet gevonden worden.', true);
			return;
		}
		if (response.Status.code != 200 || placemark.CountryNameCode != 'NL') {
			if(response.name) this.trackEvent('Zoeken','Onduidelijk',response.name);
			this._application.setMessage('Onduidelijk adres', 'Dit adres kon niet gevonden worden.', true);
			return;
		}
		
		
		//get the lat/lng for the location
		var lat = placemark.coordinates[1] ;
		var lng = placemark.coordinates[0] ;
		var location = new GLatLng(lat, lng);
		
		//if the returned location is accurate enough, determine street and city
		if(placemark.LocalityName){
			var street   = placemark.ThoroughfareName;
			var city     = placemark.LocalityName;
		//if this is not a retry and the location is not accurate enough, try again with the lat/lng data
		} else if (!isRetry) {
			var geoCoder = new GClientGeocoder(VDB.utils.cache);
			geoCoder.setBaseCountryCode('.nl');
			geoCoder.getLocations(new GLatLng(lat, lng), (function (response) {
				this.handleAddressResult(response, true, showInfoWindow);
			}).bind(this));

			return;

		//if even after the retry the data is not accurate enough, give up
		} else {
			window.console.log('oeps');
			this._application.setMessage('Onduidelijk adres', 'Dit adres kon niet gevonden worden', true);
			return;
		}
		
		//center on the found location
		var zoom = this.COUNCIL_ZOOM_LEVEL;
		if(placemark.Accuracy != undefined && placemark.Accuracy > 4)
			zoom = this.NEIGHBOURHOOD_ZOOM_LEVEL;
		else if(placemark.Accuracy < 4)
			zoom = this.COUNTRY_ZOOM_LEVEL = 11;
		this._map.setCenter(location,zoom);
		this.handleViewPortChange();

		if (showInfoWindow) {
			//build the nodes for the infowindow
			var wrapper = new Element('div', {
				'class': 'infowindow'
			});
			var title = new Element('h2', {
				'text': 'Gevonden adres:'
			});
			
			var addrDescr = street != '' ? street + ', ' + city : city;
			var streetCity = new Element('p', {
				'text': addrDescr
			});
			
			this.trackEvent('Zoeken', 'Resultaat', addrDescr)
			
			//build the buttons to place issues
			var options = new Element('p');
			var newProblem = new Element('span', {
				'class': 'describe',
				'text': 'Plaats nieuw probleem'
			});
			var newIdea = new Element('span', {
				'class': 'describe',
				'text': 'Plaats nieuw idee'
			});
			
			//make a call to map::addIssue on click
			newProblem.addEvent('click', (function(){
				this._map.closeInfoWindow();
				this.addIssue(location, 'problem', response);
			}).bind(this));
			
			//make a call to map::addIssue on click
			newIdea.addEvent('click', (function(){
				this._map.closeInfoWindow();
				this.addIssue(location, 'idea', response);
			}).bind(this));
			
			//combine all the created nodes
			options.adopt(newProblem, new Element('br'), newIdea);
			wrapper.adopt(title, streetCity, options);
			
			//show the infowindow
			this._map.openInfoWindow(location, wrapper);
			
			//hide the message panel
			this._application.hideMessage();
			
			//if the welcome panel is open, destroy it and show the widgets
			if ($('panel-welcome')) {
				$('panel-welcome').destroy();
				
				$$('#widget-address').setStyle('display', 'block');
				this._application.widgetManager.setAddbtnsWidgetVisibility(true);
				this._application.widgetManager.setMessageWidgetVisibility($('widget-message').get('text') != '');
				
//				$$('#widget-address').setStyle('display', 'block');
				
//				if ($('widget-message').get('text') == '') $('widget-message').setStyle('display', 'none');
			}
		}
	},


	/**
	 * Adds a new issue to the map
	 * @param {Object} point The GLatLng object of the location
	 */
	addIssue: function (latLng, type, response) {
		if (this.latLngInCountry(response, 'NL')) {
			var options = {
				type: type,
				latitude: latLng.lat(),
				longitude: latLng.lng(),				
				showInfoWindow: true
			}
			
			var marker = new VDB.marker(options, true, this);
			marker.addToMap();

			this._application.hideMessage();
		} else {
			this._application.setMessage('Ongeldige locatie', 'Nieuwe ideeën en problemen zijn alleen in Nederland te plaatsen', true);
		}
	},


	/**
	 * checks a geocode response to see if the coordinates are in the given country
	 * @param {Object} response
	 */
	latLngInCountry: function(response, country) {
		placemark = new PlacemarkHelper(response.Placemark[0]);
		if (response.Status.code != 200 || placemark.CountryNameCode != country) {
			inCountry = false;
		} else {
			inCountry = true;
		}

		return inCountry;
	},

	/**
	 * Set the application in a certain mode (detailview, data insertion, etc)
	 */
	showMode: function (mode, config) {
		var config = config || this._config;

		// for both info and message modes
		if (mode == 'info' || mode == 'message') {
			$$('#widget-address').setStyle('display', 'block');
			this._application.widgetManager.setAddbtnsWidgetVisibility(true);
			this._application.widgetManager.setCategoriesWidgetVisibility(true);
			
			if ($('widget-message').get('text') != '') {
				this._application.widgetManager.setMessageWidgetVisibility(true);
//				$('widget-message').setStyle('display', 'block');
			}
		}

		//if a panel needs to be shown in relation to a marker (showing or inserting details)
		//position the map so that the marker is at Y: 50% and X: 25% in relation to the map canvas 
		if ((mode == 'info' && parseInt(config.issue) > 0) || mode == 'create') {
			var viewPortSpan = this._map.getBounds().toSpan();
			var lat = config.lat;
			var lng = config.lon + (viewPortSpan.lng() * 0.25);

			this._map.panTo(new GLatLng(lat, lng));
		}

		switch (mode) {
			case 'info': //show the info panel with the content of the url
				$('panel-info').empty();

				//create the upper close button
				$('panel-info').adopt(new Element('span', {'class': 'close', 'text': 'Sluiten', 'id': 'upper'}));

				//fill #panel-info with an iframe
				if (config.type == 'iframe') {
					$('panel-info').adopt(new Element('iframe', {'class': 'panel-content', 'frameborder': '0'}));
					$('panel-info').setStyle('display', 'block');
					$('panel-info').getElement('iframe').set('src', config.url);
					$('panel-info').getElement('iframe').setStyle('height', $('panel-info').getHeight() - 35);

				//fill #panel-info with a div
				} else {
					var content = new Element('div', {'class': 'panel-content'});
					$('panel-info').adopt(content);

					var pageRequest = new Request.HTML({'update': content}).get(config.url);
					$('panel-info').setStyle('display', 'block');

					this.setMapSize();
				}
			break;

			case 'create': //in between mode for showing the insertDetails page
				var params = new Hash(config).toQueryString();
				var formUrl = '/melding/toevoegen?' + params

				this.showMode('info', {type: 'iframe', url: formUrl});
			break;

			case 'message': //show a message regarding an issue to the user
				if (!this._messageIssue) {
					var infoWindow = new Element('div', {'class': 'infowindow', 'text': config.message});
					this._map.openInfoWindow(this._map.getCenter(), infoWindow);
				}
			break;

			case 'error':
				if (this._config.message) {
					var infoWindow = new Element('div', {'class': 'infowindow-error', 'text': this._config.message});
					this._map.openInfoWindow(this._map.getCenter(), infoWindow);
				}

			case 'welcome': //show the welcome window and set an cookie
				if (this._config.message && this._config.message != '') {
					break;
				}

				$$('#widget-address').setStyle('display', 'none');
				this._application.widgetManager.setAddbtnsWidgetVisibility(false);
				this._application.widgetManager.setMessageWidgetVisibility(false);
				this._application.widgetManager.setCategoriesWidgetVisibility(false);
				Cookie.write('skipwelcome', 'yes');

				//create the nodes
				var welcomeScreen = new Element('div', {'id': 'panel-welcome'});
				var upperCloseBtn = new Element('span', {'class': 'close', 'text': 'Sluiten', 'id': 'upper'});

				//add a behaviour to the close buttons
				var ref = this;
				$$(upperCloseBtn).addEvent('click', function () {
					this.getParent().destroy();
					$$('#widget-address').setStyle('display', 'block'); /*'#widget-categories', */
					ref._application.widgetManager.setAddbtnsWidgetVisibility(true);
					ref._application.widgetManager.setMessageWidgetVisibility($('widget-message').get('text') != '');

//					if ($('widget-message').get('text') == '')
//						$('widget-message').setStyle('display', 'none');
				});

				content = new Element('div', {'class': 'panel-content'}).setStyle('margin', '25px 0 0 0');

				welcomeScreen.adopt(upperCloseBtn, content);
				this._mapCanvas.adopt(welcomeScreen);

				welcomeScreenHtml = new Request.HTML({'update': content, onSuccess: this.welcomeUpdateHandler.bind(this)}).get('/welkom');
			break;
		}
	},


	/**
	 * Called after the contents of the welcome panel are loaded.
	 * Creates close buttons and sets the behaviour for the address search
	 */
	welcomeUpdateHandler: function () {
		this.setMapSize();

		$('searchaddress-welcome').addEvent('click', (function (e) {
			this.executeAddressSearch($('welcomeaddress').get('value'));
		}).bind(this));

		$('welcomeaddress').addEvent('keyup', (function (e) {
			if (e.key == 'enter')
				this.executeAddressSearch($('welcomeaddress').get('value'));
		}).bind(this));

		$('searchaddress-welcome').getParent('form').addEvent('submit', function (e) {
			e.stop();
		});

		var dummy = new Driebit.defaultValue($('welcomeaddress'));
	},

	/**
	 * 
	 * @param {Object} type
	 */
	setInsertionMode: function (type) {
		if (type == 'problem' || type == 'idea') {
			var geoCoder = new GClientGeocoder(VDB.utils.cache);
			var latLng   = map._map.getCenter();

			this.insertionMode = type;

			geoCoder.getLocations(latLng, function (response) {
				map.addIssue(latLng, type, response);
			});

			if (type == 'problem') {
				$('new-problem-btn').src = '/images/new_problem_active.gif';
				$('new-idea-btn').src = '/images/new_idea.gif';
			} else {
				$('new-problem-btn').src = '/images/new_problem.gif';
				$('new-idea-btn').src = '/images/new_idea_active.gif';
			}

		} else if (type == 'normal') {
			this.insertionMode = 'normal';
			$('new-idea-btn').src = '/images/new_idea.gif';
			$('new-problem-btn').src = '/images/new_problem.gif'
		}
	},

	/**
	 * Handler to show or hide different markers based on the checked checkboxes
	 */
	showCategories: function () {
		var mask;

		mask = new Element('div', {'class': 'mask'});
		$('widget-categories').adopt(mask);

		if (!$('ideas').checked) { 
			this._issuesToFilter['idea'] = true;
		} else {
			this._issuesToFilter['idea'] = false;
		}

		if (!$('problems').checked) {
			this._issuesToFilter['problem'] = true;
		} else {
			this._issuesToFilter['problem'] = false;
		}
		
		if (!$('category-1').checked) {
			this._issuesToFilter[1] = true;
		} else {
			this._issuesToFilter[1] = false;
		}
		if (!$('category-2').checked) {
			this._issuesToFilter[2] = true;
		} else {
			this._issuesToFilter[2] = false;
		}
		if (!$('category-3').checked) {
			this._issuesToFilter[3] = true;
		} else {
			this._issuesToFilter[3] = false;
		}
		if (!$('category-4').checked) {
			this._issuesToFilter[4] = true;
		} else {
			this._issuesToFilter[4] = false;
		}
		if (!$('category-5').checked) {
			this._issuesToFilter[5] = true;
		} else {
			this._issuesToFilter[5] = false;
		}
		if (!$('category-6').checked) {
			this._issuesToFilter[6] = true;
		} else {
			this._issuesToFilter[6] = false;
		}
		if (!$('category-7').checked) {
			this._issuesToFilter[7] = true;
		} else {
			this._issuesToFilter[7] = false;
		}
		if (!$('category-8').checked) {
			this._issuesToFilter[8] = true;
		} else {
			this._issuesToFilter[8] = false;
		}
		if (!$('open').checked) {
			this._issuesToFilter['open'] = true;
		} else {
			this._issuesToFilter['open'] = false;
		}

		if (!$('closed').checked) {
			this._issuesToFilter['closed'] = true;
		} else {
			this._issuesToFilter['closed'] = false;
		}
		
		if (!$('nosolution').checked) {
			this._issuesToFilter['nosolution'] = true;
		} else {
			this._issuesToFilter['nosolution'] = false;
		}
		

		mask.destroy();
		
		if(this._map.getZoom() == this.NEIGHBOURHOOD_ZOOM_LEVEL) {
			var viewport = this._map.getBounds();
			this._markerLookup = [];
			this._map.clearOverlays();
			this.requestDataPortion(viewport);	
			this.loadCouncilInfo(viewport);
		}
	},
	
	//Google analytics pagetrackker wrapper 
	setPagetracker: function (tracker) {
		this._pagetracker = tracker;
	},
	
	trackEvent: function(){
		if(this._pagetracker){
			//this._pagetracker._trackEvent.apply(this,arguments);
		}
	},
	initControls: function(){
		if(this._config.hide){
			for(var i=0;i< this._config.hide.length;i++){
				element = this._config.hide[i];
				$(element).checked =false;
				if(element == "ideas"){this._issuesToFilter['idea']=true;}
				if(element == "problems"){this._issuesToFilter['problem']=true;}
				if(element == "closed"){this._issuesToFilter['closed']=true;}
				if(element == "open"){this._issuesToFilter['open']=true;}
				if(element == "category-1"){this._issuesToFilter['1']=true;}
				if(element == "category-2"){this._issuesToFilter['2']=true;}
				if(element == "category-3"){this._issuesToFilter['3']=true;}
				if(element == "category-4"){this._issuesToFilter['4']=true;}
				if(element == "category-5"){this._issuesToFilter['5']=true;}
				if(element == "category-6"){this._issuesToFilter['6']=true;}
				if(element == "category-7"){this._issuesToFilter['7']=true;}
				if(element == "category-8"){this._issuesToFilter['8']=true;}	
			}
		}
	}
	
});

