var GoogleMapManager = new function(){
	
	// Costants	
	var MARKERS_FOLDER_PATH = "/backend/images/google-map-icons/";
	var DEFAULT_MARKER_FILE_NAME = "default.png";
	var DEFAULT_MAP_ZOOM_FOR_SINGLE_MARKER = 14;
	
	var map = null;
	var geoCoder = null;
	var markerClusterer = null;
	
	var mapDivElement;
	var pathToGoogleMarkerIcons;
	var isAtLeastOneMarkerGeoCoded = false;
	var isMapRangeDefined = false;
	
	var addedMarkersBounds = new GLatLngBounds();
	var addedMarkers = {};
	var markersForCluster = [];
	
	var clusterIcon = "default.png";
	
	var contextPath = "";
	
	var defaultMapCoords = {
		x: 52.118312,
		y: 4.880676,
		zoom: 8
	};
	
	var clusterIconConfig = {
		width: 53,
		height: 52,
		urlPrefix: "/backend/images/google-map-cluster-icons/" 
	};
	
	var d = document;
	var self = this;
	
	this.cluster;
	
	this.init = function(range, contextPath_, clusterIcon_){
		if (GBrowserIsCompatible()) {
			mapDivElement = d.getElementById("map_canvas"); 
	 		mapDivElement.style.display = "block";
	 		
	        map = new GMap2(mapDivElement);
			geoCoder = new GClientGeocoder();
	        
	    	GEvent.addListener(map, "tilesloaded", function() {	    				 
				var o = d.getElementById("googleMapLoader");			
				if (o) {
					o.style.display = "none";		  						
				}
		    });
	
			map.addControl(new GSmallZoomControl());
			map.addControl(new GMapTypeControl());
			
			if (range){
				setDefinedRange(range);
			} else {
				map.setCenter(new GLatLng(defaultMapCoords.x, defaultMapCoords.y), defaultMapCoords.zoom);
			}
			
			if (contextPath_){
				contextPath = contextPath_;
			}
			
			if (clusterIcon_){
				clusterIcon = clusterIcon_;
			}
			
	 		map.enableScrollWheelZoom();
		}		
	};
	
	var setDefinedRange = function(range){
		isMapRangeDefined = true;
		range = range.replace("(","");
		range = range.replace(")","");
		range = range.replace(" ","");
		
		var params = range.split("&&");
		range = params[0];
		var rangeZoom = parseInt(params[1]);   				
		var coords =  range.split(",");
		var rangeMapCoords = new GLatLng( parseFloat(coords[0]), parseFloat(coords[1]));
	    map.setCenter(rangeMapCoords, rangeZoom);
	};
	
	var hideMap = function(){
		mapDivElement.style.display="none";
		var o = d.getElementById("googleMapLoader");			
		if(o) {
			o.style.display = "none";
		}
	};
	
	var showMap = function(){
		mapDivElement.style.display="block";
		var o = d.getElementById("googleMapLoader");			
		if(o) {
			o.style.display = "block";
		}
	};	
	
	var getMarkerIconPath = function(markerIcon){
		var iconImage = "";
		if (markerIcon.indexOf("/") == -1) {	
			if (!pathToGoogleMarkerIcons) {
			    if(contextPath){
			      iconImage += contextPath + MARKERS_FOLDER_PATH;
			    }else { 
			      iconImage = MARKERS_FOLDER_PATH;
			    }
			    pathToGoogleMarkerIcons = iconImage;
			}
			if (markerIcon) {
				iconImage = pathToGoogleMarkerIcons + markerIcon;
			} else {
				iconImage = pathToGoogleMarkerIcons + "default.png";
			}
		} else {
			iconImage = markerIcon;
		}	
	    return iconImage;
	};
	
	var trim = function(str){	
		return str.replace(/^\s+|\s+$/g,"");
	};
	
	var makeGIcon = function(markerIconPath){
		var iconImg = new GIcon(G_DEFAULT_ICON);
		iconImg.iconSize = new GSize(20, 34);			
		iconImg.image = markerIconPath;
		return iconImg;
	};
	
	var getMarkerPopupTextIfClustered = function(date, address, postcode, type, sort, link){
		var str = "<div class='markerPopup'>";
		if (date){
			str += date + " | ";
		}
		str += address  + " " + postcode + 
				"<br /><br />";
		if (type){
			str += type + ", "; 
		}
		if (sort){
			str +=  sort;	
		}
		
		if (type || sort){
			str += "<br /><br />";
		}
				
		str += "<a href = '" + link +"'>Naar detailspagina</a></div><br />";
		return str;
	};
	
	var makeClusterIconObj = function(){
		// Define custom cluster icon
		var clusterIconObj = new GIcon();
		clusterIconObj.image				= contextPath + clusterIconConfig.urlPrefix + clusterIcon;
		clusterIconObj.iconSize			= new GSize(27, 40);
		clusterIconObj.shadow				= contextPath + '/backend/images/new_shadow.png';
		clusterIconObj.shadowSize			= new GSize(40, 40);
		clusterIconObj.iconAnchor			= new GPoint(10, 30);
		clusterIconObj.infoWindowAnchor	= new GPoint(10, 8);
		
		return clusterIconObj;
	}
	
	var myClusterClick = function(args){
		markerClusterer.defaultClickAction=function(){
			map.setCenter(args.clusterMarker.getLatLng(), map.getBoundsZoomLevel(args.clusterMarker.clusterGroupBounds))
			delete markerClusterer.defaultClickAction;
		}		
		var html = '';	
		for (var i = 0; i < args.clusteredMarkers.length; i++){
			html += args.clusteredMarkers[i].html;
		}
		
		html = getFormattedHTML(html);
		html += "<br/><a href='#' class='clusterMeerLink' onclick='GoogleMapManager.cluster.defaultClickAction()'>Zoom in om meer bekendmakingen te bekijken  &rarr;</a>";
		
		args.clusterMarker.openInfoWindowHtml(html);
	}
	
	var refreshCluster = function(){
		var markers = []
		for (var i in addedMarkers){
			if (addedMarkers.hasOwnProperty(i)){
				markers.push(addedMarkers[i].marker);
			}
		}
		if (markerClusterer != null) {
          markerClusterer.removeMarkers();
        }
        
        var clusterIconObj = makeClusterIconObj();
        
        markerClusterer = new ClusterMarker(map, { markers: markers, clusterMarkerClick: myClusterClick, clusterMarkerTitle: " " } );
		markerClusterer.clusterMarkerIcon = clusterIconObj;
		if (!isMapRangeDefined){
			markerClusterer.fitMapToMarkers();
			map.setZoom(map.getZoom() - 1);
		} else {
			markerClusterer.refresh(false);
		}
		self.cluster = markerClusterer;
	};
	
	var addClickHandler = function(marker, html){
		GEvent.addListener(marker, "click", function() {
			marker.openInfoWindowHtml(getFormattedHTML(html));
		});
	};
	
	var getFormattedHTML = function(html){
		return "<div style='he\\ight /**/:auto; -height:170px; max-height:170px; width:370px; overflow:auto; margin:10px 5px 0 10px;'>" + html + "</div>";
	};
	
	this.showSimpleMarker = function(postcode, address, markerIcon){
		if (geoCoder) {
			if(postcode.length>6  && parseInt(postcode)){
				postcode = postcode.substring(0,6);
			}
				
			var searchString = "The Netherlands, " + (trim(address) ? address : postcode);
			if (postcode && postcode != "") {
				address = address ? ", " + address : "";
			}	 
			
			geoCoder.getLatLng(searchString, function(point) {
				if (point) {		
					isAtLeastOneMarkerGeoCoded = true;					
					map.setCenter(point, DEFAULT_MAP_ZOOM_FOR_SINGLE_MARKER);					
					var iconImg = makeGIcon(getMarkerIconPath(markerIcon));
					var marker = new GMarker(point, iconImg); 
					map.addOverlay(marker);
					GEvent.addListener(marker, "click", function() {
						marker.openInfoWindowHtml(postcode + "" + address);
					});
				}
				if (!isAtLeastOneMarkerGeoCoded){
					hideMap();
				}
			}); 
		}
	};

	this.showPermissionsOnMap = function(loc, title){
		if (geoCoder) {
			var locat = loc;
			if(loc.length>6  && parseInt(loc)){
				locat = loc.substring(0,6);
			}
				
			geoCoder.getLatLng("The Netherlands, " + locat + ", " + title, function(point) {
				if (!point) {
					mapDivElement.style.display="none";
				} else {
					map.setCenter(point, DEFAULT_MAP_ZOOM_FOR_SINGLE_MARKER);
					var marker = new GMarker(point);
					map.addOverlay(marker);
					GEvent.addListener(marker, "click", function() {
						marker.openInfoWindowHtml(title);
					});
				}
			});
		}
	}
	
	this.showAnnouncementItemWithCluster = function(postcode, address, date, title, link, type, sort, markerIcon, addressCoords){
		if (geoCoder) {
			var postcodeArray = postcode.split(";");
			var addressArray = address.split(";");
			var adressCoordsArray = addressCoords.split(";");
			
			for (var i=0; i<postcodeArray.length; i++){
				
				var address = trim(addressArray[i]);
				var postcode = postcodeArray[i];
				if(postcodeArray[i].length>6  && parseInt(postcodeArray[i])){
					postcode = postcodeArray[i].substring(0,6);
				}
				var searchString = "The Netherlands, " + (address ? address : postcode);
				var addressForOutput = addressArray[i].split(",")[1];
				if (!addressForOutput){
					addressForOutput = postcodeArray[i];
				}
				
				var displayMarker = function(postcode, address, point){
					var key = point.lat().toString() + point.lng().toString();
					address = address ? address + "," : "";
					
					if (!addedMarkers[key]){								
						var iconImg = makeGIcon(getMarkerIconPath(markerIcon));
    					var marker = new GMarker(point, iconImg);
						addedMarkersBounds.extend(point);
						
						addedMarkers[key] = {};
						addedMarkers[key].marker = marker;
						addedMarkers[key].markerText = getMarkerPopupTextIfClustered(date, address, postcode, type, sort, link);
						addClickHandler(marker, addedMarkers[key].markerText);
						
						addedMarkers[key].marker.html = addedMarkers[key].markerText; 
						
						if (!isMapRangeDefined){
							map.setZoom(map.getBoundsZoomLevel(addedMarkersBounds) - 1);
							map.setCenter(addedMarkersBounds.getCenter());
						}
					} else {						    
					    var marker = addedMarkers[key].marker;						    
						var iconImg = makeGIcon(getMarkerIconPath(markerIcon));    					  
    					//marker= new GMarker(marker.getLatLng(), iconImg);
							
    					
						addedMarkers[key].markerText += getMarkerPopupTextIfClustered(date, address, postcode, type, sort, link);
														
						GEvent.clearListeners(marker, "click"); 
						addClickHandler(marker, addedMarkers[key].markerText);								
						marker.html = addedMarkers[key].markerText;
					}
					refreshCluster();
				}
				
				var coords = trim(adressCoordsArray[i]);
				if (coords){
					coords = coords.split(",");
					displayMarker(postcode, address, new GLatLng(coords[1], coords[0]));
				} else {
					(function(postcode, address){
						geoCoder.getLatLng(searchString, function(point) {
							if (point) {
								displayMarker(postcode, address, point);
							}				
						});
					})(postcode, addressForOutput);
				}
			}
		}
	};
	
	var getMarkerPopupText = function(title, addressForOutput, postcode, type, sort, uri){
		var html = '<div class="markerPopup"><b>'+title+'</b>';
		html += '<br/><br/>' + addressForOutput + postcode + '<br/>';
		html += type;						
		if(sort != ""){
			html += ', '+sort;
		} 
		html += '<br/><br/><a href="'+uri+'">Meer informatie</a>';
		html += "</div><br/>";
		return html;
	};
	
	this.showItemOnMap = function (postcode, address, title, uri, type, sort, markerIcon, addressCoords){
		if (geoCoder) {
			if(postcode.length>6  && parseInt(postcode)){
				postcode = postcode.substring(0,6);
			}
			
			var searchString = "The Netherlands, " + (address ? address : postcode);
			var addressForOutput = address.split(",")[1] || "";			
			addressForOutput = addressForOutput ? addressForOutput + ", " : "";
			
			var displayMarker = function(postcode, address, point) {
				if (point) {
					isAtLeastOneMarkerGeoCoded = true;
					showMap();					
					var key = point.lat() + "_" + point.lng();
					var html = getMarkerPopupText(title, addressForOutput, postcode, type, sort, uri);
					
					var marker = null;
					
					if (!addedMarkers[key]){
						var iconImg = makeGIcon(getMarkerIconPath(markerIcon));
						marker = new GMarker(point, iconImg);
						
						addedMarkersBounds.extend(point);
						
						addedMarkers[key] = {};
						addedMarkers[key].marker = marker;
						addedMarkers[key].markerText = html;
						
						map.addOverlay(marker);
						
						map.setZoom(map.getBoundsZoomLevel(addedMarkersBounds));
						map.setCenter(addedMarkersBounds.getCenter());
					} else {
						marker = addedMarkers[key]; 
						marker.markerText += html;
														
						GEvent.clearInstanceListeners(marker); 
					}
					
					GEvent.addListener(marker, "mouseover", function() {
						var html = getFormattedHTML(addedMarkers[key].markerText);
						marker.openInfoWindowHtml(html);
					});
					GEvent.addListener(addedMarkers[key].marker, "click", function() {
						var html = getFormattedHTML(addedMarkers[key].markerText);
						marker.openInfoWindowHtml(html);
					});
				}				
			}				
			
			if (coords){
				var coords = trim(addressCoords);
				coords = coords.split(",");
				displayMarker(postcode, address, new GLatLng(coords[1], coords[0]));
			} else {
				(function(postcode, address){
					geoCoder.getLatLng(searchString, function(point) {
						if (point) {
							displayMarker(postcode, address, point);
						}
						if (!isAtLeastOneMarkerGeoCoded) {
							hideMap();
						}																	
					});
				})(postcode, addressForOutput);
			}			
		}	
	};
	
	this.showCompany = function(location,str,house,city,country, showAlways){
		if(location.length = 0) {
			return;
		}
		
		var query = location;
		
		if (str!="" && house!="" && city!=""){
			query = str + " " + house + ", " + location + ", " + city;
		}
		
		query = query + ", The Netherlands";
		
		if (geoCoder) {
			geoCoder.getLatLng(query, function(point) {
				if (!point) {
					if (!showAlways){
						document.getElementById("map_canvas").style.display="none";
					}
				} else {
					map.setCenter(point, 13);
					var marker = new GMarker(point);
					map.addOverlay(marker);
					marker.openInfoWindowHtml(str + " " + house + ", " + city + ", " + country);
				}
			});
		}
	}
}();