/* 
 * Written by Chris Schroeder 6/22/2007
 * Copyright 2007 Johns Hopkins University. All rights reserved.
 * 
 * This is our group of Ajax functions.
 * 
 * Edited and expanded on 7/21/2007 CS
 * 
 * Major overhaul to work with project map module v3 on 10/24/2008 CS 
 */

/* vars initialized */

/* the map */
    var map = null; //Google API object

/* the Google geocoder */
    var geocoder = null; //Google API object

/* 
 * all the points on the map stored in an array.
 * 
 * this way, we can easily - and quickly - clear the map. 
 */
	var mapPoints= []; //array of points plotted with marker data
	
/* counter */
	counter = null; //counts points

/* bubble content info is stored in this */	
	var textMessage = null;
	
/* 
 * this tells our functions whether a 
 * point has been plotted yet or not. 
 * right now, we're not using it at all.
 */
	var pointPlotted = false;

/*
 * These are the current latitude and longitude for each point.
 * We re-use this set for each point instance.
 */
	var currLatitude = null;
	var currLongitude = null;
	
/* the countries array */
	var countriesList = []; //Array of Category JSON data

/* 
 * the AJAX includes.
 * 
 * These are initialized here and 
 * set in the "setURLs(pages)" function 
 */
	var cityController = null;//city tab mode
	var projectController = null;//project tab mode
	var facultyController = null;//faculty tab mode
	var searchController = null;//search results tab mode
	var facultyListController = null;//faculty list tab mode
	var countryListController = null;//country list tab mode
	var countryController = null;//country tab mode

/* CF var defaults */
	var country_code = null;
	var project_id = null;
	var center_id = null;
	var city_id = null;
	var department_id = null;
	var department_id = null;
	var map_mode = null;
	var countryZoom = 1;
	var smallContinentZoom = 1;
	var largeContinentZoom = 1;
	var only_jhsph = 'yes';
	var m_useLocations = 'true';
	var m_breadcrumb = 'yes';
	var m_status = null;
	var linking_src = null;
	var showCountryInfo = null;
	var preloader = null;
	
/* Asset path */
	var assetPath = null;
	
/* this is the AJAX request. 
 * We can move this to a common lib soon.
 */
function createRequest() {
	var request = null;
	try {
		request = new XMLHttpRequest();
	} catch (trymicrosoft) {
		try {
			request = new ActiveXObject("Msxml2.XMLHTTP");
		} catch (othermicrosoft) {
			try {
				request = new ActiveXObject("Microsoft.XMLHTTP");
			} catch (failed) {
				request = null;
			}
		}
	}
	if (request == null) {
		alert ("Error creating request object");
	} else {
		return request;
	}
}


/*
 * We kick off each new app with this function
 * to declare all includes we intend to use.
 */
	function setCFVars(pages) {
		if(pages) {
			for (key in pages) {
				eval(key+"='"+pages[key]+"'");
			}
		}
	}
	
	function setZoom(thisZoom) {
		if(thisZoom) {
			zoom = thisZoom;
		} else {
			zoom = 4;
			alert("We guessed at the zoom level");
		}
		return zoom;
	}

/* 
 * Here's where we use AJAX
 * to send requests our JSon component.
 * 
 * We can give it a country ID
 * or it will return each country
 * in a packet.
 * 
 * The query can have as many vars
 * as we need - in JSon format.
 */
	function startRequest(url,query) {
		var myURL = null;
		urlQuery = "";
		if(query) {
			for (key in query) {
				if(key) {
					myName = key;
					myValue = query[key];
					urlQuery += myName + "=" + myValue + "&";
				}
			}
		}
		if(!url) {
			url = "";
			alert("we've lost our URL somewhere");
			exit;
		}
		myURL = url;
		JSONRequest = createRequest();
		JSONRequest.open("POST", myURL, true);
		JSONRequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
		JSONRequest.onreadystatechange = putOnPage;
		JSONRequest.send(urlQuery);
  	}

/*
 * This function allows us to use checkboxes
 * to add or remove points by country.
 * 
 * To see it in use, visit http://commprojects.jhsph.edu/urbanhealth/
 */
	function checkFunction (url,country_code,formField) {
		if(formField.checked == true) {
			startRequest(url,{'country_code':country_code,'map_mode':map_mode,'center_id':center_id,'department_id':department_id,'only_jhsph':only_jhsph,'m_breadcrumb':m_breadcrumb,'m_useLocations':m_useLocations,'status':m_status,'src':linking_src,'showCountryInfo':showCountryInfo});
/*			alert("checked = " + formField.checked); */
		} else {
			unplotPoints(country_code); 
/*			alert("checked = " + formField.checked); */
		}
	}


