$.fileMaps = {
	/**
	 * Variable to store map
	 */
	map: null,
	geoCoder: null,
	geoDir: null,
	reversegeocoder: null,
	
	// Variables for navigation (routeplanner)	
    gdir: null,
    addressMarker: null,
    gencoder: null,

	/**
	 * Variables to store overlay data
	 */
	overlays: null,
	selectedOverlay: null,
	clickedOverlay: null,
	currentOverlay: null,
	hoverOverlayIndex: -1,
	enablePhotosByZoomLevel: false,
	bounds: null,

	/**
	* Begin and End of rote
	*/
	addressStart: null,
	addressEnd: null,
	
	/**
	 * Array with zoomlevels
	 */
	zoomLevels: {
		country: 13,
		province: 8,
		community: 11,
		town: 13
	},


	/**
	 * Array with colors
	 */
	colors: {
		normal: "#f00",
		hover: "#0f0",
		select: "#00f"
	},


	/**
	 * Opacity of overlays
	 */
	opacity: 0.37,


	/**
	 * Variable to store markers
	 */
	markers: new Array(),

	/**
	 * Used to keep track of open infowindows
	 */
	openInfoWindow: null,


	/**
	 * Initialize the plaatsMaps object and load the Google map
	 */
	init: function() {
		// Check if Google maps object exists
		if(typeof GMap2 == 'undefined') {
			alert('GoogleMaps is not loaded!');
			return false;
		}
		// Check if browser is compatible
		if (!GBrowserIsCompatible()) {
			alert('Browser not capable of showing GoogleMaps!');
			return false;
		}

		// Load Google map
		this.map = new GMap2(document.getElementById("gmap"));
		this.map.addMapType(G_PHYSICAL_MAP); 

	
		// Set the center of the map to the Netherlands and show it at a decent zoom level
		var centerLat = $.cookie('centerLat');
		var centerLng = $.cookie('centerLng');
    	var zoom = Number($.cookie('zoomLevel'));
    	var point = new GLatLng(centerLat, centerLng);
    	if(centerLat && centerLng && zoom) {
    		this.map.setCenter(point, zoom, G_PHYSICAL_MAP);
    	} else {
			this.map.setCenter(new GLatLng(52.21, 5.3), 9, G_PHYSICAL_MAP);
    	}
		
		$.fileMaps.bounds = new GLatLngBounds();
		   		
		// Disable dragging of map
		this.map.disableDragging();

		// Bind the unload function
		$(document).bind("unload", function() {
			GUnload();
		});
	},


	/**
	 * Change map type
	 */
	setMapType: function(mapType) {
		if (mapType == 'normal') {
			this.map.setMapType(G_NORMAL_MAP);
		}
		else if (mapType == 'satellite') {
			this.map.setMapType(G_SATELLITE_MAP);
		}
	},


	/**
	 * Enable map controls (disabled by default)
	 */
	enableControls: function() {
		// Enable continuous and scrollwheel zoom
		this.map.enableContinuousZoom();
		this.map.enableScrollWheelZoom();

		// Enable dragging of map
		this.map.enableDragging();

  	// Add a large zoom and position controller
		this.map.addControl(new GLargeMapControl());
	},

	
	/**
	 * Center the map on a location
	 */
	centerOnLocation: function(locationName, locationType) {

		// Determine the zoom level using the location type
		var zoomLevel = (locationType == '') ? this.zoomLevels.country : this.zoomLevels[locationType];

		// Load the geoCoder to get the coordinates based on a location
		if($.fileMaps.geoCoder == null) {
			$.fileMaps.geoCoder = new GClientGeocoder();
		}
		if ($.fileMaps.geoCoder) {
			// Get latitude and longitude using a location
			$.fileMaps.geoCoder.getLatLng(locationName + ', Nederland', function(point) {
				if (point) {
					// Set map zoom and pan to the location
					$.fileMaps.map.setZoom(zoomLevel);
					$.fileMaps.map.panTo(point);
				}
			});
		}
	},


	/**
	 * Center the map on a point
	 */
	centerOnPoint: function(point, locationType) {

		// Determine the zoom level using the location type
		var zoomLevel = (locationType == '') ? this.zoomLevels.country : this.zoomLevels[locationType];

		// Set map zoom and pan to the location
		$.fileMaps.map.setZoom(zoomLevel);
		$.fileMaps.map.panTo(point);

		if ($.fileMaps.enablePhotosByZoomLevel) {
			// Handle changes in the zoom-level
			GEvent.addListener($.fileMaps.map, 'moveend', $.fileMaps.retrievePhotoMarkers);
		}
	},

	/**
	 * Create icon used as marker
	 */
	createSmallIcon: function() {
		var icon = new GIcon();
		icon.image            = '/images/icons/trafficjam.png';
		icon.shadow           = '/images/icons/trafficjam_shadow.png';
		icon.iconSize         = new GSize(32, 32);
		icon.shadowSize       = new GSize(32, 32);
		icon.iconAnchor       = new GPoint(16, 16);
		icon.infoWindowAnchor = new GPoint(16, 16);

		return icon;
	},
	
	createBigIcon: function() {
		var icon = new GIcon();
		icon.image            = '/images/icons/trafficjam.png';
		icon.shadow           = '/images/icons/trafficjam_shadow.png';
		icon.iconSize         = new GSize(64, 64);
		icon.shadowSize       = new GSize(64, 64);
		icon.iconAnchor       = new GPoint(32, 32);
		icon.infoWindowAnchor = new GPoint(32, 32);

		return icon;
	},


	/**
	* Looks for a point by given address
	*/
	geocode: function(address, marker_name, mouseover){
		if($.fileMaps.geoCoder == null) {
			$.fileMaps.geoCoder = new GClientGeocoder();
		}
		if ($.fileMaps.geoCoder) {
	    	$.fileMaps.geoCoder.getLatLng(address, function(point){
	    		if(point) {
		    		var smallIcon = $.fileMaps.createSmallIcon();
		    		var bigIcon = $.fileMaps.createBigIcon();
		    		// Set marker
					$.fileMaps.markers[marker_name] = {
						name: marker_name,
						point: point,
						markerSmall: new GMarker(point, smallIcon),
						markerBig: new GMarker(point, bigIcon)
					};
					
					$.fileMaps.map.addOverlay($.fileMaps.markers[marker_name].markerSmall);
					$.fileMaps.map.addOverlay($.fileMaps.markers[marker_name].markerBig);
					if(mouseover) {
						$.fileMaps.markers[marker_name].markerBig.hide();
						
						GEvent.addListener($.fileMaps.markers[marker_name].markerSmall, "mouseover", function() {
							$('#' + marker_name).addClass("zebraHover");
							$.fileMaps.markers[marker_name].markerBig.show();
						});
						
						GEvent.addListener($.fileMaps.markers[marker_name].markerBig, "mouseout", function() {
							$('#' + marker_name).removeClass("zebraHover");
							$.fileMaps.markers[marker_name].markerBig.hide();	
						});
					}
					else {
						$.fileMaps.centerOnPoint(point,'community');
					}
	    		}
	    	})
  		}
	},
	
	/**
	 * Create a marker on the map
	 */
	createMarker: function(address, name) {
		$('#' + name).fadeIn('slow', function(){$.fileMaps.geocode(address, name, true)});
		$('#' + name).bind('mouseover', function() {
			$('#' + name).addClass("zebraHover");
			if($.fileMaps.markers[name]) {
				$.fileMaps.markers[name].markerBig.show();
			}	
		});
		
		$('#' + name).bind('mouseout', function() {
			$('#' + name).removeClass("zebraHover");
			if($.fileMaps.markers[name]) {
				$.fileMaps.markers[name].markerBig.hide();
			}
		});
	},
	
	createBigMarker: function(address, name, locale) {
		$('#' + name).fadeIn('slow', function(){$.fileMaps.geocode(address, name, false)});
	},
	
	setDirections: function(fromAddress, toAddress, locale) {
	    $.fileMaps.addressStart = fromAddress;
	    $.fileMaps.addressEnd = toAddress;
		$.fileMaps.enableControls();
	    if($.fileMaps.geoDir == null) {
	 		$.fileMaps.geoDir = new GDirections($.fileMaps.map, document.getElementById("directions"));
	    }
	 	GEvent.addListener($.fileMaps.geoDir, 'error', function() {
	 		alert('Adres niet bekend.');
	 	});	
      	$.fileMaps.geoDir.load("from: " + fromAddress + " to: " + toAddress,
                { "locale": locale });
        $('#print').show();
    },
    
    /*
    * Plot a new polyline and post it so its added to the database
    * then draw the polyline on the map
    */
    createPoly: function(trafficjamId, fromAddress, toAddress, locale) {
		var gdir = new GDirections();
	    	    
	    if($.fileMaps.gencoder == null) {
	 		$.fileMaps.gencoder = new PolylineEncoder();
	    }
	  
        GEvent.addListener(gdir, "load", function()
        {
            var poly = gdir.getPolyline();
            var points = [];
            
            for (var i=0; i<poly.getVertexCount(); i++) {
          		points.push(poly.getVertex(i));
        	}
        	
        	if(points.length > 0) { 
            	var encoded = $.fileMaps.gencoder.dpEncode(points);
				$.fileMaps.drawEncodedPolyline(encoded.encodedPoints, encoded.encodedLevels);
				$.post("/file/addPolyline", { id: trafficjamId, points: encoded.encodedPoints, levels: encoded.encodedLevels } );
				//alert(encoded.encodedPoints);
        	}
			
        });
        
        GEvent.addListener(gdir, "error", function()
        {
   			//alert(gdir.getStatus().code);
        });
		gdir.loadFromWaypoints([fromAddress, toAddress], {getPolyline:true});
    },

    /*
    * Open a window with printable version of the google map
    */   
    printRoute: function() {
    	if($.fileMaps.geoDir == null) {
			return false;
		}
		var route = $.fileMaps.geoDir.getRoute(0);
		var beginLatLong = route.getStep(0).getLatLng(); 
		var endLatLong = route.getEndLatLng();

    	var url = 'http://maps.google.nl/maps?f=d&saddr=' + $.fileMaps.addressStart + ',Nederland&daddr=' + $.fileMaps.addressEnd + ',Nederland&hl=nl&geocode=&mra=ls&sll=' + beginLatLong.toUrlValue() +'&sspn=' + endLatLong.toUrlValue() + '&ie=UTF8&z=12&pw=2';
    	window.open(url);
    },
    
    /*
    * Draw a polyline on the map
    */
    drawEncodedPolyline: function(encodedPoints, encodedLevels) {
    	var encodedPolyline = new GPolyline.fromEncoded({
			points: encodedPoints,
			levels: encodedLevels
		});
		
		var points = [];
        for (var i=0; i<encodedPolyline.getVertexCount(); i++) {
      		points.push(encodedPolyline.getVertex(i));
    	}
    	$.fileMaps.drawPolyline(points);
    	$.fileMaps.arrowHead(points);
    },
    
    /*
    * Get the angle for a polyline
    */
    bearing: function( from, to ) {
		// Convert to radians.
		var degreesPerRadian = 180.0 / Math.PI;
		var lat1 = from.latRadians();
		var lon1 = from.lngRadians();
		var lat2 = to.latRadians();
		var lon2 = to.lngRadians();
		
		// Compute the angle.
		var angle = - Math.atan2( Math.sin( lon1 - lon2 ) * Math.cos( lat2 ), Math.cos( lat1 ) * Math.sin( lat2 ) - Math.sin( lat1 ) * Math.cos( lat2 ) * Math.cos( lon1 - lon2 ) );
		if ( angle < 0.0 )
			angle  += Math.PI * 2.0;
		
		// And convert result to degrees.
		angle = angle * degreesPerRadian;
		angle = angle.toFixed(1);
		
		return angle;
	},
	
	/*
	* Give polyline a middle arrow
	*/
	midArrows: function(points) {
        for (var i=1; i < points.length-1; i++) {  
          var p1=points[i-1];
          var p2=points[i+1];
          var dir = $.fileMaps.bearing(p1,p2);
          // == round it to a multiple of 3 and cast out 120s
          var dir = Math.round(dir/3) * 3;
          while (dir >= 120) {dir -= 120;}
          
          var arrowIcon = new GIcon();
	      arrowIcon.iconSize = new GSize(10,10);
	      arrowIcon.shadowSize = new GSize(1,1);
	      arrowIcon.iconAnchor = new GPoint(5,5);
	      arrowIcon.infoWindowAnchor = new GPoint(0,0);

          // == use the corresponding triangle marker 
          arrowIcon.image = "http://www.google.com/intl/en_ALL/mapfiles/dir_"+dir+".png";
          $.fileMaps.map.addOverlay(new GMarker(points[i], arrowIcon));
        }
	},
	
	/*
	* Give polyline a arrow head
	*/
	arrowHead: function(points) {
		// == obtain the bearing between the last two points
		var mid = Math.round( points.length/2);
		var p1=points[mid-1];
		var p2=points[mid];
		var p3=points[mid];
		var dir = $.fileMaps.bearing(p1,p2);
		// == round it to a multiple of 3 and cast out 120s
		var dir = Math.round(dir/3) * 3;
		while (dir >= 120) {dir -= 120;}
		// == use the corresponding triangle marker 
		
		var arrowIcon = new GIcon();
		arrowIcon.iconSize = new GSize(12,12);
	    arrowIcon.shadowSize = new GSize(1,1);
	    arrowIcon.iconAnchor = new GPoint(6,6);
	    arrowIcon.infoWindowAnchor = new GPoint(0,0);

		// == use the corresponding triangle marker 
		arrowIcon.image = "http://www.google.com/intl/en_ALL/mapfiles/dir_"+dir+".png";
				
		$.fileMaps.map.addOverlay(new GMarker(p1, arrowIcon));
	},
	
	/*
	* Check if givens points are in the current bounds
	*/
	checkBounds: function(points) {
		if($.fileMaps.bounds == null) {
			$.fileMaps.bounds = new GLatLngBounds();
		}
	   	for (var i=0; i< points.length; i++) {
	   		$.fileMaps.bounds.extend(points[i]);
	   	}
	},
	
	/*
    * Draw a polyline on the map
    */
    drawPolyline: function(polypoints) {
    	var polyline = new GPolyline(polypoints, "#0000FF", 4, 0.5);
		        	
    	$.fileMaps.map.addOverlay(polyline);
    },
    
    setToCookie: function() {
    	var center = $.fileMaps.map.getCenter();
    	var zoom = $.fileMaps.map.getZoom();
    	$.cookie("centerLat", center.lat()); 
    	$.cookie("centerLng", center.lng()); 
    	$.cookie("zoomLevel", zoom); 
    },
    
    creatFileMarker: function(point, html) {
    	var jamIcon = new GIcon();
		jamIcon.iconSize = new GSize(32,32);
		jamIcon.shadowSize = new GSize(1,1);
		jamIcon.iconAnchor = new GPoint(10,32);
		jamIcon.infoWindowAnchor = new GPoint(32,1);
		jamIcon.image = "/images/icons/trafficjam.png";
		var jamMarker = new GMarker(point, jamIcon);
		GEvent.addListener(jamMarker, "mouseover", function() {
			$.fileMaps.map.closeInfoWindow();
			jamMarker.openInfoWindowHtml(html);
		});
		$.fileMaps.map.addOverlay(jamMarker);
    }
};

// Initialize the Plaats maps object
$(document).ready(function() {
	$.fileMaps.init();
});
