// map_functions.js
// Provide functionality for managing the map display
// Developed by Kyle Evans, 2007
// Revised by Rich Rarey
// REVISIONS:
// 090217 Changed function GotResponse() to display "not available" in a field 
//        when the database returns "-1". Also added error handling on that catches
//        when the user selects a demographic category without clicking on a public station in the map.
// 090318 Made globalMinZoom a variable that is used in function updateMarkers() to limit how far the user 
//        can zoom out and still see the coverage maps.
// ------------------------------------------------------------------------------------------

// Initial variables (with global map variable)
var map;
var globalLowFrequency = 87.9;
var globalHighFrequency = 107.9;
var globalMapCommercial = 1;
var activeOverlays = [];
var globalOverlayCounter = 0;
var currentStation;

// globalMinZoom is the variable that controls how far out a user can zoom and still have
// the coverage maps displayed.
// The higher the zoom is, the closer the zoom and the fewer stations will be in the viewable frame.
// Accroding to Kyle, he made the (arbitrary) decision to go with a zoom level of 7 because it seemed
// that anything smaller than that would really kill the server.  "But YMMV :-)" he says.
// We set it to 5, to see as much as the great state of Texas as possible.
var globalMinZoom = 5;
// ------------------------------------------------------------------------------------------

// Setting the transmitter icons
var icon_nonPTFP_FB = new GIcon();
icon_nonPTFP_FB.image = "http://www.nprlabs.org/nova/map_images/Icon_nonPTFP_FB.png";
icon_nonPTFP_FB.shadow = "http://www.nprlabs.org/nova/map_images/Icon_nonPTFP_transmitterShadow.png";
icon_nonPTFP_FB.iconSize = new GSize(18, 16);
icon_nonPTFP_FB.shadowSize = new GSize(18, 16);
icon_nonPTFP_FB.iconAnchor = new GPoint(6, 20);
icon_nonPTFP_FB.infoWindowAnchor = new GPoint(5, 1);

var icon_nonPTFP_FM = new GIcon();
icon_nonPTFP_FM.image = "http://www.nprlabs.org/nova/map_images/Icon_nonPTFP_FM.png";
icon_nonPTFP_FM.shadow = "http://www.nprlabs.org/nova/map_images/Icon_nonPTFP_transmitterShadow.png";
icon_nonPTFP_FM.iconSize = new GSize(18, 16);
icon_nonPTFP_FM.shadowSize = new GSize(18, 16);
icon_nonPTFP_FM.iconAnchor = new GPoint(6, 20);
icon_nonPTFP_FM.infoWindowAnchor = new GPoint(5, 1);

var icon_nonPTFP_FL = new GIcon();
icon_nonPTFP_FL.image = "http://www.nprlabs.org/nova/map_images/Icon_nonPTFP_FL.png";
icon_nonPTFP_FL.shadow = "http://www.nprlabs.org/nova/map_images/Icon_nonPTFP_transmitterShadow.png";
icon_nonPTFP_FL.iconSize = new GSize(18, 16);
icon_nonPTFP_FL.shadowSize = new GSize(18, 16);
icon_nonPTFP_FL.iconAnchor = new GPoint(6, 20);
icon_nonPTFP_FL.infoWindowAnchor = new GPoint(5, 1);

var icon_nonPTFP_FX = new GIcon();
icon_nonPTFP_FX.image = "http://www.nprlabs.org/nova/map_images/Icon_nonPTFP_FX.png";
icon_nonPTFP_FX.shadow = "http://www.nprlabs.org/nova/map_images/Icon_nonPTFP_transmitterShadow.png";
icon_nonPTFP_FX.iconSize = new GSize(18, 16);
icon_nonPTFP_FX.shadowSize = new GSize(18, 16);
icon_nonPTFP_FX.iconAnchor = new GPoint(6, 20);
icon_nonPTFP_FX.infoWindowAnchor = new GPoint(5, 1);

var icon_PTFP_FB = new GIcon();
icon_PTFP_FB.image = "http://www.nprlabs.org/nova/map_images/Icon_PTFP_FB.png";
icon_PTFP_FB.shadow = "http://www.nprlabs.org/nova/map_images/Icon_PTFP_transmitterShadow.png";
icon_PTFP_FB.iconSize = new GSize(18, 16);
icon_PTFP_FB.shadowSize = new GSize(18, 16);
icon_PTFP_FB.iconAnchor = new GPoint(6, 20);
icon_PTFP_FB.infoWindowAnchor = new GPoint(5, 1);

