var map;  				// The large map
var minimap;			// The search map
var theChosenMarker;	// Will contain a reference to the "chosen" marker
var userMark;			// An arrow the user can click and drag
var polyBoundary;		// The most recent shape drawn on the map
var currentID = 0;  	// The ID of the last marker selected
var onloadZoom = 0;		// Keep track of what hike to show after loading.
						// 0 = newest hike

var mCount = 0;
var mArray = new Array();
var lArray = new Array();

// Data is accessed through these PHP file
var dataURL = "data.php";



/* Map parameters to view Washington State on a 750x500 pixel map */
var stateLatitude = 47.5542;
var stateLongitude = -121.5307;
var stateZoom = 7;

/* Map parameters to view Washington State on a 300x200 pixel map */
var searchLatitude = 47.3;
var searchLongitude = -120.8;
var searchZoom = 5;

/* Zoom level for viewing individual trails. */
var trailZoom = 10;




/* GIcon objects used by GMarkers. */
var greenIcon = makeIcon("green");			// Used for each trailhead
var green2Icon = makeIcon("green2");		// Alternate trailhead icon when this is a good month
var greenGlowIcon = makeIcon("greenGlow");	// Used to highlight a marker
var arrowIcon = makeIcon("arrow");			// Used for the search map

/* Make an icon based on the folder the icon information is in. */
function makeIcon(color) {
	var xMarker = new GIcon();
	xMarker = new GIcon();
	xMarker.image = "markers/"+color+"/marker.png";
	xMarker.iconSize = new GSize(20, 34);
	xMarker.shadow = "markers/"+color+"/shadow.png";
	xMarker.shadowSize = new GSize(37, 34);
	xMarker.iconAnchor = new GPoint(9, 34);
	xMarker.infoWindowAnchor = new GPoint(9, 34);
	xMarker.printImage = "markers/"+color+"/markerie.gif";
	xMarker.printShadow = "markers/"+color+"/shadowie.gif";
	xMarker.mozPrintImage = "markers/"+color+"/markerff.gif";
	xMarker.mozPrintShadow = "markers/"+color+"/shadowff.gif";
	return xMarker;
}

/* Do the initial set up of the Google Map */
function load(id) {
	if (GBrowserIsCompatible()) {
		
		//// Figure out which hike to display ////
		onloadZoom = (isNaN(id)) ? 0 : parseInt(id);
		
		//// Initialize Main Map ////
		map = new GMap2(document.getElementById("big_map"));
		map.addControl(new GLargeMapControl());
		map.addControl(new GScaleControl());
		map.addControl(new GMapTypeControl());
		zoomState();
		map.enableContinuousZoom();
		map.enableDoubleClickZoom();
		
		//// Initialize Search Map ////
		minimap = new GMap2(document.getElementById("minimap"));
		minimap.addControl(new GSmallMapControl());
		minimap.setCenter(new GLatLng(searchLatitude, searchLongitude), searchZoom);
		// Add listener for minimap click
		GEvent.addListener(minimap, "click", function(marker, point) {
			if (!userMark) {
				userMark = new GMarker(point, {icon: arrowIcon, draggable: true});
				minimap.addOverlay(userMark);
				updateMiniMap();
				
				GEvent.addListener(userMark, "dragend", function() {
					updateMiniMap();
				});
			}
		});
		
		map.addMapType(G_PHYSICAL_MAP);
		map.setMapType(G_PHYSICAL_MAP);
		
		//// Load the markers ////
		loadStateMap();
		
	} // End of "if (GBrowserIsCompatible())"
}

function zoomState() {
	map.setCenter(new GLatLng(stateLatitude, stateLongitude), stateZoom);
}

//////// State Map Functions ////////

function triggerReloadStateMapButton() {
	loadStateMap();
}

/** Display the state map on the big map */
function loadStateMap() {
	
	displayInfo("Loading state map...");
	
	removeAllMarkers();
	
	theChosenMarker = null;
	
	// http://developer.apple.com/internet/webcontent/xmlhttpreq.html
	var request = GXmlHttp.create();
	request.open("GET", dataURL);
	request.onreadystatechange = function() {
		
		// This code only runs once the data is retrieved.
		// if (request.readyState == "completed")
		if (request.readyState == 4) {
			
			var output = "";
			
			// Display new markers
			var response = request.responseText;
			var rows = response.split("\n");
			for (var i=0; i<rows.length-1; i++) {
				var record = rows[i];
				var data = record.split("|");
				if (data.length == 10) { // If there is the correct number of fields (a simple safety)
					if (data[1] * data[2] != 0) { // If latitude and longitude are not zero
						addNewMarker(data);
					}
				}
			}
			
			displayResult(output);
			displayInfo("Finished loading state map.");
			
			if (onloadZoom) {
				loadTrail(onloadZoom, false);
			} else {
				loadWeeklyTrail(false);
				zoomState();
			}
			onloadZoom = 0;
			
		}
	};
	
	request.send(null);
	
}

