var loadDelay;		// allows message only to displaye if wait is more than 1 second
var myGlobalHandlers = {
onCreate: function(){
	clearTimeout(loadDelay);	
	loadDelay = setTimeout(function() {$D('showing animation'); Element.show('requesting_data')}, 1000);
},
onComplete: function() {
	clearTimeout(loadDelay);	
	$D('hiding animation')
	Element.hide('requesting_data');
}
};
Ajax.Responders.register(myGlobalHandlers);


window.onbeforeunload = function () {		// clears queue if user leaves page
   renderQueueClear();
}


/// If set to true, will lock results to those catagories
var catArts = true;
var catHotel = true;
var catShopping = true;
var catOutdoors = true;
var catDining = true;



function toggleLock(wOn) {
	
	lockresults = wOn;
	clearSearchUnits();
	if (wOn) {
		setCheckboxes();
	}
	else {
		displayUserMessage("You are now including points of interest outside of " + catName );
	}
	triggerRefresh();
}

var curLocation = 0;
var unitSetCheckBoxes = [ {} ];
var outdoorCategoryCheckBoxes = [  ];
var cuisineCategoryCheckBoxes = [  ];
var lastUnits = null;
/*
var SET_ARTS_N_CULTURE = 1;
var SET_HOTEL = 2;
var SET_SHOPPING = 3;
var SET_OUTDOORS = 4;
var SET_DINING = 5;
var SET_TROLLEY = 6;

var ARTS_CHECK  =1;
var HOTEL_CHECK  =2;
var DINING_CHECK = 3;
var OUTDOORS_CHECK = 4;
var SHOPPING_CHECK  =5;
var TROLLEY_CHECK  =6;
*/

var showalert = true;
var isMoving = false;	// set to true when user is moving map
var maxZoom = 5;		// lower number is farther out
var minZoom = 15;
var tooFar = false;

var currentZoom;

function checkZoomLevel() {
	if (map == null) return;
	var cZoom = map.getZoom();
	//$D("zoom: " + cZoom);
	if (cZoom < maxZoom) {
		tooFar = true;
	}
	else {
		tooFar = false;
	}
	if (tooFar && currentZoom != cZoom) {
		//map.setZoom(maxZoom);
		displayMessage("Results may be limited, please zoom in to recieve more results");
	}
	currentZoom = cZoom;
	
}
function fixupCheckboxes() {
	$J(".cbox").click(function() {
		var cCheck = $J(this).find("INPUT");
		cCheck.click();
	});
}

var map;
var mgr;
function Gload() {
	$D("gload");
	if (GBrowserIsCompatible()) {	  	
		map = new GMap2(document.getElementById("map"));		// throws IE error?
				
		if (startLat != 0 && startLong != 0)
			centerPoint = new GLatLng(startLat, startLong) 
		else
			centerPoint = new GLatLng(39.9466, -74.9213 ) 

		map.setCenter(centerPoint)

		if (startZoom > 0)
			map.setZoom(startZoom);	
		else 
			map.setZoom(10);
	
		fixupCheckboxes();
		
		map.addControl(new GMapTypeControl());
		map.addControl(new GLargeMapControl());	
		
		var points = [ ];
		var bounds = new GLatLngBounds(centerPoint, centerPoint);
		
					
		GEvent.addListener(map, "moveend", function() {
			checkZoomLevel();
		});			
		
		runAllInputs($('UnitSetSelector'), 'checkbox', function(obj) { 
			unitSetCheckBoxes.push(obj);
			Event.observe(obj, "click", function() {
				enableSpecificDropDowns();
				updateSelectedSet();
				setTimeout('setPoints();', 100);
			});
		});
		
		runAllInputs($('OutdoorSelector'), 'checkbox', function(obj) { 
			outdoorCategoryCheckBoxes.push(obj);
			Event.observe(obj, "click", function() {
				updateSelectedOutdoorCategories();
				setTimeout('setPoints();', 100);
			});
		});
		
		runAllInputs($('CuisineSelector2'), 'checkbox', function(obj) { 
			cuisineCategoryCheckBoxes.push(obj);
			Event.observe(obj, "click", function() {
				updateSelectedCuisineCategories();
				setTimeout('setPoints();', 100);
			});
		});
					
		updateSelectedSet();	
		updateSelectedOutdoorCategories();	
		updateSelectedCuisineCategories();
		
		$D("SEARCH POINTS: " + searchPoints.length );		

		if (catPoints.length > 0) {
			setupCategoryPage();
			enableSpecificDropDowns();			
		}
		else if (searchPoints.length > 0 ) { 
			setSearchPoints();		// set any initial search points
			enableSpecificDropDowns();
		}		
		else {
			generateMapItems();
			registerMapMoveHook();
			enableSpecificDropDowns();
		}
		
		var groundOverlay, imageURL;
		if (histOverlay)  {
			imageURL  = "/assets/images/historic/map-overlay2-thick.png";
			// SW, NE
			groundOverlay = new GGroundOverlay(imageURL, new GLatLngBounds(new GLatLng(39.94304166666667,  -75.15438055555556), new GLatLng(39.9574888888889,  -75.13733055555555)));
		   	map.addOverlay(groundOverlay);
			
		}

	}
	
	$D("gload done");
}