var icon_PTFP_FM = new GIcon();
icon_PTFP_FM.image = "http://www.nprlabs.org/nova/map_images/Icon_PTFP_FM.png";
icon_PTFP_FM.shadow = "http://www.nprlabs.org/nova/map_images/Icon_PTFP_transmitterShadow.png";
icon_PTFP_FM.iconSize = new GSize(18, 16);
icon_PTFP_FM.shadowSize = new GSize(18, 16);
icon_PTFP_FM.iconAnchor = new GPoint(6, 20);
icon_PTFP_FM.infoWindowAnchor = new GPoint(5, 1);

var icon_PTFP_FL = new GIcon();
icon_PTFP_FL.image = "http://www.nprlabs.org/nova/map_images/Icon_PTFP_FL.png";
icon_PTFP_FL.shadow = "http://www.nprlabs.org/nova/map_images/Icon_PTFP_transmitterShadow.png";
icon_PTFP_FL.iconSize = new GSize(18, 16);
icon_PTFP_FL.shadowSize = new GSize(18, 16);
icon_PTFP_FL.iconAnchor = new GPoint(6, 20);
icon_PTFP_FL.infoWindowAnchor = new GPoint(5, 1);

var icon_PTFP_FX = new GIcon();
icon_PTFP_FX.image = "http://www.nprlabs.org/nova/map_images/Icon_PTFP_FX.png";
icon_PTFP_FX.shadow = "http://www.nprlabs.org/nova/map_images/Icon_PTFP_transmitterShadow.png";
icon_PTFP_FX.iconSize = new GSize(18, 16);
icon_PTFP_FX.shadowSize = new GSize(18, 16);
icon_PTFP_FX.iconAnchor = new GPoint(6, 20);
icon_PTFP_FX.infoWindowAnchor = new GPoint(5, 1);

// ------------------------------------------------------------------------------------------
function init() {
	var xmlHttp; // Creating the xmlHttp variable
	map = new GMap2(document.getElementById("map"));  // Creating the map element
	map.addControl(new GSmallMapControl());  // Creating a control for scale
	map.addControl(new GMapTypeControl());  // Creating a control for map type (map, satellite, etc.)
	map.addControl(new GScaleControl());
	map.setCenter(new GLatLng(35.224773, -100.991943), 9);  // Initializing the center of the map

	updateMarkers();  // Call the updateMarkers method, finding and adding markers that appear within the viewable area

	// Method called when the user zooms on the map
	GEvent.addListener(map,'zoomend',function() {
		updateMarkers();											  
	});

	// Method called when the user moves the viewable area of the map
	GEvent.addListener(map,'moveend',function() {
		updateMarkers();
	});
}

// ------------------------------------------------------------------------------------------
// Method called when a user clicks on a quickview
function getQuickview() {
	var selectedQuickview = document.getElementById("quickviewOptions").value;  // Get the index of the selected quickview
	var quickLatitude = Col0[selectedQuickview];  // Look up the latitude
	var quickLongitude = Col1[selectedQuickview];  // and longitude
	var quickZoom = Col2[selectedQuickview];  // and zoom of the selected quickview index
	map.setCenter(new GLatLng(quickLatitude, quickLongitude));  // Set the center
	map.setZoom(quickZoom);  // and the zoom at the returned values
	updateMarkers();  // and recalculate the viewable markers
}