/* variable "data" is an array containing information in the order
 * displayed on spots.php and returns that information formatted for HTML. */
function makeHTML(data) {
	var id = data[0];
	var latitude = data[1];
	var latitude = data[2];
	var title = data[3];
	var city = data[4];
	var state = "WA";
	var difficulty = data[5];
	var roundtrip = data[6];
	var elevation = data[7];
	var hike_months = data[8];
	var hike_now = data[9];
	
	var result = "";
	if (title != "") {
		result += "<div class='info2' align='left'><b>"+title+"</b>";
	}
	if (city != "") {
		result += "<br />Near "+city+", "+state+"";
	}
	result += "<br />Difficulty: ";
	for (var i = 0; i < difficulty; i++) {
		result += '<img src="images/star.gif" />';
	}
	result += "<br />Round Trip: " + roundtrip + " "+((roundtrip == 1) ? "mile" : "miles")+"";
	result += "<br />Elevation Gain: " + checkMinimal(elevation);
	
	if (hike_months != "") {
		result += "<br />Best time to hike:";
		result += "&nbsp;&nbsp;" + hike_months;
	}
	
	result += "</div>";
	
	result += '<div class=info><b><a href="javascript:void(loadTrail(' + id + '))">View Details</a></b></div>';
	
	return result;
}

/* Remove all markers and listeners from the map. */
function removeAllMarkers() {
	while (lArray.length > 0) {
		GEvent.clearInstanceListeners(mArray[lArray.length-1]);
		mArray.pop();
	}
	
	map.clearOverlays();
	
	mCount = 0;
}

function addNewMarker(data) {
	var point = new GLatLng(data[1],data[2]);
	var marker;
	
	// Determine how marker is displayed
	if (data[9] == 1) {
		marker = new GMarker(point, {icon: green2Icon});
	} else {
		marker = new GMarker(point, {icon: greenIcon});
	}
	
	map.addOverlay(marker);
	mArray[data[0]] = marker;
	mCount++;
	
	/* Original
	map.addOverlay(marker);
	mArray[mCount++] = marker;
	*/
	
	// Add listener
	GEvent.addListener(marker, "click", function() {
		marker.openInfoWindowHtml(makeHTML(data));
	});
}

//////// Search Functions ////////