function createMapMarker(unit) {    

	var point = unit.Pos;
	var pinLabel = unit.pinLabel;
	var html;
	if (typeof(unit.LocationID) != "undefined" && unit.LocationID > 0)
	html = sprintf("<iframe src='/map/mapWindow.aspx?location=%s' width='290' height='170' scrolling='no' frameborder='0' class='segFrame' id='mapWin'></iframe>", unit.LocationID);
	else
	html = sprintf("<iframe src='/map/mapWindow.aspx?unit=%s' width='290' height='170' scrolling='no' frameborder='0' class='segFrame' id='mapWin'></iframe>", unit.UnitID);
	
	var icon = new GIcon();
	icon.shadow =  "/assets/images/maps/sjtc_icons/shadow.png";
	icon.iconSize = new GSize(23, 30);
	icon.shadowSize = new GSize(46, 31);
	icon.iconAnchor = new GPoint(6, 38);  

	icon.image = sprintf("/assets/images/maps/sjtc_icons/%s", GetMarkerImage(unit));
	$D("createMapMarker: " +  icon.image);

	icon.infoWindowAnchor = new GPoint(10, 10);
	var marker = new GMarker(point,{ icon: icon, title: pinLabel } );
	if (html == null) return marker;
	
	GEvent.addListener(marker, "click", function() {		
		marker.openInfoWindowHtml(html);
		setRenderPause(3000)
	});
	GEvent.addListener(marker, "click", function() {		// remove hook when automatic repositioning
		removeMapMoveHook();
	});
	return marker;
}


var mapHook, mapHookAdd
function removeMapMoveHook() {	// disables the hook for one move, then re-enables;
	$D("removeMapMoveHook");
	if (mapHookAdd) GEvent.removeListener(mapHookAdd);
	if (mapHook) GEvent.removeListener(mapHook);		
	mapHookAdd = GEvent.addListener(map, "moveend", function() {
			registerMapMoveHook();
	});	
}

function registerMapMoveHook() {
	$D("registerMapMoveHook");
	if (mapHookAdd) GEvent.removeListener(mapHookAdd);
	if (mapHook) GEvent.removeListener(mapHook);	
	mapHook = GEvent.addListener(map, "moveend", function() {						
			generateMapItems();
	});
}

var mapRequestPause = null;
var mapRequestTimeout = null;		// used to limit consequtive requests
var requestRateLimit = 10000;
var ajaxUnitRequest;
var ajaxSearchRequest;

