// Map constructor
function Map(mapContainer, rootURL, centerLat, centerLng) {

	// Do nothing for incompatible browsers and illegal constructor argument
	if (!mapContainer || !rootURL || !google.maps.BrowserIsCompatible()) {
		return;
	}
	
	this.rootURL = rootURL;
	
	// Constants
	var MIN_ZOOM = this.MIN_ZOOM = 7;
	var MAX_ZOOM = this.MAX_ZOOM = 16;
	
	// Add Google Maps unload event (for circular reference cleanup)
	google.maps.Event.addDomListener(window, "unload", google.maps.Unload);
	
	// Initialize Map2 object
	this.gmap = new google.maps.Map2(mapContainer);
	
	// Set up default map types
	this.gmap.addMapType(G_NORMAL_MAP);
	this.gmap.removeMapType(G_SATELLITE_MAP);
	this.gmap.removeMapType(G_HYBRID_MAP);
	this.gmap.removeMapType(G_PHYSICAL_MAP);

	// Set up adventure map type
	this.gmap.getMapTypes()[0].getMinimumResolution = function() { return MIN_ZOOM; }
	this.gmap.getMapTypes()[0].getMaximumResolution = function() { return MAX_ZOOM; }
	
	// Add keyboard handler
	new google.maps.KeyboardHandler(this.gmap);

	// Add small map zoom control
	this.gmap.addControl(new google.maps.SmallZoomControl());

	// Initialize map
	this.gmap.setCenter(new google.maps.LatLng(centerLat ? centerLat : 55.34, centerLng ? centerLng : 23.74), this.MAX_ZOOM - 1);

	this.gmap.enableDragging();
	this.gmap.enableInfoWindow();
	this.gmap.enableScrollWheelZoom();
	this.gmap.enableContinuousZoom();
	this.gmap.disableGoogleBar();
	this.gmap.disableDoubleClickZoom();
	
	// Create marker manager
	this.markerManager = new google.maps.MarkerManager(this.gmap);
	
	// GMarker storage
	this.markers = [];
}

// Process marker zIndex value
Map.prototype.onMarkerZIndexProcess = function(marker) {

	return marker.id;
}

// Create google.maps.Marker
Map.prototype.createMarker = function(id, lat, lng, title) {

	this.markers[id] = new google.maps.Marker(new google.maps.LatLng(lat, lng), {icon: G_DEFAULT_ICON, title: title, zIndexProcess: this.onMarkerZIndexProcess});
	this.markers[id].id = id;

	return this.markers[id];
}

// Add new markers
Map.prototype.addMarkers = function(stations) {

	var GMarkers = [];
	for (var i in stations) {
	
		// Create google.maps.Marker
		GMarkers.push(this.createMarker(i, stations[i][0], stations[i][1], stations[i][2]));
	}

	this.markerManager.addMarkers(GMarkers, this.MIN_ZOOM);
}

// Draw markers on the map
Map.prototype.drawMarkers = function() {

	this.markerManager.refresh();
}

// MapPicker constructor
function MapPicker(mapContainer, rootURL, no_marker, markerLat, markerLng, viewMode) {

	this.base = Map;
	this.base(mapContainer, rootURL, markerLat, markerLng);
	
	// Re-create custom marker manager and picker
	this.markerManager = new google.maps.MarkerManager(this.gmap, { trackMarkers: true });

	var pickerOptions = {}
	pickerOptions.icon = this.ICON_STATION;

	if (viewMode) {
		pickerOptions.clickable = false;
	}
	else {
		pickerOptions.draggable = true;
		pickerOptions.autoPan = false;
	}

	this.pickerMarker = new google.maps.Marker(new google.maps.LatLng(markerLat, markerLng), pickerOptions);

	if (!no_marker) {
		this.markerManager.addMarker(this.pickerMarker, this.MIN_ZOOM);
		this.markerManager.refresh();
	}

	// Add events
	if (!viewMode) {
		google.maps.Event.bind(this.gmap, 'click', this, function(overlay, latlng) { this.onMapPickerClick(overlay, latlng); } );
		google.maps.Event.bind(this.pickerMarker, 'dragend', this, this.onMapPickerMarkerDragEnd );
		google.maps.Event.bind(this.pickerMarker, 'mouseover', this, function() { this.onMarkerMouseOver(this.pickerMarker); });
		google.maps.Event.bind(this.pickerMarker, 'mouseout', this, function() { this.onMarkerMouseOut(this.pickerMarker); });
	}
}

// MapPicker extends Map
MapPicker.prototype = new Map;

// onMapPickerClick event
MapPicker.prototype.onMapPickerClick = function(overlay, latlng) {

	if (!overlay) {
		this.setPickerLocation(latlng.lat(), latlng.lng());
	}
}

// onMapPickerMarkerDragEnd event
MapPicker.prototype.onMapPickerMarkerDragEnd = function() {
	var pickerLatLng = this.pickerMarker.getLatLng();
	
	this.setPickerLocation(pickerLatLng.lat(), pickerLatLng.lng());
}

// setPickerLocation
MapPicker.prototype.setPickerLocation = function(lat, lng) {

	if (!this.markerManager.getMarkerCount(this.MIN_ZOOM)) {
		this.markerManager.addMarker(this.pickerMarker, this.MIN_ZOOM);
		this.markerManager.refresh();
	}

	this.pickerMarker.setLatLng(new google.maps.LatLng(lat, lng));

	if (window.onMarkerLocationChanged) {
		window.onMarkerLocationChanged(lat, lng);
	}
}