/** Display the state map on the big map */
function loadSearchMap() {
	
	if (!validate()) {
		return;
	}
	
	displayInfo("Loading search results...");
	
	var form = document.search_form;
	
	removeAllMarkers();
	
	theChosenMarker = null;
	
	// Extra URL information
	var extraURL = "?";
	
	if (form.check_map.checked) {
		extraURL += "check_map=yes&";
		extraURL += "latitude=" + form.latitude.value + "&";
		extraURL += "longitude=" + form.longitude.value + "&";
		extraURL += "distance=" + form.distance.value + "&";
	}
	if (form.check_city.checked) {
		extraURL += "check_city=yes&";
		extraURL += "dropdown_city=" + form.dropdown_city.value + "&";
	}
	if (form.check_difficulty.checked) {
		extraURL += "check_difficulty=yes&";
		extraURL += "dropdown_difficulty_proximity=" + form.dropdown_difficulty_proximity.value + "&";
		extraURL += "dropdown_difficulty=" + form.dropdown_difficulty.value + "&";
	}
	if (form.check_roundtrip.checked) {
		extraURL += "check_roundtrip=yes&";
		extraURL += "dropdown_roundtrip_proximity=" + form.dropdown_roundtrip_proximity.value + "&";
		extraURL += "text_roundtrip=" + form.text_roundtrip.value + "&";
	}
	if (form.check_elevation.checked) {
		extraURL += "check_elevation=yes&";
		extraURL += "dropdown_elevation_proximity=" + form.dropdown_elevation_proximity.value + "&";
		extraURL += "text_elevation=" + form.text_elevation.value + "&";
	}
	if (form.check_months.checked) {
		extraURL += "check_months=yes&";
		extraURL += "dropdown_month=" + form.dropdown_month.value + "&";
	}

	
	// http://developer.apple.com/internet/webcontent/xmlhttpreq.html
	var request = GXmlHttp.create();
	request.open("GET", dataURL + extraURL);
	request.onreadystatechange = function() {
		
		// This code only runs once the data is retrieved.
		// if (request.readyState == "completed")
		if (request.readyState == 4) {
			
			var output = "<div class=info4>Search Results</div>";
			output += "<table width='100%' border='0' class='uinfo2'>\n";
			output += "<tr bgcolor='#333333' class='info_white' align='left'><th></th><th>Hike Title</th><th>City</th><th>Difficulty</th><th>Round Trip</th><th>Elevation Gain</th><th>Best Months</th></tr>\n";
			
			// Display new markers
			var response = request.responseText;
			var rows = response.split("\n");
			for (var i=0; i<rows.length-1; i++) {
				var record = rows[i];
				var data = record.split("|");
				if (data.length == 10) { // If there is the correct number of fields (a simple safety)
					if (data[1] * data[2] != 0) { // If latitude and longitude are not zero
						addNewMarker(data);
						output += "<tr align='left'>";
						output += '<td class=info2><a href="javascript:void(loadTrail(' + data[0] + '))">Info</a>';
						output += "<td class=info2 width='100px'>"+data[3]+"</td>";
						output += "<td class=info2 width='100px'>"+data[4]+"</td>";
						output += "<td class=info2>"+stars(data[5])+"</td>";
						output += "<td class=info2>"+data[6]+" "+((data[6] == 1) ? "mile" : "miles")+"</td>";
						output += "<td class=info2>"+checkMinimal(data[7])+"</td>";
						output += "<td class=info2>"+data[8]+""+((data[9] == 1) ? " (now)" : "")+"</td>";
						output += "</tr>";
					}
				}
			}
			
			output += "</table>\n";
			displayResult(output);
			displayInfo("Finished loading search results.");
			
			zoomState();
			
			location.hash = "map"
		}
	};
	
	request.send(null);
	
}

	/* Represent a number by stars. */
	function stars(value) {
		var result = "";
		for (var i = 0; i < value; i++) {
			result += '<img src="images/star.gif" alt="*" />';
		}
		return result;
	}

   /* Make sure that all search criteria are filled out. */
   function validate() {
      
	  var form = document.search_form;
	  
      if (form.check_map.checked) {
	     if (userMark == null) {
		    alert("Please click on the map to choose a location to search at.");
			return false;
		 }
	  }
	  
      if (form.check_city.checked) {
	     if (form.dropdown_city.value == "") {
		    alert("Please choose a city to search near.");
			return false;
		 }
	  }
	  
      if (form.check_difficulty.checked) {
	     // Nothing can go wrong with the difficulty
	  }
	  
      if (form.check_roundtrip.checked) {
	     if (form.text_roundtrip.value.match(/^\d*\.?\d+$/)) {
		 	// User entered a valid number
		 } else {
		    alert ("Please make sure \"rount trip distance\" is a valid number.\nA valid number can be a decimal, but cannot be negative.");
		 	return false;
		 }
	  }
	  
      if (form.check_elevation.checked) {
	     if (form.text_elevation.value.match(/^-?\d+$/)) {
		 	// User entered a valid number
		 } else {
		    alert ("Please make sure \"elevation gain\" is a valid number.\n A valid number can be negative, but cannot be a decimal.");
		 	return false;
		 }
	  }
	  
      if (form.check_months.checked) {
	     // Nothing can go wrong with the month search
	  }
	  
	  return true;
   }
   
   /* Given the name of a criteria, enable or disable the components related to that criteria. */
   function allowEntry(criteria) {
      
	  var form = document.search_form;
	  
      switch(criteria) {
	     case "map":
		    // If check box is checked, then disabled = false
		    var disabled = !(form.check_map.checked);
			form.distance.disabled = disabled;
		    break;
		 case "city":
		    // If check box is checked, then disabled = false
		    var disabled = !(form.check_city.checked);
			form.dropdown_city.disabled = disabled;
		    break;
	     case "difficulty":
		    // If check box is checked, then disabled = false
		    var disabled = !(form.check_difficulty.checked);
			form.dropdown_difficulty_proximity.disabled = disabled;
			form.dropdown_difficulty.disabled = disabled;
		    break;
		 case "roundtrip":
		    var disabled = !(form.check_roundtrip.checked);
			form.dropdown_roundtrip_proximity.disabled = disabled;
			form.text_roundtrip.disabled = disabled;
		    break;
		 case "elevation":
		    var disabled = !(form.check_elevation.checked);
			form.dropdown_elevation_proximity.disabled = disabled;
			form.text_elevation.disabled = disabled;
		    break;
		 case "months":
		    var disabled = !(form.check_months.checked);
			form.dropdown_month.disabled = disabled;
		    break;
	  }
	  
   }
   
   /* When the user presses the reset button or reloads the page, reset the
    * disabled property of the HTML form items.
	* 
	* A reset button was not used because the reset button action happened the
	* onclick action. This code resets the check boxes in the correct order.
	*/
   function resetCheckBoxes() {
      
	  var form = document.search_form;
	  
	  form.check_map.checked = false;			allowEntry("map");
	  form.check_difficulty.checked = false;	allowEntry("difficulty");
	  form.check_roundtrip.checked = false;		allowEntry("roundtrip");
	  form.check_elevation.checked = false;		allowEntry("elevation");
	  form.check_months.checked = false;		allowEntry("months");
   }
   
   