// ------------------------------------------------------------------------------------------
// Method called to update markers in the viewable area
function updateMarkers() { 
	document.getElementById('sidebar-list').innerHTML = '';  // Reset the sidebar list by setting the inner HTML to null

// Only update markers if the map is at a closer zoom level (controls the server load)
// On original source currentZoom had to be > 7 to reduce server workload.
	var currentZoom = map.getZoom();  
	if(currentZoom > globalMinZoom) {
		var i = 0;
		map.clearOverlays();  // Remove the existing points 
	
		var bounds = map.getBounds(); 	// Get the boundary for the data 
		var southWest = bounds.getSouthWest();  // Southwest boundary
		var northEast = bounds.getNorthEast();  // Northwest boundary
		// Format the boundary values for the xmlhttp request
		var getVars = 'ne=' + northEast.toUrlValue() + '&sw=' + southWest.toUrlValue() + '&high=' + globalHighFrequency + '&low=' + globalLowFrequency; 
		// GLog.writeUrl(url);  // Log the URL for testing 
		// Retrieve viewable points
		var request = GXmlHttp.create();  // Create an xmlHttp request
		request.open('GET', 'map_server.php?'+getVars, true);  // Open the page with the boundaries as input variables
		request.onreadystatechange = function() { 
			if (request.readyState == 4) { // When the request has been completed
				var jscript = request.responseText;  // Read the response text
				var points;  // Initialize the points variable
				eval(jscript);  // Parse the responseText, essentially creating the variable array 'points'
				for (i in points) {  // Iterate through the viewable point array
					var point = new GLatLng(points[i].lat,points[i].lng);  // Create the GLatLng object for the point
					var marker = createMarker(point,
											  points[i].city,
											  points[i].ptfpID,
											  points[i].service,
											  points[i].frequency,
											  points[i].stationClass,
											  points[i].callsign,
											  points[i].fileNumber,
											  points[i].licensee);  // Create the point using the GLatLng point object and information in the viewable point array
					// map.addOverlay(marker); 
				} 
			} 
		} 
		request.send(null);  // Send a null request when the function has completed

		// Redraw the active layers on the map
		if(globalOverlayCounter != 0) {
			for(i = 0; i <= globalOverlayCounter; i++){
				map.addOverlay(activeOverlays[i].geoXml);	
			}
		}
		updateActiveOverlays();

	}
	else {
		map.clearOverlays();  // Remove the existing points if the map is beyond the appropriate zoom level
	}
}


// ------------------------------------------------------------------------------------------
// This is a helper method to dynamically control mapping of commercial stations
function checkCommercial() {
	if(document.myForm.commOff.checked == true) {  // Check if commercial mapping is set to 'off'
		globalMapCommercial = 0;   // Set global variable to zero
		updateMarkers();  // Refresh the map - the change is caught in the createMarker method
	}
	else {
		globalMapCommercial = 1;  // Set global variable to one
		updateMarkers();  // Refresh the map
	}
}

// ------------------------------------------------------------------------------------------
// This function handles error checking for the input frequency ranges
function checkFrequency(inputLowFrequency, inputHighFrequency) {
	// Type casting the input variables
	var lowFrequency = inputLowFrequency - 0;
	var highFrequency = inputHighFrequency - 0;
	var error="";  // Declaring the initial error string

	// Checking for illegal characters
	var illegalChars= /(^\d+$)|(^\d+\.\d+$)/;
	if (!(illegalChars.test(lowFrequency))) {
		error += "* Please enter a positive digit for the Low Frequency field.\n";
	}
	if (!(illegalChars.test(highFrequency))) {
		error += "* Please enter a positive digit for the High Frequency field.\n";
	}
	
	// Checking for valid frequencies
	if((lowFrequency < 87.9) || (lowFrequency > 107.9)) {
		error += "* Valid Frequencies are 87.9 - 107.9.\n";
	}
	if((highFrequency < 87.9) || (highFrequency > 107.9)) {
		error += "* Valid Frequencies are 87.9 - 107.9.\n";
	}

	// Checking relative frequency position
	if(lowFrequency >= highFrequency) {
		error += "* Lower frequency has to be less than the upper frequency";
	}
		
	if (error != "") {
       alert(error);
    }
	else {
		// This is a klooge, but it works - ideally you'd retrieve the low and high frequencies with a 
		// document.getElementByID call, but for some reason I couldn't get that to work - this mimics
		// the functionality, in a slightly less elegant way.
		globalLowFrequency = lowFrequency;  // If everything passes muster, reset the global frequency variables
		globalHighFrequency = highFrequency;
		updateMarkers();  // Update the markers
	}
}

