(function($){
	jQuery.fn.presentationMap = function(options){
		var $pm = jQuery(this);
		
		var options = jQuery.extend({
			map_interactive:true,
			zoom_to_stream:false,
			zoomToMarker:false
		},options);
		
		var $mapInternals = null;
		var userOverideZoom = false;
		
		var mappedItems = [];
		var itemBounds = {};
		var temporaryMarkers = [];
		var locationIcons = {};
		var globalOverlay = null;
		var wtcOverlay = null;
		var $current_location = $pm.children(".current_location");
		var $changeLocationButton = $pm.children(".map_controls").children(".change_location");
		var $changeLocationForm = $pm.children(".controls_header").children(".change_location_form");
		var $loaderImage = $pm.children(".controls_header").children(".loader_large");
		var $cancel_button = $pm.children(".controls_header").children(".cancel");
		var $map_button = $changeLocationForm.children(".map_button");
		var $location_dropdown = $changeLocationForm.children(".search").children("select");
		var $location_text = $changeLocationForm.children(".search").children(".text");
		var $location_radiobuttons = [];
		var $location_form_status = $changeLocationForm.children(".status");
		var $zoomInButton = $pm.children(".map_controls").children(".zoom_in");
		var $zoomOutButton = $pm.children(".map_controls").children(".zoom_out");
		
		var initialized = false;
		
		function initialize(){
			initializeMapInternals();
			restoreDefaults();
			setupLocationDialog();
			setupZoomFunctions();
			globalOverlay = $mapInternals.makeGlobalGrayOverlay();
			wtcOverlay = $mapInternals.generateWTCOverlay();
			setupLocationIcons();
			
			$mapInternals.addMarker(globalOverlay,false);
			$mapInternals.addMarker(wtcOverlay,false);
			
			initialized = true;
			ns11mmPresentationLoader.trigger("loadStatusEvent",{pct:10,msg:"Map Internal Initialized"});
		};
		
		function initializeMapInternals(){
			$mapInternals = jQuery("<div class='mapInternals'></div>").presentationMapInternalCloudmade({target_div:$pm.children(".map").children(".map_inner").get(0)});
			$mapInternals.formatCopyright();
			$mapInternals.fixBackground("#485f89 url(../images/presentation_lower_background.png) repeat-x center top");
			$mapInternals.fixLoader("transparent url(/images/presentation_map_internal_loader.gif) no-repeat scroll 0 0")
			$mapInternals.disableMouseZoom();
		};
		
		function setupLocationIcons(){
			locationIcons = {};
			locationIcons.wtc = $mapInternals.makeLocationMarker("wtc");
			$mapInternals.addMarker(locationIcons.wtc,false);
			locationIcons.shanksville = $mapInternals.makeLocationMarker("shanksville");
			$mapInternals.addMarker(locationIcons.shanksville,false);
			locationIcons.pentagon = $mapInternals.makeLocationMarker("pentagon");
			$mapInternals.addMarker(locationIcons.pentagon,false);
		};
		
		
		$pm.update = function(data){
			clearMap(null);
			parseData(data);
		};
		
		$pm.clear = function(){
			clearMap();
			restoreDefaults();
		};
		
		$pm.selectAndPanToMarkerById = function(id){
			clearTemporaryMarkers();
			var marker = getMarkerById(id);
			if(marker.length > 0){
				panAndZoomToMarker(marker[0]);
				selectMarker(marker[0]);
				displayTitle(marker[0].locationString);
			};
		};
		
		$pm.showTemporaryMarkerFromCuepointData = function(data){
			clearTemporaryMarkers();
			addTemporaryMarker(data);
			$mapInternals.panTo(data.lat,data.lng);
			if(userOverideZoom == false && options.zoomToMarker == true){
				$mapInternals.zoomTo(data.zoom);
			};
		};
		
		function parseData(data){
			itemBounds = {
				minLat:180,
				maxLat:-180,
				minLng:180,
				maxLng:-180
			};
			mappedItems = jQuery.map(jQuery(data.items),mapItem);
			if(mappedItems.length > 0){
				if(options.zoom_to_stream == true){
					$mapInternals.zoomToBounds(itemBounds);
				};
			} else {
				_handleNoResults(data);
			};
			hideLoader();
		};
		
		function _handleNoResults(data){
			restoreDefaults();
			displayTitle("No Results");
		};
		
		function restoreDefaults(){
			$mapInternals.restoreDefaults();
		};
		
		function displayTitle(title){
			$current_location.show();
			$current_location.children("h2").text(title);
		};
		
		function mapItem(di){
			var item = {};
			item.id = di.id;
			item.lat = di.lat * 1;
			if(item.lat > itemBounds.maxLat) itemBounds.maxLat = item.lat;
			if(item.lat < itemBounds.minLat) itemBounds.minLat = item.lat;
			item.lng = di.lng * 1;
			if(item.lng > itemBounds.maxLng) itemBounds.maxLng = item.lng;
			if(item.lng < itemBounds.minLng) itemBounds.minLng = item.lng;
			item.zoom = di.zoom;
			item.timeframeIndex = di.timeframe_index;
			item.geohash = di.geohash;
			item.locationString = di.location;
			item.markers = jQuery({});
			item.markers.marker = $mapInternals.makeMarker(item.lat,item.lng,"standard");
			item.markers.marker.parent = item;
			item.markers.selectedMarker = $mapInternals.makeMarker(item.lat,item.lng,"selected");
			item.markers.selectedMarker.parent = item;
			item.clickHandler = function(latlng){
				_mapItemClickHandler(this.parent);
			};
			item.select = function(){
				$mapInternals.selectItem(this);
			};
			item.deselect = function(){
				$mapInternals.deselectItem(this);
			};
			$mapInternals.addClickHandlerToItemMarkers(item,item.markers.marker);
			$mapInternals.addClickHandlerToItemMarkers(item,item.markers.selectedMarker);
			$mapInternals.addMarker(item.markers.marker,false);
			$mapInternals.addMarker(item.markers.selectedMarker,true);
			return item;
		};
		
		function _mapItemClickHandler(item){
			if(options.map_interactive == true){
				var data = {
					clicked:item
				};
				selectMarker(item);
				ns11mmPresentation.trigger("mapMarkerClicked",data);
			}
		};
		
		function selectMarker(item){
			jQuery(mappedItems).each(function(i,j){
				j.deselect();
			});
			$mapInternals.toggleMarkerSelectedState(item);
		};
		
		function panAndZoomToMarker(item){
			if($mapInternals.viewportContainsMarker(item) == false){
				$mapInternals.panTo(item.lat,item.lng);
				if(userOverideZoom == false && options.zoomToMarker == true){
					$mapInternals.zoomTo(item.zoom);
				};
			}
		};
		
		function getMarkerById(id){
			return jQuery.grep(mappedItems,function(i,j){
				return (i.id == id);
			});
		};
		
		function clearMap(callback){
			clearTemporaryMarkers();
			userOverideZoom = false;
			if(mappedItems.length > 0){
				jQuery(mappedItems).each(function(i,item){
					$mapInternals.destroyMarker(item,item.markers.marker);
					$mapInternals.destroyMarker(item,item.markers.selectedMarker);
					item.clickHandler = null;
					item = null;
				});
				mappedItems = [];
			};
			if(callback != null && typeOf(callback) == "function"){
				callback();
			};
		};
		
		//TEMPORARY MARKERS
		
		function clearTemporaryMarkers(){
			jQuery(temporaryMarkers).each(function(i,j){
				$mapInternals.destroyMarker(null,j);
				j = null;
			});
			temporaryMarkers = [];
		};
		
		function addTemporaryMarker(data){
			var tempMarker = $mapInternals.makeMarker(data.lat,data.lng,"temporary");
			temporaryMarkers.push(tempMarker);
		};
		
		//LOADER
		
		function setupLoader(){
			$loaderImage.hide();
		};
		
			$pm.showLoader = function(){
				$changeLocationButton.hide();
				$zoomInButton.hide();
				$zoomOutButton.hide();
				$changeLocationForm.hideForm();
				$loaderImage.show();
				$pm.children(".controls_header").css("overflow","hidden").stop().animate({height:"100%"},250);
			};
			
			$pm.hideLoader = function(){
				hideLoader();
			};
		
			function hideLoader(){
				$loaderImage.hide();
				$cancel_button.hide();
				$pm.children(".controls_header").css("overflow","hidden").animate({height:"0px"},250,function(){
					$zoomInButton.css({"width":"22px","opacity":0}).show().animate({"opacity":1});
					$zoomOutButton.css({"width":"22px","opacity":0}).show().animate({"opacity":1});
					$changeLocationButton.css("opacity",0).show().removeClass("disabled").animate({"opacity":1});
				});
			};
		
		//locationDialogInternals
		
		function setupLocationDialog(){
			$changeLocationForm.isVisible = false;
			$changeLocationButton.bind("click",_changeLocationButtonClickHandler);
			
			$cancel_button.bind("click",_cancelChangeLocationButtonClickHandler);
			$map_button.bind("click",_mapButtonClickHandler);
			$location_dropdown.bind("change",_locationDropdownChangeHandler);
			$location_text.bind("focus",_locationTextFocusHandler);
			$location_text.bind("blur",_locationTextBlurHandler);
			$location_text.bind("keypress",_locationTextKeypressHandler);
			if($location_text.attr("value").length == 0){
				$location_text.attr("value","Search worldwide.");
			};
			
			$location_radiobuttons = jQuery(jQuery.map($changeLocationForm.children(".radio_buttons").children("input"),function($t){
				$t = jQuery($t);
				jQuery($t).bind("change",function(){
					_selectRadioButtonHandler($t.value);
				});
				$t.deselect = function(){
					$t.attr("checked",false);
				}; 
				return $t;
			}));
			
			$location_form_status.hide();
		};
			
			function showLocationDialog(){
				$zoomInButton.css("width","0px");
				$zoomOutButton.css("width","0px");
				$changeLocationForm.showForm();
				$cancel_button.show();
				$changeLocationButton.stop().animate({"opacity":.1}).addClass("disabled");
				$pm.children(".controls_header").animate({height:"100%"},250,function(){
					
				});
			};
			function hideLocationDialog(){
				$changeLocationForm.hideForm();
				$changeLocationButton.css("opacity",1).removeClass("disabled");
				$cancel_button.hide();
				$pm.children(".controls_header").animate({height:"0px"},250).css("overflow","hidden");
				$zoomInButton.css("width","22px");
				$zoomOutButton.css("width","22px");
			};
			
			function _changeLocationButtonClickHandler(e,ui){
				e.preventDefault();
				if($changeLocationForm.isVisible == false){
					showLocationDialog();
				};
			};
			
			$changeLocationForm.showForm = function(){
				this.show();
				this.isVisible = true;
			};
			$changeLocationForm.hideForm = function(){
				this.hide();
				this.isVisible = false;
			};
		
			function _cancelChangeLocationButtonClickHandler(e,ui){
				e.preventDefault();
				ns11mmPresentation.trigger("cancelEvent");
			};
		
			$cancel_button.hide = function(){
				this.css("width","0px");
			}; $cancel_button.hide();
		
			$cancel_button.show = function(){
				this.css("width","79px");
			};
		
			$pm.cancel = function(){
				if($changeLocationForm.isVisible == true){
					hideLocationDialog();
				} else {
					hideLoader();
				}
			};
			
			function _mapButtonClickHandler(){
				submitChanges();
			};
			
			function _locationDropdownChangeHandler(){
				$location_text.attr("value","Search worldwide.");
				$location_radiobuttons.each(function(i,j){
					j.deselect();
				});
			};
			
			function _locationTextFocusHandler(e,ui){
				if($location_text.attr("value") == "Search worldwide."){
					$location_text.attr("value","");
				};
			};
			
			function _locationTextBlurHandler(e,ui){
				if($location_text.attr("value").length == 0){
					$location_text.attr("value","Search worldwide.");
				};
			};
			
			function _locationTextKeypressHandler(e){
				if(e.which == 13){
					e.preventDefault();
					submitChanges();
				} else {
					$location_radiobuttons.each(function(i,j){
						j.deselect();
					});
					$location_dropdown.children("option[value='']").attr("selected",true);
				};
			};
			
			function _selectRadioButtonHandler(value){
				$location_text.attr("value","Search worldwide.");
				$location_dropdown.children("option[value='']").attr("selected",true);
			};
			
			$location_form_status.status = function(status){
				if(status == "loading"){
					this.children("p").hide();
					this.children("img").show();
				} else {
					this.children("img").hide();
					this.children("p").text(status);
				};
			};
			
			function submitChanges(){
				var data = {};
				data.type='search';
				data.query = null;
				$location_radiobuttons.each(function(i,j){
					if(j.attr("checked") == true){
						data.query = 'nearby:"'+j.attr('value')+'" approved:true';
					};
				});
				if(data.query == null){
					if($location_dropdown.attr("value") != ""){
						data.query = $location_dropdown.attr('value')+' approved:true';
					} else if($location_text.attr("value") != ""){
						data.query = 'nearby:"'+$location_text.attr('value')+'" approved:true';
					} else {
						hideLocationDialog();
						return false;
					};
				};
				ns11mmPresentation.trigger("locationSearchEvent",data);
			};
		
		//ZOOM Functions
		
		function setupZoomFunctions(){
			$zoomInButton.bind("click",_zoomInButtonClickHandler);
			$zoomOutButton.bind("click",_zoomOutButtonClickHandler);
		};
			
			
			$pm.setZoom = function(zoom){
				$mapInternals.setZoom(zoom);
			};
		
			function _zoomInButtonClickHandler(e,ui){
				e.preventDefault();
				userOverideZoom = true;
				$mapInternals.zoomIn();
			};
		
			function _zoomOutButtonClickHandler(e,ui){
				e.preventDefault();
				userOverideZoom = true;
				$mapInternals.zoomOut();
			};
		
		initialize();
		return $pm;
	}	
})(ns11mmPresentation);