var preventMapRequest = false;
function generateMapItems(isDelay) {	
  if (!GBrowserIsCompatible()) return;
  if (tooFar) return;
  
  if (!preventMapRequest) {
	  	controlledMapRequest()
		preventMapRequest = true;
		
    	if (mapRequestPause) clearTimeout(mapRequestPause);		
		mapRequestPause = setTimeout(function() {preventMapRequest = false;},requestRateLimit);	
  }
  else {
	  $D("request cancelled: too soon, queing request")
	  if (mapRequestTimeout) clearTimeout(mapRequestTimeout);		
	  mapRequestTimeout = setTimeout(function() {preventMapRequest = false; $D("--DELAYED REQUEST"); generateMapItems();},requestRateLimit);	  
  }

 // mapRequestTimeout = setTimeout(function() {controlledMapRequest()},requestRateLimit);
}

function controlledMapRequest() {		// gets all units in bounds
  if (!GBrowserIsCompatible()) return;
  if (lockresults) {
	  $D("results locked : no request");
	  setPoints();
	  return;
  }
  if (true) {
	Element.hide('requesting_data');
	$D('controlledMapRequest: Requesting from server.');
	var bounds = map.getBounds();
	var northeast = bounds.getNorthEast();
	var southwest = bounds.getSouthWest();
	var pars = sprintf('request=unitregion&northeast-lat=%d&northeast-lng=%d&southwest-lat=%d&southwest-lng=%d', 
		northeast.lat(), northeast.lng(), 
		southwest.lat(), southwest.lng());


	//$D('Requesting url: /map/MapsAjaxHandler.aspx?' + pars);
	if (ajaxUnitRequest) ajaxUnitRequest.transport.abort();
	ajaxUnitRequest = new Ajax.Request( "/map/MapsAjaxHandler.aspx", { method: 'get', onlyLatestOfClass: 'units', parameters: pars, onComplete: function(originalRequest) {
		var response = originalRequest.responseText;
		//$D("MAP RESPONSE: " + response)		
		if (response == "") {	// BUG? return's empty string if server is busy?
		//	displayMessage("Server busy");
			return;
		}
		setPoints(eval(response));
		
		ajaxUnitRequest = null;
	  }
	});
  }
  else
  {
	$D('Value from cache');
	setPoints();
  }
}




var displayedMarkers = new Object;
var displayedMarkersQIndex = new Object;
var renderQueue = new Array();
var renderQueueIndex = 0;

var showOnce = true

function renderQueueExec() {
	if (pauseRendering) return;
	//if (mgr == null) mgr = new GMarkerManager(map);		// marker manager causes blinking
	//$D("QUEUELENGTH: " + renderQueue[renderQueueIndex]);
	
	if (renderQueueIndex < renderQueue.length) {
		if (renderQueue[renderQueueIndex] != null ) {
			map.addOverlay(renderQueue[renderQueueIndex]);
 			//mgr.addMarker(renderQueue[renderQueueIndex], maxZoom);
			//mgr.refresh();			
			//$D(sprintf('RenderQueue %s/%s', renderQueueIndex, renderQueue.length))
			renderQueueIndex++;
			renderNum++;
		}
		else {
			renderQueueIndex++;
			renderQueueExec()
		}
		
		if (renderQueue.length == 1 && showOnce) {		// if one item, open window
			
			GEvent.trigger(renderQueue[0], "click")
			showOnce = false;
		}
		renderQueue[renderQueueIndex - 1] = null;	
	}
	
}

function renderQueueAdd(unitID, wMarker) {
	displayedMarkers[unitID] = wMarker;	
	displayedMarkersQIndex[unitID] = renderQueue.length;
	renderQueue.push(wMarker);
}

function renderQueueRemove(unitID) {
	map.removeOverlay(displayedMarkers[unitID]); 
	displayedMarkers[unitID] = null;
	renderQueue[displayedMarkersQIndex[unitID]] = null;
}

function renderQueueClear() {
	renderQueue = null;
	renderQueue = new Array();	
	renderQueueIndex = 0;
}