/*
 * Here is where we deconstruct 
 * the JSon data. We assign values 
 * to each of our javascript vars.
 * 
 * Two loops here. One through the
 * countries and one through the 
 * cities for each country...
 */
	function putOnPage() {
		if(JSONRequest.readyState == 4) { 



/* 
 * m is the internal counter, 
 * counter is the global counter
 * 
 * on function start, 
 * counter sets m's value
 * 
 * on document load,
 * counter is null 
 */
			m = 0;//function counter
			if(counter!=null) {
				m = m + counter;
			} else {
				counter = 0;
			}
			var myCountries = eval("(" + JSONRequest.responseText + ")");
			for(i=0; i <= myCountries.countries.length; i++) {
				if(myCountries.countries[i]) {
					countriesList.push(myCountries.countries[i]);
					for(n=0; n<= myCountries.countries[i].cities.length; n++) {
						if(myCountries.countries[i].cities[n]) {
							var pointCoords = null;

/*
 * address is the geocoding location
 */
							address = myCountries.countries[i].cities[n].city_name + ", ";
							if(myCountries.countries[i].cities[n].state_code != "") {
								address += myCountries.countries[i].cities[n].state_code + ", ";
							}
							address += myCountries.countries[i].country_name;
						
/*
 * We found tha Google geocoding failed on some of our cities
 * so we map countries if that happens.
 */
							mapCountry = "";
							if(myCountries.countries[i].cities[n].state_code != "") {
								mapCountry += myCountries.countries[i].cities[n].state_code + ", ";
							}
							mapCountry += myCountries.countries[i].country_name;
						
/*
 * title is the tooltip for each point
 */
							tt_title = myCountries.countries[i].cities[n].city_name + ", ";
							if(myCountries.countries[i].cities[n].state_code != "") {
								tt_title += myCountries.countries[i].cities[n].state_code + ", ";
							}
							tt_title += myCountries.countries[i].country_name;

/*
 * if we have coords for a city, we use those
 * rather than geocoding
 */
							if((myCountries.countries[i].cities[n].longitude!="") && (myCountries.countries[i].cities[n].latitude!="")) {
								currLatitude = myCountries.countries[i].cities[n].latitude;
								currLongitude = myCountries.countries[i].cities[n].longitude;
							}

/*
 * vars set
 */
							state_code = myCountries.countries[i].cities[n].state_code;
							country_code = myCountries.countries[i].country_code;
							city_id = myCountries.countries[i].cities[n].city_id;
							country_name = myCountries.countries[i].country_name;

/*
 * check for coords
 */
							if(currLatitude == null || currLongitude == null) {
								plotPoint(address,tt_title,country_code,city_id,m,country_name,m_status,map_mode,center_id,department_id,only_jhsph,m_breadcrumb,m_useLocations,m_status,showCountryInfo);
							} else {
								plotCodedPoint(currLatitude,currLongitude,tt_title,country_code,city_id,counter,country_name,map_mode,center_id,department_id,only_jhsph,m_breadcrumb,m_useLocations,m_status,showCountryInfo);
							}

/*
 * step up counter
 */
							m++;
							counter = m;
						}
					}
				}
			}
		}
	}
	
/* 
 * Primary map function - loads on 
 * pageload and creates the map 
 * and geocoder objects
 */
    function load(longitude,latitude,zoom) {
      if (GBrowserIsCompatible()) {
        map = new GMap2(document.getElementById("map"));
        map.setCenter(new GLatLng(latitude,longitude), zoom, G_HYBRID_MAP);
        geocoder = new GClientGeocoder();
      }
    }

