(function($){
	var g = google.maps,
		
		// Private utility object
		utils = {
			// Slow, stupid and dangerous (but it works)
			encodeCoords: function(strCoords){
				return eval("({" + strCoords + "})");
			}
		},
		
		
		// Exported sigleton
		Maintenance = {
			
			// Properties
			markerOpts: {
				tyokohde: {
					icon: new google.maps.MarkerImage('/stc/shared/images/map/icn_tyokohde.png', 
						new google.maps.Size(42, 43),
						new google.maps.Point(0,0),
						new google.maps.Point(20, 21)),
					shape: {
						coord: [0, 21, 20, 1, 39, 21, 20, 40],
						type: 'poly'
					}
				},
				tyokeskeytys: {
					icon: new google.maps.MarkerImage('/stc/shared/images/map/icn_tyokeskeytys.png', 
						new google.maps.Size(42, 43),
						new google.maps.Point(0,0),
						new google.maps.Point(20, 21)),
					shape: {
						coord: [0, 21, 20, 1, 39, 21, 20, 40],
						type: 'poly'
					}
				}
			},
			mapOpts: {
				zoom: 7,
				center: new g.LatLng(61.0, 24.0),
				mapTypeId: g.MapTypeId.ROADMAP
			},
			
			mapPoints: [],
			map: null,
			infoWin: null,
			infoWinHeight: 0, // Current info window height
			infoWinTweaks: {x: -18, y: -14},
			activeMarker: -1,
			
			// Event listeners
			mapListeners: {
				move: null,
				zoom: null,
				click: null
			},
			
			
			
			// Static geocoding service provided to the WYSIWYG editor (no map instance required)
			adminGeocode: function(from, to){
				var address = document.getElementById(from).getElementsByTagName("div")[0].innerHTML,
					geocoder = new g.Geocoder();
				
				geocoder.geocode({'address': address}, function(results, status){
					if(status == g.GeocoderStatus.OK){
						var loc = results[0].geometry.location;
						document.getElementById(to).getElementsByTagName("div")[0].innerHTML = "lat : " + loc.lat() + ", lng : " + loc.lng();
						
						if(!window.Save || !Save.u4_disabled){
							top.main.postData();
						}
					}
					else{
						alert("google.maps.Geocoder error: " + status);
					}
				});
			},
			
			
			// Map methods
			initMap: function(containerId){
				this.map = new g.Map(document.getElementById(containerId), this.mapOpts);
				this.infoWin = new VJBox({pixelOffset: {x: -137, y: 0}});
			
				this.mapListeners.move = new google.maps.event.addListener(this.map, "center_changed", function(){
					Maintenance.mapOpts.center = Maintenance.map.getCenter();
				});
				
				this.mapListeners.click = new google.maps.event.addListener(this.map, "click", function(){
					Maintenance.infoWin.close();
					Maintenance.activeMarker = -1;
				});
			},
			
			
			// Add marker and bindings
			addBoundMarker: function(strCoords, instanceId, type){
				if(strCoords.length > 6){
					var point = utils.encodeCoords(strCoords);
					point.instanceId = instanceId;
					point.type = type;
					point.marker = this.createMarker(point);
					point.marker.setIcon(this.markerOpts[type].icon);
					point.marker.setShape(this.markerOpts[type].shape);
					
					var markerIndex = this.mapPoints.length;
					point.listener = new google.maps.event.addListener(point.marker, "click", function(){
						Maintenance.activeMarker = markerIndex;
						Maintenance.displayInfoWindow(markerIndex);
						Maintenance.map.panTo(Maintenance.mapPoints[markerIndex].marker.getPosition());
					});
					
					this.mapPoints.push(point);
				}
			},
			
			createMarker: function(point){
				var marker = new g.Marker({position: new g.LatLng(point.lat, point.lng)});
				marker.setMap(this.map);
				return marker;
			},
			
			
			
			/*
				Info window methods
			*/
			
			// Display info window
			displayInfoWindow: function(markerIndex){
				var marker = this.mapPoints[markerIndex].marker,
					iid = this.mapPoints[markerIndex].instanceId;
				
				this.infoWin.close();
				this.infoWin.setContent($('#map_infowin_' + iid).html());
				this.infoWin.open(this.map, marker);
				this.infoWin.show();
			},
			
			// Hide info window and reset active marker
			hideInfoWindow: function(){
				this.infoWin.close();
			}
		};
	
	// Exports
	window.Maintenance = Maintenance;
})(jQuery);