var pauseRendering = false
var renderNum = 0;
var renderInterval = 300;
var speedCheckInterval = 12;
setInterval(renderQueueExec,renderInterval);		// calls render queue repeatedly to show units
setInterval(renderSpeedCheck,renderInterval * speedCheckInterval);		// sets render speed 

function renderSpeedCheck() {	// if rendering every second, pause 
	if (renderNum/speedCheckInterval >= 1) setRenderPause(2000);
	renderNum = 0;
}

function setRenderPause(rWait) {
	$D("PAUSING RENDER: " + rWait);
	pauseRendering = true;
	setTimeout(function() {pauseRendering = false}, rWait); 
}


var displayedUnits = new Object;		// USED TO ONLY RENDER NEW UNITS // doesntExist = null; removeFromMap = false; keepOnMap = true;
var displayedSearchUnits = new Object;		// USED TO ONLY RENDER NEW UNITS // doesntExist = null; removeFromMap = false; keepOnMap = true;
function setPoints(units) { // parses units and sets them according to category
	$D("lock to cat: " + lockresults);
	$D("setPoints");
	if (!units) units = lastUnits;
	if (!lockresults) {
		if (!units) return generateMapItems();	
	}
	lastUnits = units;
	var dateObj = new Date();
	
	
	var unitDisplayed = 0;

	for(x in displayedUnits) {	// mark all existing units as false 
		if (displayedUnits[x] == true)	{
			displayedUnits[x] = false;		
		}
	}

	for (var i = 0; i < catPoints.length; i++) {		// CATEGORIES
		var unit = catPoints[i];
		if (!unitInSelectedSets(unit)) continue;
		
		if (displayedUnits[unit.UnitID] == false) {		// if already exists, set to true to keep it
			displayedUnits[unit.UnitID] = true;		
		}
		if (displayedUnits[unit.UnitID] != true && unitIsVisible(unit)) {		// if unit doesn't exist, create it
			var marker = createMapMarker(unit);			
			if (marker != null) {
				unitDisplayed++;
				//$D("ADDING: " + unit.UnitID);
				displayedUnits[unit.UnitID] = true;				// set all refound units as true
				renderQueueAdd(unit.UnitID, marker)
			}
		}
	}	
	if (!lockresults && units) {		// if results are locked only show things in the category
	$D("displaying regional units");
	$D(sprintf('Received %d units.', units.length));
		for (var i = 0; i < units.length; i++) {
			var unit = units[i];
			if (!unitInSelectedSets(unit)) continue;
			
			if (displayedUnits[unit.UnitID] == false) {		// if already exists, set to true to keep it
				displayedUnits[unit.UnitID] = true;		
			}
			if (displayedUnits[unit.UnitID] != true && unitIsVisible(unit)) {		// if unit doesn't exist, create it
				var marker = createMapMarker(unit);			
				if (marker != null) {
					unitDisplayed++;
					//$D("ADDING: " + unit.UnitID);
					displayedUnits[unit.UnitID] = true;				// set all refound units as true
					renderQueueAdd(unit.UnitID, marker)
				}
			}
		}
	}	
	for(x in displayedUnits) {								// remove all marker still set to false
		if (displayedUnits[x] == false)	{
		//	$D("REMOVING: " + x);
			displayedUnits[x] = null;
			renderQueueRemove(x);
		}	
	}

  var dateObj2 = new Date();
 $D(sprintf('setPoints took: %s ms, render queue now has %s', dateObj2-dateObj, renderQueue.length ));
}

function clearSearchUnits() {
	for(x in displayedSearchUnits) {								// remove all marker still set to false
		if (displayedSearchUnits[x] == true)	{
		//	$D("REMOVING: " + x);
			displayedSearchUnits[x] = null;
			renderQueueRemove(x);
		}	
	}
}

function unitIsVisible(unit) {
	return map.getBounds().contains(unit.Pos);
}