/*
 * We use this function to plot the points 
 * with coords on the map. It also pushes
 * the city_id and marker into the 
 * array we are holding on to, which contains
 * all our points.
 * 
 * it also calls clickHandler to display our includes. 
 * we call them here because the click event is part 
 * of the marker attributes.
 */
 
 	function plotCodedPoint(currLatitude,currLongitude,tt_title,country_code,city_id,counter,country_name,map_mode,center_id,department_id,only_jhsph,m_breadcrumb,m_useLocations,cinfo) {
		if (currLatitude && currLongitude) {
			var currPoint = new GLatLng(currLatitude,currLongitude);
			myicon = createIcon();
			var marker = new GMarker(currPoint, {'icon': myicon, 'tt_title': tt_title});
			mapPoints[counter] = [];
			mapPoints[counter].push(country_code,city_id,only_jhsph,marker);
			map.addOverlay(marker);
			GEvent.addListener(marker, "click", function() {
				clickHandler(marker, "click", cityController, 'tabContainer', {"country_code":country_code,"city_id":city_id,"state_code":state_code,"map_mode":map_mode,"center_id":center_id,"department_id":department_id,"only_jhsph":only_jhsph,'m_breadcrumb':m_breadcrumb,'m_useLocations':m_useLocations,'status':m_status,'assetPath':assetPath,'src':linking_src,'showCountryInfo':showCountryInfo});
				//map.setCenter(currPoint,eval(countryZoom));
				showAddress('"'+country_name+'"',eval(countryZoom));
				try {
				eventTrack("Maps:Projects Module v3","Clicked",tt_title);
				} catch (e) { }

/*				if(textMessage != null) {
					marker.openInfoWindowHtml(textMessage);
				} else {
					marker.openInfoWindowHtml(tt_title + "<br/>" + address);
				} */
			});
			return marker;
		}
 	}
 	
/*
 * We use this function to geocode AND plot
 * the points on the map. It also pushes
 * the city_id and marker into the 
 * array we are holding on to, which contains
 * all our points.
 * 
 * it also calls clickHandler 
 * to display our includes. we call them here
 * because the click event is part of the marker
 * attributes.
 */
	function plotPoint(address,tt_title,country_code,city_id,counter,country_name,map_mode,center_id,department_id,only_jhsph,m_breadcrumb,m_status,cinfo) {
		if (geocoder) {
			geocoder.getLatLng(
				address, function(point) {
				if (point) {
					myicon = createIcon();
					var marker = new GMarker(point, {'icon': myicon, 'tt_title': tt_title});
					mapPoints[counter] = [];
					mapPoints[counter].push(country_code,city_id,marker,only_jhsph,m_breadcrumb);
					map.addOverlay(marker);
					GEvent.addListener(marker, "click", function() {
						clickHandler(marker, "click", cityController, 'tabContainer', {"country_code":country_code,"city_id":city_id,"state_code":state_code,"map_mode":map_mode,"center_id":center_id,"department_id":department_id,"only_jhsph":only_jhsph,'m_breadcrumb':m_breadcrumb,'m_useLocations':m_useLocations,'status':m_status,'assetPath':assetPath,'src':linking_src,'showCountryInfo':showCountryInfo});
						showAddress('"'+country_name+'"',eval(countryZoom));
						try {
							eventTrack("Maps:Projects Module v3","Clicked",tt_title);
						} catch (e) { }

/* 
 * We'd put our bubble content here if we wanted to
 */
						//if(textMessage != null) {
						//	marker.openInfoWindowHtml(textMessage);
						//} else {
						//	marker.openInfoWindowHtml(tt_title + "<br/>" + address);
						//} 
					});
					return marker;
				}
			}
			);
		}
	}

/*
 * Here's where we remove points from the map.
 * We're using a second array, which has the marker
 * in it, to keep track of all the current points 
 * on the map.
 * 
 * If a country_code is supplied, we only remove the
 * points who have that country_code as part of 
 * their subarray. If not, we remove all points using 
 * the mapPoints array.
 */	
	function unplotPoints(country_code) {
		for(x=0;x<=mapPoints.length;x++) {
			if(mapPoints[x]) {
				if(mapPoints[x][0]==country_code) {
					map.removeOverlay(mapPoints[x][2]);
				} else {
					if(country_code==null) {
						map.removeOverlay(mapPoints[x][2]);
						document.getElementById(mapPoints[x][0]).checked = false;
					}
				}
			}
		}
	}

 