// ------------------------------------------------------------------------------------------
function createMarker(point,html,ptfpID,service,frequency,stationClass,callsign,fileNumber,licensee) {
	// Create a marker for the input point based on its PTFP status and service
	if(ptfpID  > 0 && service == "FM") { var marker = new GMarker(point, icon_PTFP_FM); } // PTFP - Full Service
	if(ptfpID  > 0 && service == "FX") { var marker = new GMarker(point, icon_PTFP_FX); } // PTFP - Translator
	if(ptfpID  > 0 && service == "FB") { var marker = new GMarker(point, icon_PTFP_FB); } // PTFP - Booster
	if(ptfpID  > 0 && service == "FL") { var marker = new GMarker(point, icon_PTFP_FL); } // PTFP - LP
	if(globalMapCommercial > 0) {
		if(ptfpID  < 1 && service == "FM") { var marker = new GMarker(point, icon_nonPTFP_FM); } // Non-PTFP - Full Service	
		if(ptfpID  < 1 && service == "FX") { var marker = new GMarker(point, icon_nonPTFP_FX); } // Non-PTFP - Translator		
		if(ptfpID  < 1 && service == "FB") { var marker = new GMarker(point, icon_nonPTFP_FB); } // Non-PTFP - Booster
		if(ptfpID  < 1 && service == "FL") { var marker = new GMarker(point, icon_nonPTFP_FL); } // Non-PTFP - LP
	}
	
	// Fill the sidebar content for PTFP station
	if(ptfpID > 0) {
		var listItem = document.createElement('li');  // Create the list element
		// var listItemLink = listItem.appendChild(document.createElement('a'));
		// listItemLink.href = "#"
		listItem.innerHTML = "<span class='style1'>" + callsign + " - " + frequency + " (" + stationClass + ") - " + service + "</span><br><span class='style3'>" + licensee + "<br><b>Station Coverage Overlay - </b></span><span class='style1'><input type='checkbox' id='" + callsign + "' onClick='toggleGeoXML(this.id, this.checked)'><br><hr></span>";

		
		var focusPoint = function() { 
			var markerHTML = '<div class="style1">' + callsign + '</div><div class="style3">Frequency - ' + frequency + '</div><div class="style3">Class - ' + stationClass + '</div><div class="style3">File Number - ' + fileNumber + '</div>';  /* Maybe some noncommercial image goes here */ 
			marker.openInfoWindowHtml(markerHTML); 
			showUser(callsign); // Passes the currently selected point into the showUser method, requesting relevant information for the bottom panel
			newStationSelected();
			getConstantFields(callsign);
			currentStation = callsign;
			return false;
		}; 

		GEvent.addListener(marker, 'click', focusPoint);
		// listItemLink.onclick = focusPoint;
		document.getElementById('sidebar-list').appendChild(listItem);	
		map.addOverlay(marker);
	}

	if(globalMapCommercial > 0) {
		if(ptfpID < 1) {
			/*
			var listItem = document.createElement('li');
			var listItemLink = listItem.appendChild(document.createElement('a'));
			listItemLink.href = "#"
			listItemLink.innerHTML = "<span class='style1'>" + callsign + "</span><br><span class='style3'>Frequency - " + frequency + "<br> Class - " + stationClass + "</span>";
			*/
			var focusPoint = function() { 
				var markerHTML = '<div class="style1">' + callsign + '</div><div class="style3">Frequency - ' + frequency + '</div><div class="style3">Class - ' + stationClass + '</div><div class="style3">File Number - ' + fileNumber + '</div>'; 
				marker.openInfoWindowHtml(markerHTML); 
				/* This is where the AJAX call to the table will go */
				newStationSelected();
				showUser(callsign); // Passes the currently selected point into the showUser method, recalling relevant information for the bottom panel
				return false;
			}; 
			
			GEvent.addListener(marker, 'click', focusPoint);
			// listItemLink.onclick = focusPoint;
			// document.getElementById('sidebar-list').appendChild(listItem);	
			map.addOverlay(marker);
		}
	}
} 

