var CAPEMOVIES = {
	utils : {},
	location : {}
};

/*** Utils ********************************************************************/

CAPEMOVIES.utils.getObject = function(id)
{	
	var object = document.getElementById(id);
	
	if (object == null)
	{
		throw("Failed to find object with id " + id + ".");
	}
	
	return object;
}

/*** Map **********************************************************************/

CAPEMOVIES.location.LocationCollection = function()
{
	this._locations = [];
	
	/* Registers a location. The location will be added to the map when the map
	 * is shown. */
	
	this.add = function(id, name, latitude, longitude)
	{
		this._locations.push({
			"id" : id,
			"name" : name,
			"latitude" : latitude,
			"longitude" : longitude
		});
	};
	
	/* Returns an array containing all of the locations. */
	
	this.get = function()
	{
		return this._locations;
	};
	
	this.exists = function(locationID)
	{
		for (var i = 0; i < this._locations.length; i++)
		{
			var location = this._locations[i];
			
			if (location.id == locationID)
			{
				return true;
			}
		}
		
		return false;
	};
};

/* A logical map object. This is a wrapper for the Google map, the YUI panel
 * which contains it, and the locations that are shown on the map. */

CAPEMOVIES.location.Map = function(id, locations, callback)
{
	/* Properties. */
	
	this._panelID = id;
	this._callback = callback;
	this._locations = locations;
	this._locationsMapped = false;
	
	// Generate element id's unique to this map.
	
	this._mapID = id + "-map";
	this._locationID = id + "-location";
	this._cancelID = id + "-cancel";
	
	/* Creates a Google Map using the specified HTML element ID. */
	
	this._createMap = function(id)
	{
		var element = CAPEMOVIES.utils.getObject(id);
		
		var map = new GMap2(element);
		
		map.addControl(new GSmallMapControl());
		
		this._centerMap(map);
		
		return map;
	};
	
	/* Sets the center coordinate for the specified map. */
	
	this._centerMap = function(map)
	{
		var point = new GLatLng(41.71393, -70.337219);
		
		map.setCenter(point, 9);
	};
	
	/* Creates a YUI panel using the specified element ID. */

	this._createPanel = function(panelID, mapID, locationID, cancelID)
	{
		var options = this._createPanelOptions();
		
		var panel = new YAHOO.widget.Panel(panelID, options);
		
		panel.setHeader("Pick a Location");
		
		panel.setBody('\
			<div id="' + mapID + '" class="mapContainer"></div>\
			<div id="' + locationID + '" style="padding: 10px;">\
				Move your cursor over the map.\
			</div>\
			<div align="center">\
				<input type="button" id="' + cancelID + '" class="button"\
						value="Cancel">\
			</div>\
		');
		
		panel.render(document.body);
		
		// Add a click event to the cancel button.
		
		var map = this;
		
		var cancel = CAPEMOVIES.utils.getObject(cancelID);
		
		YAHOO.util.Event.addListener(cancel, "click",
				function() { map.hide(); } );
		
		return panel;
	};
	
	/* Creates a YUI panel options object which is used to initialize the panel
	 * object. */
	
	this._createPanelOptions = function()
	{
		return {
			width : "508px",
			fixedcenter: true,
			constraintoviewport : true,
			close : true,
			visible : false,
			modal : true
		};
	}
	
	/* Displays the map. */
	
	this.show = function()
	{
		if (!this._initialized)
		{
			this._initialize();
		}
		
		this._panel.show();
	};
	
	/* Hides the map. */
	
	this.hide = function()
	{
		this._panel.hide();
	};
	
	/* Selects the specified location and closes the map. */
	
	this.select = function(location)
	{
		this.hide();
		
		if (typeof this._callback == "function")
		{
			this._callback(location);
		}
	};
	
	/* Deselects the currently selected location and closes the map. */
	
	this.deselect = function()
	{
		this.hide();
	};
	
	/* Adds all the locations to the Google map. */
	
	this._mapLocations = function()
	{
		// Toggle our flag first to minimize the chance of race conditions.
		
		this._locationsMapped = true;
		
		var locations = this._locations.get();
		
		for (var i in locations)
		{
			var location = locations[i];
			
			this._mapLocation(location);
		}
	};
	
	/* Adds the specified location to the Google map. */
	
	this._mapLocation = function(location)
	{
		var coordinates = new GLatLng(location.latitude, location.longitude);
		
		var marker  = new GMarker(coordinates);
		
		var map = this;
		
		GEvent.addListener(marker, "mouseover", function() { map.setTitle(location.name); });
		GEvent.addListener(marker, "click", function() { map.select(location) });
		
		this._map.addOverlay(marker);
	};
	
	/* Updates the title of the map. */
	
	this.setTitle = function(title)
	{
		var element = CAPEMOVIES.utils.getObject(this._locationID);
		
		element.innerHTML = title;
	};
	
	this._initialize = function()
	{
		this._panel = this._createPanel(this._panelID, this._mapID,
			this._locationID, this._cancelID);
		
		this._map = this._createMap(this._mapID);
		
		this._mapLocations();
	};
};