/*
 * showAddress finds the address returned
 * from the search form.
 */
	function showAddress(address,zoom) {
		if (geocoder) {
			geocoder.getLatLng(
				address,
				function(point) {
					if (!point) {
						alert(address + " not found");
					} else {
						var myZoom = 15;
						if(zoom) {
						myZoom = zoom;
						map.setCenter(point,myZoom);
					}
				}
			}
			);
		}
	}
	
	function panToAddress(address,zoom) {
		if (geocoder) {
			geocoder.getLatLng(
				address,
				function(point) {
					if (!point) {
						alert(address + " not found");
					} else {
						var myZoom = 15;
						if(zoom) {
						myZoom = zoom;
						map.panTo(point);
						map.setZoom(myZoom);
					}
				}
			}
			);
		}		
	}

/*
 * Simple function to create icon object
 * 
 * There's the default if one is not supplied.
 */
	function createIcon(iconImage,iconShadow) {
		var icon = new GIcon();
		if(!iconImage) {
			icon.image = assetPath+"/_images/pinPoint.png";
		} else {
			icon.image = iconImage;
		}
		if(!iconShadow) {
			icon.shadow = assetPath+"/_images/mm_20_shadow.png";
		} else {
			icon.shadow = iconShadow;			
		}

		icon.iconSize = new GSize(12, 20);
		icon.shadowSize = new GSize(22, 20);
		icon.iconAnchor = new GPoint(6, 6);
		icon.infoWindowAnchor = new GPoint(5, 1);
		return icon;
	}
	
/*
 * This function is a carryover from Chris's v2 map. 
 * It creates the request for the details about
 * the selected service
 * 
 * Note: We'll eventually want to combine the following
 * four functions into one or two or a class, but for now
 * in the interest of saving time, we'll leave it this way
 * CS 7/20/2007
 * 
 * Modified 10/2007 to allow multiple query items 
 * and dynamic includes
 * CS 10/17/2007
 */
	function clickHandler(marker, mode, requestInclude, requestContainer, query){
		if(query) {
			urlQuery = "";
			for (key in query) {
				if(key) {
					myName = key;
					myValue = query[key];
					if(myValue!="") {
						urlQuery += myName + "=" + myValue + "&";
					}
				}
			}
		}
		pointRequest = createRequest();
		pointRequest.open("POST", requestInclude, true);
		pointRequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
		//pointRequest.setRequestHeader("Content-length", urlQuery.length);
		//pointRequest.setRequestHeader("Connection", "close");
		pointRequest.onreadystatechange = function() {
			getInfo(requestContainer,pointRequest);
		}
		pointRequest.send(urlQuery);
  	}

/*
 * This is the function that loads the 
 * listing into the tabContainer div
 */
	function getInfo(requestContainer,pointRequest) {
		if(pointRequest.readyState == 4) {
			document.getElementById(requestContainer).innerHTML = pointRequest.responseText;
			setTabs({'countryLink':'','projectLink':'selected','facultyLink':''});
		} else {
			document.getElementById(requestContainer).innerHTML = '<div style="width:95%;text-align:center;padding-top:50px;"><img src="'+preloader+'" alt="loading..."/></div>';
		}
	}

/*
 * Better versions of the functions above 
 */
	function dataHandler(requestInclude,requestContainer,srcName,ctabs,query){
		requestQuery = "src=" + srcName + "&";
		document.getElementById(requestContainer).innerHTML = "";
		if(query) {
			for (key in query) {
				myName = key;
				myValue = query[key];
				requestQuery += myName + "=" + myValue + "&";
			}
		}		
		aRequest = createRequest();
		aRequest.open("POST", requestInclude, true);
		aRequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
		//aRequest.setRequestHeader("Content-length", requestQuery.length);
		//aRequest.setRequestHeader("Connection", "close");
		aRequest.onreadystatechange = function () {
			if(aRequest.readyState != '4') {
				loadMapResponse(requestContainer,srcName,ctabs,'<div style="width:95%;text-align:center;padding-top:50px;"><img src="'+preloader+'" alt="loading..."/></div>');
			} else {
				loadMapPause(requestContainer,srcName,ctabs,aRequest.responseText);
			}
		}
		aRequest.send(requestQuery);
	}

	function loadMapPause(requestContainer,srcName,ctabs,aResponse) {
		document.getElementById(requestContainer).innerHTML = aResponse;
	}
	function loadMapResponse(requestContainer,srcName,ctabs,aResponse) {
		document.getElementById(requestContainer).innerHTML = aResponse;
		switch(srcName) {
			case "faculty":
			if(ctabs == true) {
				setTabs({'projectLink':'','facultyLink':'selected','publicationLink':''});
			}
			break;
			case "country":
			if(ctabs == true) {
				setTabs({'projectLink':'selected','countryLink':'','facultyLink':''});
			}
			break;
			case "project":
			if(ctabs == true) {
				setTabs({'projectLink':'selected','cityLink':'','facultyLink':'','publicationLink':''});
			}
			break;
			case "search":
			if(ctabs == true) {
				setTabs({'projectLink':'selected','cityLink':'','facultyLink':'','publicationLink':''});
			}
			break;
			default:
			if(ctabs == true) {
				setTabs({'projectLink':'selected','countryLink':'','facultyLink':''});
			}
		}
	}