// ------------------------------------------------------------------------------------------
// This method toggles on and off the KML file (essentially the ITM coverage)
function toggleGeoXML(id, checked) {
  var i = 0;

  if (checked) {
    var geoXml = new GGeoXml('http://www.nprlabs.org/stationcoverage/' + id + '.kml');  // create a GGeoXml object from the properly formed URL
	activeOverlays[globalOverlayCounter] = {'id':id, 'geoXml':geoXml};
	globalOverlayCounter = globalOverlayCounter + 1;
	// stationCoverageOverlay[id].geoXml = geoXml;  // Add a reference to this object in the appropriate record's attributes
    map.addOverlay(geoXml);  // Add the overlay to the map
	updateActiveOverlays();
  } 
  /* Iterate through the activeOverlays layer, looking for the appropriate id match, then remove the geoXml reference */
  else {
    for(i = 0; i <= globalOverlayCounter; i++) {
		if(activeOverlays[i].id == id){
			map.removeOverlay(activeOverlays[i].geoXml);
			activeOverlays.splice(i,1);
			globalOverlayCounter = globalOverlayCounter - 1;  // I think this would be better handled by activeOverlays.length();
			updateActiveOverlays();
		}
	}
  }
  // alert(globalOverlayCounter);
}

// ------------------------------------------------------------------------------------------
function updateActiveOverlays(){
	// alert(globalOverlayCounter);
	document.getElementById('overlays-list').innerHTML = '';
// iterate through the activeOverlays variable
	if(globalOverlayCounter != 0) {
		for (i = 0; i <= globalOverlayCounter; i++) {
			var activeOverlay = document.createElement('li');  // Create the list element for the overlay
			// activeOverlay.innerHTML = activeOverlays[i].id;
			activeOverlay.innerHTML = "<span class='style1'><input type='checkbox' id='" + activeOverlays[i].id + "' onClick='toggleGeoXML(this.id, this.checked)' CHECKED> - " + activeOverlays[i].id + "<br><hr></span>";
			document.getElementById('overlays-list').appendChild(activeOverlay);
		}
	}
// activeOverlays

}

// ------------------------------------------------------------------------------------------
function clearActiveOverlays(){
// reinitialize the activeOverlays variable
// call updateActiveOverlays
}

// ------------------------------------------------------------------------------------------
function showUser(str) { 
	// var request = GXmlHttp.create();
	xmlHttp2=GetXmlHttpObject() // Creating the xmlHTTP object, with all relevant type-checking

	var url="map_selectedStation.php"; // Identifying the PHP page that handles the database call
	url=url+"?q="+str; // Forming the URL to include the relevant callsign
	url=url+"&sid="+Math.random(); // Adding a random number to prevent the server from using a cached file
	xmlHttp2.onreadystatechange = stateChanged;  // When there's a result from the query, call the stateChanged method and write it to the screen 
	xmlHttp2.open("GET",url,true); // Opens the XMLHTTP object with the given URL
	xmlHttp2.send(null); // Executing the query
}

// ------------------------------------------------------------------------------------------
function stateChanged()  { 
	if (xmlHttp2.readyState==4 || xmlHttp2.readyState=="complete") { 
		document.getElementById("stationHeader").innerHTML=xmlHttp2.responseText // If the state has changed, then replace the text of the div element with the returned information
	} 
}

// ------------------------------------------------------------------------------------------
// Creating the XMLHTTP object with all relevant type-checking and cross-browser compatability
function GetXmlHttpObject() {
	var xmlHttp=null;
	try {
		xmlHttp = new XMLHttpRequest(); // Firefox, Opera 8.0+, Safari
	}
	catch (e) {
		try {
			xmlHttp = new ActiveXObject("Msxml2.XMLHTTP"); // Internet Explorer
		}
		catch (e) {
			xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
		}
	}
	return xmlHttp;
}

// ------------------------------------------------------------------------------------------
function getConstantFields(str) { 
	
	xmlHttp=GetXmlHttpObject()
	if (xmlHttp==null) {
		alert ("Browser does not support HTTP Request");
		return
	}
	var url="map_getConstantFields.php";
	url=url+"?q="+str;
	url=url+"&sid="+Math.random();
	xmlHttp.onreadystatechange = showConstantFields; 
	xmlHttp.open("GET",url,true);
	xmlHttp.send(null);
}