function updateMiniMap() {
	if (userMark != null) {
		document.search_form.latitude.value = userMark.getPoint().y;
		document.search_form.longitude.value = userMark.getPoint().x;
		var radius = document.search_form.distance.value;
		drawShape(userMark.getPoint(), radius);
	}
}

//////// Trail of Week ////////


function triggerTrailOfTheWeekButton() {
	loadWeeklyTrail(true);
}

/* Load and display information about a specific trail.
 *
 * redirect (boolean) - redirect to text?
 */
function loadWeeklyTrail(redirect) {
	
	if (redirect) {
		displayInfo("Loading trail of the week...");
	}
	
	// http://developer.apple.com/internet/webcontent/xmlhttpreq.html
	var request = GXmlHttp.create();
	request.open("GET", dataURL + "?newest=yes");
	request.onreadystatechange = function() {
		
		// This code only runs once the data is retrieved.
		// if (request.readyState == "completed")
		if (request.readyState == 4) {
			
			var output = "<div class=webkicker><b>TRAIL OF THE WEEK</b></div>";
			
			// Display new markers
			var response = request.responseText;
			
			var data = response.split("|");
			
			if (data.length == 18) { // If there is the correct number of fields
			
				output += trailHTML(data);
				map.closeInfoWindow();
				
				// If redirecting to text, also rezoom
				// If not redirecting to text, don't rezoom either
				highlightMarker(data[0], redirect);
				
			} else {
				
				output += "<div class=info2>Information about this hike is not available at this time.</div>";
				
			}
			
			displayResult(output);
			
			if (redirect) {
				displayInfo("Finished loading trail information.");
			}
	
			if (redirect) {
				location.hash = 'results';
			}
			
		}
	};
	
	request.send(null);
	
}

/* Return a string of information about the details of this trail */
function trailHTML(data) {
	
	var result = ""
	result += '<div class="info4"><a href="index.php?id='+data[0]+'"><b>' + data[1] + '</b></a></div>';
	result += easyFormat("Description", data[3]);
	result += easyFormat("Directions", data[4]);
	result += easyFormat("Difficulty", data[8] + " (1 is the easiest, 5 is most difficult)");
	result += easyFormat("Round Trip", data[9] +((data[9] == 1) ? " mile" : " miles"));
	result += easyFormat("Elevation Gain", checkMinimal(data[10]));
	result += easyFormat("Best time to hike", data[11]);
	result += easyFormat("Map", data[2]);
	result += easyFormat("Pass", data[14]);
	result += easyFormat("Also", data[13]);
	result += easyFormat("Pets", data[15]);
	result += easyFormat("More Information", data[17]);
	//result += easyFormat("Web Site", data[16]);
	// data[11] is "humanReadableMonth", not startmonth
	// data[12] is "isGoodMonth", not endmonth
	// data[0] is ID, data[18] is approved
	
	//Ability to comment is disabled
	//result += '<div class=info2><b><a href="http://community.thenewstribune.com/hike_node_gen.php?hike_id=' + data[0] + '">View or write comments about this hike</a></b></div>';

	return result;
}

