//
// EinsteinDirectory core javascript
//
// Author: 	Brian Smith
// Date: 	August 2007
//

EII.namespace("Directory");

EII.Directory = function(mapElement, centerLatLng, radius) {
		
	var map = new EII.Directory.Map(mapElement, centerLatLng, radius);
	var that = this;
	
	// Loads the map and runs any necessary initialization. Should be set as a window (or document) load event.
	//
	this.load = function() {
		that.beforeLoad();
		
		if(map) {
			map.load();
		}
		
		that.afterLoad();
	};
	
	// Unloads the map and runs any necessary teardown code. Should be set as a window (or document) unload event.
	//
	this.unload = function() {
		that.beforeUnload();
		
		if(map) {
			map.unload();
		}
		
		that.beforeUnload();
	};
	 
	// Add an entity
	//
	// newEntity - JSON object of an entity
	// newEntityHtml - HTML representation of entity
	// newEntityLinkClass - HTML class for links to this entity
	//
	this.addEntity = function(newEntity, newEntityHtml, newEntityLinkClass) {
		that.beforeAddEntity(newEntity, newEntityHtml, newEntityLinkClass);
				
		if(map) {
			map.addEntity([newEntity.location.latitude, newEntity.location.longitude], newEntityHtml, newEntityLinkClass);
		}
		
		that.afterAddEntity(newEntity, newEntityHtml, newEntityLinkClass);
	};
	
	// Remove all entities
	//
	//
	this.clearEntities = function() {
		that.beforeClearEntities();
		
		if(map) {
			map.clearEntities();
		}
		
		that.afterClearEntities();
	};
	
	// Set the center and radius of the search.
	//
	// newLatLng needs to be a two-element array with the 
	// latitude and longitude of strings.
	//
	// newRadius needs to be an integer (for radius of search in miles)
	//
	this.setCenter = function(newLatLng, newRadius) {
		that.beforeSetCenter(newLatLng, newRadius);
		
		if(map) {
			map.moveTo(newLatLng, newRadius);
		}
		
		that.afterSetCenter(newLatLng, newRadius);
	};
	
}
// Before and after callbacks
//
// You can overwrite any of these callbacks to allow for custom
// functionality.
//
// Example:
//
// 	EII.Directory.prototype.afterLoad = function() { alert("Loaded!"); };
//
EII.Directory.prototype.afterUpdate = function() {};
EII.Directory.prototype.beforeUpdate = function() {};
EII.Directory.prototype.afterAddEntity = function(newEntity, newEntityHtml, newEntityLinkClass) {};
EII.Directory.prototype.beforeAddEntity = function(newEntity, newEntityHtml, newEntityLinkClass) {};
EII.Directory.prototype.afterLoad = function() {};
EII.Directory.prototype.beforeLoad = function() {};
EII.Directory.prototype.afterUnload = function() {};
EII.Directory.prototype.beforeUnload = function() {};
EII.Directory.prototype.afterClearEntities = function() {};
EII.Directory.prototype.beforeClearEntities = function() {};
EII.Directory.prototype.afterSetCenter = function(newLatLng, newRadius) {};
EII.Directory.prototype.beforeSetCenter = function(newLatLng, newRadius) {};


// The Map constructor creates a new map.
//
// Requires: Prototype 1.5+
//
// Parameters:
//
//	mapElement: 		The element (or string id of an element) to use for displaying the map,
//									most likely a div element.
//	centerLatLng: 	A two-element array of floats where the first element corresponds to the
//									latitude of the center of the map, and the second element for the longitude.
//	radius: 				The minimum radius (in miles) that the map should cover.
EII.Directory.Map = function (mapElement, centerLatLng, radius) {
	
	this.defaultCenter = [39.9, -98.5];
	this.defaultRadius = 1400;
	
	var _mapElement = $(mapElement);
	var _centerLatLng = centerLatLng || this.defaultCenter;
	var _radius = radius || this.defaultRadius;
	
	var _map = null;
	var _entityMarkers = new Array;
	
	var that = this;
	
	function centerLat() {
		return parseFloat(_centerLatLng[0]);
	}
	
	function centerLng() {
		return parseFloat(_centerLatLng[1]);
	}
	
	function radiusToZoom() {
		degLatInMiles =  69.170323428;
		degLngInMiles = degLatInMiles * Math.cos(centerLat() * 0.0174532925199433);
				
		diffDegLat = _radius / degLatInMiles;
		diffDegLng = _radius / degLngInMiles;
				
		swBound = new GLatLng(centerLat() - diffDegLat, centerLng() - diffDegLng);
		neBound = new GLatLng(centerLat() + diffDegLat, centerLng() + diffDegLng);

		return _map.getBoundsZoomLevel(new GLatLngBounds(swBound, neBound));
	}
	
	function loadEntityMarkers() {
		for( var i = 0; i < _entityMarkers.length; i++) {
			_map.addOverlay( _entityMarkers[i] );
		}
	}
	
	function addLinkInfoEvents(entityIndex, linkClass) {
		linkElements = $$('a.' + linkClass);
		for(var i = 0; i < linkElements.length; i++) {
			
		}
	}
	
	
	this.load = function() {
		if (GBrowserIsCompatible()) {
			_map = new GMap2(_mapElement);
			
			_map.addControl(new GSmallMapControl());
			_map.addControl(new GMapTypeControl());
			
	    	_map.setCenter(new GLatLng(centerLat(), centerLng()), radiusToZoom());
						
			loadEntityMarkers();
			return true;			
		}
		return false;
	}
	
	this.unload = function() {
		if (GBrowserIsCompatible()) {
			GUnload();
			return true;
		}
		return false;
	}
	
	this.addEntity = function(markerLatLng, entityHTML, entityLinkClass) {
		var newPoint = new GLatLng(markerLatLng[0], markerLatLng[1]);
		var newMarker = new GMarker(newPoint);
		
		newMarker.bindInfoWindowHtml(entityHTML);
		
		entityLinks = $$('a.' + entityLinkClass);
		for(var i = 0; i < entityLinks.length; i++) {
			Element.observe(entityLinks[i], "click", function() { GEvent.trigger(newMarker, "click"); });
		}
			
		_entityMarkers.push(newMarker);
		 		
		if( _map ) {
			_map.addOverlay(newMarker);
		}
		
		return true;
	}
	
	this.clearEntities = function () {
		var currentMarker;
		
		while(currentMarker = _entityMarkers.pop()) {
			_map.removeOverlay(currentMarker);
		}
		return true;
	}
	
	this.moveTo = function(newLatLng, newRadius) {
		_radius = newRadius;
		_centerLatLng = newLatLng;
		
		_map.setZoom(radiusToZoom());
		_map.panTo( new GLatLng(centerLat(), centerLng()) );
		
		return true;
	}
	
};