// ------------------------------------------------------------------------------------------
function showConstantFields()  { 
	if (xmlHttp.readyState==4 || xmlHttp.readyState=="complete") { 

	var jscript = xmlHttp.responseText;  // Read the response text
	var result;  // Initialize the result variable
	eval(jscript);  // Parse the responseText, essentially creating the variable array 'points'

	for (i in result) {  // Iterate through the viewable point array
		var totalPop_1990 = result[i].totalPop_1990;
		var totalPop_2000 = result[i].totalPop_2000;
		var totalPop_2007 = result[i].totalPop_2007;
		var HHIncome_1990 = result[i].HHIncome_1990;
		var HHIncome_2000 = result[i].HHIncome_2000;
		var HHIncome_2007 = result[i].HHIncome_2007;
	}

	// Setting the values in the table
	document.getElementById("Row1Col1").innerHTML=totalPop_1990;
	document.getElementById("Row1Col2").innerHTML=totalPop_2000;
	document.getElementById("Row1Col3").innerHTML=totalPop_2007;
	document.getElementById("Row2Col1").innerHTML=HHIncome_1990;
	document.getElementById("Row2Col2").innerHTML=HHIncome_2000;
	document.getElementById("Row2Col3").innerHTML=HHIncome_2007;
	} 
}

// ------------------------------------------------------------------------------------------
function getRow(field,target){

	xmlHttp3=GetXmlHttpObject()
	var url="map_retrieveField.php";
	url=url+"?var="+field+"&call="+currentStation+"&target="+target;
	// url=url+"&sid="+Math.random();
	xmlHttp3.onreadystatechange = gotResponse; 
	xmlHttp3.open("GET",url,true);
	xmlHttp3.send(null);

}

// ------------------------------------------------------------------------------------------
function gotResponse()  { 
	if (xmlHttp3.readyState==4 || xmlHttp3.readyState=="complete") { 
	
	var sMessage = "No public station is selected on the map.\n\nPlease click on a public station on the map FIRST, \nthen select a demographic category from the pull-down table.";
	
	// Read the response text
	var jscript = xmlHttp3.responseText;  
  	
	// Initialize the result variable
	var result;
	// Initialize the field text variables
	var field_1990;
	var field_2000;
	var field_2007;
	
	// Our default text if there's no data in the database for a field
	var sNotAvailable = "<em>not available</em>";
	
	// Evaluate the responseText as if it was a command, which creates variable array 'points'.
	// If the user has NOT selected a public station, our data will be bad, so we'll
	// pop up an alert message and exit the function gracefully.
	try {
		eval(jscript);  
	}
	catch(e) {
		alert(sMessage);
		return;
	}
	
	// Iterate through the viewable point array.
	// If we get a -1, that means there's no data
	// for that field, and we'll substitute "not avail" text.
	for (i in result) {  
			// 1990 Census field
			if (result[i].field_1990 > -1) {
				field_1990 = result[i].field_1990;
			}
			else {
				field_1990 = sNotAvailable;
			}
			
		 	// 2000 Census field
			if (result[i].field_1990 > -1) {
				field_2000 = result[i].field_2000;
			}
			else {
				field_2000 = sNotAvailable;
			}
			
			// 2007 [estimated] census field
			if (result[i].field_2007 > -1) {
				field_2007 = result[i].field_2007;
			}
			else {
				field_2007 = sNotAvailable;
			}
			var target = result[i].target;
		}

	// just some scratch to show inputs and outputs
	// Put the field name into the targets
	cell1="Row"+target+"Col1";
	cell2="Row"+target+"Col2";
	cell3="Row"+target+"Col3";
	document.getElementById(cell1).innerHTML=field_1990;
	document.getElementById(cell2).innerHTML=field_2000;
	document.getElementById(cell3).innerHTML=field_2007;
	}
}

// ------------------------------------------------------------------------------------------
function newStationSelected() {
	document.getElementById("Row1Col1").innerHTML="-";
	document.getElementById("Row1Col2").innerHTML="-";
	document.getElementById("Row1Col3").innerHTML="-";
	document.getElementById("Row2Col1").innerHTML="-";
	document.getElementById("Row2Col2").innerHTML="-";
	document.getElementById("Row2Col3").innerHTML="-";
	document.getElementById("Row3Col1").innerHTML="-";
	document.getElementById("Row3Col2").innerHTML="-";
	document.getElementById("Row3Col3").innerHTML="-";
	
}

// ------------------------------------------------------------------------------------------
window.onload = init;

// END map_functions.js -------------------------------------