/* 
 * Removes content from the tabContainer
 */
	function clearItemInfo(requestContainer) {
		document.getElementById(requestContainer).innerHTML = "";
	}

/*
 * This function sets the class for the tab links
 */
 
 	function setTabs(query) {
		if(query) {
			for (key in query) {
				if(document.getElementById(key)) {
					if(query[key] == 'selected') {
						document.getElementById(key).className = "tabSelected";
					} else {
						document.getElementById(key).className = "tab";
					}
				}
			}
		}
 	}

/* all of the map controls are in this function.
 * 
 * we will eventually replace this with a control class -
 * or at least a more useful function - but for now it works
 * and wastes about 40 lines.
 */	
	function loadControls(width,height,navwidth,navheight) {
/* Our zoom controls One for Zoom in, Zoom out, Global View, and Close up */
		var zin = new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(10,10));
		zin.apply(document.getElementById("zoomInControl"));
		document.getElementById("map").appendChild(document.getElementById("zoomInControl"));	
		document.getElementById("zoomInControl").style.visibility = "visible";

		var zout = new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(31,10));
		zout.apply(document.getElementById("zoomOutControl"));
		document.getElementById("map").appendChild(document.getElementById("zoomOutControl"));	
		document.getElementById("zoomOutControl").style.visibility = "visible";

		var zoomclose = new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(52,10));
		zoomclose.apply(document.getElementById("closeupControl"));
		document.getElementById("map").appendChild(document.getElementById("closeupControl"));	
		document.getElementById("closeupControl").style.visibility = "visible";

		var zoomglobal = new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(73,10));
		zoomglobal.apply(document.getElementById("globalControl"));
		document.getElementById("map").appendChild(document.getElementById("globalControl"));	
		document.getElementById("globalControl").style.visibility = "visible";

/* Our directional controls One for North, South, East and West */
		var northNav = new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(Math.round((width-navwidth)/2),0));
		northNav.apply(document.getElementById("northControl"));
		document.getElementById("map").appendChild(document.getElementById("northControl"));	
		document.getElementById("northControl").style.visibility = "visible";
		
		var westNav = new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(0,Math.round((height-navwidth)/2)));
		westNav.apply(document.getElementById("westControl"));
		document.getElementById("map").appendChild(document.getElementById("westControl"));	
		document.getElementById("westControl").style.visibility = "visible";
		
		var eastNav = new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(Math.round(width-navheight),Math.round((height-navwidth)/2)));
		eastNav.apply(document.getElementById("eastControl"));
		document.getElementById("map").appendChild(document.getElementById("eastControl"));	
		document.getElementById("eastControl").style.visibility = "visible";
		
		var southNav = new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(Math.round((width-navwidth)/2),Math.round(height-navheight)));
		southNav.apply(document.getElementById("southControl"));
		document.getElementById("map").appendChild(document.getElementById("southControl"));	
		document.getElementById("southControl").style.visibility = "visible";		
	}
	
/*
 * These functions are carryovers from past map versions.
 */

/*  
 * Reset map functions
 * 
 * Note: User resetCenter - more flexibility
 * the vars come from the application.
 * 
 */

//function resetMap()
//{
//	map.setCenter(new GLatLng(startLat, startLng));
//	map.setZoom(startZoom);
//
//}

function resetCenter(longitude, latitude, zoom)
{
	var center = new GLatLng(latitude, longitude);
	map.setCenter(center, zoom);
}

/* Redefining an existing function is bad pratice - especially if 
 * its does the same thing in a more limiting way the original function. 
 * Bad idea. Commented out. Good example of what NOT to do.
 * 
 * function zoomIn()
 * {
 * 	map.zoomIn();
 * }	
 * 
 * function zoomOut()
 * {
 * 	map.zoomOut();
 * }
 */