var categoryUnits = new Object;
function setupCategoryPage() {	// parses searchPoints and sets them
	lockResults = true;
	
	if (mapHook) GEvent.removeListener(mapHook);	
	
	$D("generate cat points");
	if (!catPoints || catPoints.length == 0) return;
	
	lockResults = true;
	$("togLock").style.visibility = "visible";
	var bounds = new GLatLngBounds(catPoints[0].Pos, catPoints[0].Pos);

	catPoints.each(function(item, index) {
		if (item)  {			
			var marker = createMapMarker(item);
			bounds.extend(item.Pos);
			renderQueueAdd(item.UnitID, marker)		
			displayedUnits[item.UnitID] = true;				// add to display allow them to be removed on unchecking
			categoryUnits[item.UnitID] = true;
		}
	}) 
	
	if (startLat == 0 || startLong == 0 || startZoom == 0) {
		
		map.setZoom(Math.min(map.getBoundsZoomLevel(bounds),minZoom));
		map.setCenter(bounds.getCenter());
	}

	Element.hide('requesting_data');
	$D("generate search results done");
	registerMapMoveHook();
	generateMapItems();

}



function setSearchPoints() {	// parses searchPoints and sets them
	if (mapHook) GEvent.removeListener(mapHook);	
	
	$D("generate search results");
	if (!searchPoints || searchPoints.length == 0) return;
	var bounds = new GLatLngBounds(searchPoints[0].Pos, searchPoints[0].Pos);

	searchPoints.each(function(item, index) {
		if (item)  {			
			var marker = createMapMarker(item);
			bounds.extend(item.Pos);
			renderQueueAdd(item.UnitID, marker);
			displayedSearchUnits[item.UnitID] = true;				// add to display allow them to be removed on unchecking
		}
	}) 
	
//	map.setZoom(Math.min(Math.max(map.getBoundsZoomLevel(bounds), maxZoom),minZoom));
//	map.setZoom(map.getBoundsZoomLevel(bounds));
	map.setZoom(Math.min(map.getBoundsZoomLevel(bounds),minZoom));
	map.setCenter(bounds.getCenter());

	Element.hide('requesting_data');
	$D("generate search results done");
	registerMapMoveHook();

}

function clearRequests() {
	if (ajaxUnitRequest) ajaxUnitRequest.transport.abort();
	if (ajaxSearchRequest) ajaxSearchRequest.transport.abort();
}

function displayMessage(wMessage) {
	var searchResultsDiv = $('searchResultsMessage');
	searchResultsDiv.innerHTML = wMessage;
	searchResultsDiv.style.display = 'block';
	setTimeout(function() { searchResultsDiv.style.display='none'; }, 3000);	
}

function displayUserMessage(wMessage) {
	var userDiv = $('userMessage');
	userDiv.innerHTML = wMessage;
	userDiv.style.display = 'block';
	setTimeout(function() { userDiv.style.display='none'; }, 3000);	
}
							
	
function goSearch() {
	var searchTerm = $F('mapSearch');
	
	if (searchTerm == "" || searchTerm == null) {
		displayMessage("Please enter a search term");
		return;
	}	
	
	
	renderQueueClear();
	clearCheckboxes();
	clearRequests();
	
	showOnce = true;
	

	var pars = sprintf('request=search&term=%s', searchTerm);

	map.clearOverlays();
	Element.show('requesting_data');
	ajaxSearchRequest = new Ajax.Request( "/map/MapsAjaxHandler.aspx", { method: 'get', onlyLatestOfClass: 'search', parameters: pars, onComplete: function(originalRequest) {
		
		var response = originalRequest.responseText;
		//$D("SEARCH RESULTS:"  + response)
		eval(sprintf('searchPoints = %s.compact()', response ));
		displayMessage(sprintf('Your search returned %d result%s.', searchPoints.length, (searchPoints.length == 1 ? '' : 's')));
		setSearchPoints();
		generateMapItems();
		ajaxSearchRequest = null;
	  }
	});
}



