/**
 * Client side representation and actions allowed on a Event.
 * 
 * @param isDisabled If true then this Event should not respond to actions that modify
 * 					 the state of the Event
 * @return
 */
function Event(isDisabled)
{
	this.eid;
	this.etitle;
	this.etype;
	this.ewhen;
	this.eurl;
	
	this.markerCluster;
	this.map;
	this.places = [];
	this.placeNames = [];
	this.placeIds = [];
	this.disabled = (isDisabled) ? true : false;
};

Event.prototype.eid;
Event.prototype.etitle;
Event.prototype.etype;
Event.prototype.ewhen;
Event.prototype.eurl;

Event.prototype.getPlaces = function()
{
	return this.places;
};

/**
 * Initialise the Map. 
 */
Event.prototype.load = function()
{
	var latlng = new google.maps.LatLng(0, 0);
	var myOptions = {
		zoom: 1,
		center: latlng,
		mapTypeId: google.maps.MapTypeId.ROADMAP,
        overviewMapControl: true
	};
	this.map = new google.maps.Map(document.getElementById("map"), myOptions);
  	
  	if (this.disabled)
  		return;
};

Event.prototype.construct = function(eid, etitle, etype, ewhen, eurl)
{
	this.eid = eid;
	this.etitle = etitle;
	this.etype = etype;
	this.ewhen = ewhen;
	this.eurl = eurl;
};

Event.prototype.loadPlace = function(pid, pname, type, url, showurl, googlepoint)
{
	var place = new Place(this.map);
	place.construct(pid, pname, type, url, showurl, googlepoint);
	
	this.places.push(place);
	this.placeNames.push(pname);
	this.placeIds.push(pid);
	
	this.updatePlacesOnForm();
};

/**
 * Add a new Place to the placesTable.
 * 
 * @param pid	the id of a chosen Place
 * @param pname the name of a chosen Place
 * @param googlepoint string geometry in google GLatLng format
 */
Event.prototype.addPlace = function(pid, pname, ptype, purl, pshowurl, googlepoint)
{
	if (this.disabled)
		return;

	var place = new Place(this.map);
	place.construct(pid, pname, ptype, purl, pshowurl, googlepoint);
	
	this.places.push(place);
	this.placeNames.push(pname);
	this.placeIds.push(pid);
	
	placesTable.addRow({id: pid, name: pname, type: ptype});
	
	this.updatePlacesOnForm();
	
	alert(pname + ' added to the Event.');
	
	this.cluster();
};

Event.prototype.removePlace = function(index)
{
	if (this.disabled)
		return;
	
	var place = this.places[index];
	
	this.clearPlace(index);
	this.places.splice(index, 1);
	this.placeIds.splice(index, 1);
	
	this.updatePlacesOnForm();
};

Event.prototype.clearPlace = function(index)
{
	if (this.disabled)
		return;
	
	var place = this.places[index];
	place.clearGeometry(this.map);
	
	this.updatePlacesOnForm();
};

Event.prototype.updatePlacesOnForm = function()
{
	if (this.disabled)
		return;
	
	var form_event_places = document.getElementById('event_placeIds');
	form_event_places.value = this.placeIds; 
};

/**
 * Zoom and center the map to a particular Place if it has any geometry.
 * 
 * @param index index of a Place
 */
Event.prototype.zoomPlace = function(index)
{
	var place = this.places[index];
	place.zoom();
};

Event.prototype.getMarkers = function()
{
	var m = [];
	var len = this.places.length;
	for (var i = 0; i < len; i++)
	{
		m.push(this.places[i].getMarker());
	}
	
	return m;
}

Event.prototype.cluster = function()
{
	if (this.markerCluster)
	{
		this.markerCluster.clearMarkers();
	}
	this.markerCluster = new MarkerClusterer(this.map, this.getMarkers());
};

/**
 * Zoom the map to fill all the Point geometry only.
 */
Event.prototype.zoom = function()
{
	var allgeom = [];

	var plen = this.getMarkers().length;
	for (var i = 0; i < plen; i++)
	{
		allgeom.push(this.getMarkers()[i].getPosition());
	}
	
	reSizeAndReCentreMap(allgeom, this.map);
};

/**
 * @param address
 */
Event.prototype.locate = function(address)
{
	geocodeAddress(address, this);
};

/**
 * Set the point value on the hidden form field.
 *
 * Contract method for anything that wants to be used as a callback. A class can only be a callback to
 * a single source.
 *
 * @param point a GLatLng
 */
Event.prototype.callback = function(point, address)
{
	var geocodeFormField = document.getElementById('place_geocode');
	geocodeFormField.value += point + address + ':';

	this.addPlace(null, address, null, null, null, point.toString());
	
	this.cluster();
	this.zoom();
};
