/*

	Custom Google Maps overlay for info windows.
	http://code.google.com/apis/maps/documentation/overlays.html#Custom_Overlays

*/
function AZOverlay(control, marker, html, offset_x, offset_y)
{
	// Cache control, marker, and html
	this.control = control;
	this.marker  = marker;
	this.html    = html;

	if (offset_x === null) { offset_x = 0; }

	// Set left offset
	this.offset_x = offset_x;

	if (offset_y === null) { offset_y = 0; }

	// Set top offset
	this.offset_y = offset_y;
}
AZOverlay.prototype = new GOverlay();
AZOverlay.prototype.initialize = function(gmap)
{
	// Create a new overlay
	var box = $('<div></div>').addClass('gmap-custom');

	// Current overlay, use this for anonymous functions
	var _this = this;

	$('<div></div>').addClass('content').html(this.html).appendTo(box);
	$('<div></div>').addClass('close-button').html('close').click(function()
	{
		// Close the current marker
		_this.control.openMarker(null);
	})
	.appendTo(box);

	// Switch to raw DOM
	box = box.get(0);

	// Cache the map and box
	this.gmap = gmap;
	this.box  = box;

	// Redraw to set top/left
	this.redraw();

	// Add overlay to map
	this.gmap.getPane(G_MAP_FLOAT_PANE).appendChild(this.box);
};
AZOverlay.prototype.remove = function()
{
	if (this.box.parentNode !== null)
	{
		// Remove the info window
		this.box.parentNode.removeChild(this.box);
	}
};
AZOverlay.prototype.redraw = function(force)
{
	// Only redraw when coordinates change
	if (force !== true) { return false; }

	// Make the box
	var box = $(this.box);

	// Set left/top offset based on current location/zoom
	box.css('left', (this.gmap.fromLatLngToDivPixel(this.marker.getPoint()).x - this.offset_x) +'px');
	box.css('top',  (this.gmap.fromLatLngToDivPixel(this.marker.getPoint()).y - box.height() - this.offset_y) +'px');
};

/*

	Creates a new custom google map from a div element.

*/
function AZMap(gmap)
{
	// Map does not contain search results
	this.search_results = true;

	// Initialize the GMap
	this.gmap = new GMap2(gmap);

	// Go to the center of the map
	this.goToCenter();

	// Set options
	this.gmap.addControl(new GLargeMapControl());
	this.gmap.addControl(new GMapTypeControl());
	this.gmap.enableScrollWheelZoom();

	// Initialize the marker manager
	this.mgr = new MarkerManager(this.gmap, { maxZoom: 20 });

	// Initialize the open marker storage
	this.open_marker = null;
	this.open_center = null;

	// Create icons
	this.icons = {
		country: null,
		city: null,
		restaurant: null,
		hotspot: null
	};

	for (var name in this.icons)
	{
		// Create an icon for each type
		icon = new GIcon();
		icon.image = base_url +'resources/img/pins/'+ name +'.png';
		icon.iconSize = new GSize(12, 20);
		icon.iconAnchor = new GPoint(6, 20);
		icon.infoWindowAnchor = new GPoint(5, 1);

		// Replace the icon with a constructed one
		this.icons[name] = icon;
	}

	// Default zoom levels
	this.zoom_level = {
		countries: [0, 3],
		cities:    [4, 7],
		places:    [8, 20]
	};
}

/*

	Goes to the center of the map.

*/
AZMap.prototype.goToCenter = function()
{
	// Go to the center of the map
	this.gmap.setCenter(new GLatLng(20, 0), 1);
};

/*

	Gets the maximum zoom level for a collection of points.

*/
AZMap.prototype.getZoom = function(collection)
{
	// Create a new bounds for this collection
	var bounds = new GLatLngBounds();

	for (name in collection)
	{
		// Extend the bounds
		bounds.extend(new GLatLng(collection[name].lat, collection[name].lon));
	}

	return this.gmap.getBoundsZoomLevel(bounds);
};

/*

	Loads an array of point collections. Collection array data structure:

	{
		group_type: {
			place_name: {
				lat: 0.0,
				lon: 0.0,
				type: 'place type',
			},
			...
		},
		...
	}


*/
AZMap.prototype.loadCollection = function(collection, focus, search)
{
	// Create a new set of bounds for this collection
	var bounds = new GLatLngBounds();

	// Current instance of the map, use for anonymous function
	var _this = this;

	// Close all current markers
	this.openMarker(null);

	// Clear all current markers
	this.mgr.clearMarkers();

	$.each(collection, function(group, places)
	{
		// Markers array for this collection
		var markers = [];

		$.each(places, function(name, place)
		{
			// Create the latitude and longitude and marker
			var latlng = new GLatLng(place.lat, place.lon);
			var mark   = new GMarker(latlng,
			{
				title: name,
				icon:  _this.icons[place.type]
			});

			// Extend the bounds
			bounds.extend(latlng);

			if (group == 'countries' || group == 'cities')
			{
				// Set the zoom level
				var zoom = group == 'countries' ? 4 : 10;

				GEvent.addListener(mark, 'click', function()
				{
					// Zoom in and pan to the clicked point
					_this.gmap.setZoom(zoom);
					_this.gmap.panTo(this.getPoint());
				});
			}
			else
			{
				// Add the marker info window
				mark.overlay = new AZOverlay(_this, mark, place.html, 100, 28);
				GEvent.addListener(mark, 'click', function()
				{
					// Close open markers and switch the current marker
					_this.openMarker(this);
				});
			}

			// Add the maker to collection array
			markers.push(mark);
		});

		if (search === true)
		{
			// All search results should be visible
			min = 0;
			max = 20;
		}
		else
		{
			// Get the min and max zoom for this type
			min = _this.zoom_level[group][0];
			max = _this.zoom_level[group][1];
		}

		// Add the markers and refresh
		_this.mgr.addMarkers(markers, min, max);
		_this.mgr.refresh();
	});

	// Are the current markers search results?
	this.search_results = (search === true);

	if (focus === true || focus === null)
	{
		// Set the zoom and center based on the point bounds
		this.gmap.setZoom(this.gmap.getBoundsZoomLevel(bounds) - 1);
		this.gmap.panTo(bounds.getCenter());
	}
	else
	{
		// Go to the center of the map
		this.goToCenter();
	}
};

/*

Open the info window of any marker

*/
AZMap.prototype.openMarker = function(marker)
{
	if (this.open_marker)
	{
		// Remove the popup
		this.gmap.removeOverlay(this.open_marker.overlay);
	}

	// Set the current open marker
	this.open_marker = marker;

	if (marker !== null)
	{
		// Center on the map point
		this.gmap.panTo(marker.getPoint());

		// Display the custom overlay
		this.gmap.addOverlay(marker.overlay);
	}
};