/* Return either "minimal" or "### feet" */
function checkMinimal(elevation) {
	if (elevation == 0) {
		return "minimal";
	} else {
		return "" + elevation + " feet";
	}
}

function loadTrail(id) {
	loadTrail(id, true);
}

/** Load and display information about a specific trail. */
function loadTrail(id, redirect) {
	
	displayInfo("Loading trail information...");
	
	// http://developer.apple.com/internet/webcontent/xmlhttpreq.html
	var request = GXmlHttp.create();
	request.open("GET", dataURL + "?id=" + id);
	request.onreadystatechange = function() {
		
		// This code only runs once the data is retrieved.
		// if (request.readyState == "completed")
		if (request.readyState == 4) {
			
			var output = "";
			
			// Display new markers
			var response = request.responseText;
			
			var data = response.split("|");
			if (data.length == 18) { // If there is the correct number of fields (a simple safety)
				
				output += trailHTML(data);
				
			} else {
				
				output += "<p>Information about this hike is not available at this time.</p>";
				
			}
			
			
			displayResult(output);
			displayInfo("Finished loading trail information.");
			
			map.closeInfoWindow();
			highlightMarker(data[0], true);
			
			if (redirect) {
				location.hash = 'results';
			}
		}
	};
	
	request.send(null);
	
}

/** Control how most pieces of trail information are displayed. */
function easyFormat(title, content) {
	if (content != "") {
		return "<div class=info2><strong>"+title+":</strong> "+content+"</div>\n";
		// "<p><strong>"+title+":</strong></p>\n<p>"+content+"</p>\n";
	} else {
		return "";
	}
}

/* Highlight the specified marker
 *
 * id (int) - the ID of the trail to highlight
 * rezoom (boolean) - center map on highlighted marker?
 */
function highlightMarker(id, rezoom) {
	
	var marker = mArray[id];
	
	if (theChosenMarker == null) {
		theChosenMarker = new GMarker(marker.getPoint(), {icon: greenGlowIcon});
	}
	
	// Bring the chosen icon image to the front, so that it
	// overlaps the marker to make it appear highlighted.
	map.removeOverlay(theChosenMarker);
	map.addOverlay(theChosenMarker);
	theChosenMarker.setPoint(marker.getPoint());
	
	// When first loading trail of week, don't recenter map
	if (rezoom) {
		map.setCenter(marker.getPoint(), trailZoom);
	}
	
}

//////// Extra ////////


/** Draw a shape. */
function drawShape(point, boundarySize) {

	var lat, lng, dLat, dLng;  // Variables to be passed from drawShape to this HTTP GET request
	
	lat = point.lat();
	lng = point.lng();
	
	if (polyBoundary) {
		minimap.removeOverlay(polyBoundary);
	}
	var boundaryColor = "#ff3366";
	var boundaryWidth = 3;
	
	// Left if anyone wants to perfect the calculation.
	//var d2r = Math.PI/180;  // Degrees to radians
	//var r2d = 180/Math.PI;  // Radians to degrees
	//dLat = (boundarySize/3963)*r2d;   // 3963 is magic number for "circumfurence of earth"
	//dLng = dLat/Math.cos(lat*d2r);
	dLat = 0.01446;  // Degrees per E/W mile
	dLng = 0.02129;  // Degrees per N/S mile (approx)
	
	var boundaryPoints = [];
	/* Circle-drawing equation borrowed from
	 * http://www.tripmojo.com/api/main.jsp?query=10001 */
	for (var i=0; i < 33; i++) {
		var theta = Math.PI * (i/16);
		Cx = lng + (dLng * Math.cos(theta) * boundarySize);
		Cy = lat + (dLat * Math.sin(theta) * boundarySize);
		var P = new GPoint(Cx,Cy);
		boundaryPoints.push(P);
	};
	
	polyBoundary = new GPolyline(boundaryPoints,boundaryColor,boundaryWidth);
	minimap.addOverlay(polyBoundary);
	
}

function updateMap() {
	if (userMark != null) {
		document.search_form.latitude.value = userMark.getPoint().y;
		document.search_form.longitude.value = userMark.getPoint().x;
		var radius = document.search_form.distance.value;
		drawShape(userMark.getPoint(), radius);
	}
}

/* Print the value to the page */
function displayInfo(value) {
	document.getElementById("hike_info").innerHTML = value;
}

/* Print the value to the page */
function displayResult(value) {
	document.getElementById("hike_results").innerHTML = value;
}