//declare global variables to be used by all functions
var init_lat = 40.75416131535263;
var init_lng = -96.9848110961914;
var zoom = 4;
var map;
var marker;
var i=0;
var places = new Array();
var fltSchtype='all';
var fltSchlevel='all';
var counter;
var loc = '';
var site_url = 'http://www.k12guides.com';
//var site_url = 'http://192.168.1.92';
var query_base = site_url+'/ajax';

// define vars associated with custom map controls
var mapStatus;

//set global vars associated w/ XML parsing
var sides = new Array();
var markers = new Array();
var id = new Array();
var name = new Array();
var phone = new Array();
var schtype = new Array();
var addr = new Array();
var city = new Array();
var state = new Array();
var schlevel = new Array();
var zip = new Array();
var gslo = new Array();
var gshi = new Array();
var lat_arr = new Array();
var lng_arr = new Array();
var leaid = new Array();
var agname = new Array();
var _count = 0;
var notfound = 'No matching school found on this map.';
var toomany = 'Too many matching school found on this map. Please zoom in.';

// create icons
function makeIcon(icon, image) {
    icon.image = image;
    icon.iconSize = new GSize(12, 16);
    icon.shadow = iconBase + "/marker_shadow.png";
    icon.shadowSize = new GSize(20, 16);
    icon.iconAnchor = new GPoint(5, 13);
    icon.infoWindowAnchor = new GPoint(5, 13);
}
// mark icon for each school type
// AIRPORT, SEAPLANE, HELIPORT, STOLPORT, ULTRALIGHT, GLIDERPORT, BALLOONPORT
// school
var iconBase = site_url + '/images';

// primary
var icon_primary = new GIcon();
makeIcon(icon_primary, iconBase + "/icon_map_primary.png");
// middle
var icon_middle = new GIcon();
makeIcon(icon_middle, iconBase + "/icon_map_middle.png");
// high
var icon_high = new GIcon();
makeIcon(icon_high, iconBase + "/icon_map_high.png");
// other
var icon_other = new GIcon();
makeIcon(icon_other, iconBase + "/icon_map_other.png");

// StatusControl is a GControl that displays map status info at the top of the map
function StatusControl() {
}
StatusControl.prototype = new GControl();
// Creates a one DIV for each of the buttons and places them in a container DIV which is returned as our
//control element. We add the control to the map container and return the element for the map class to position properly.
StatusControl.prototype.initialize = function() {
	var container = document.createElement("div");
	var statusDiv = document.createElement("div");
	statusDiv.id = 'status';
	this.setStyle_(statusDiv);
	container.appendChild(statusDiv);
	map.getContainer().appendChild(container);
	return container;
}

// By default, the control will appear in the top left corner of the map with 1 pixels of padding.
StatusControl.prototype.getDefaultPosition = function() {
  return new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(1, 1));
}
// Sets the proper CSS for the given button element.
StatusControl.prototype.setStyle_ = function(bar) {
	bar.style.color = "#FFFFFF";
	bar.style.backgroundColor = "#CC0000";
	bar.style.font = "small Arial";
	bar.style.padding = "2px";
	bar.style.marginBottom = "3px";
	bar.style.cursor = "pointer";
}

//this function hides the "loading" status window
function closeStatus(){
	//hide status bar
	map.removeControl(mapStatus);

        // enable filters
	toggleFilters('on');																	//disable search criteria while loading markers

	//re-enable dragging
	map.enableDragging();
}

// this function clears all markers and the array of plotted points
function clearMarkers(){
	//remove all markers from map
	map.clearOverlays();
	// reset array of markers
	places.length=0;
	sides.length=0;
	// clear side bar
	document.getElementById('schools').innerHTML = '';
}

function toggleView(){
	var map_type = map.getCurrentMapType();
	var types = map.getMapTypes();
	if(map_type == types[0]){
		map.setMapType(types[1]);
	}
	if(map_type == types[1]){
		map.setMapType(types[0]);
	}
}

function createMarker(point, html, schtype, schlevel) {
	useIcon = icon_other;
        if ( schlevel == "1" ) useIcon = icon_primary;
        if ( schlevel == "2" ) useIcon = icon_middle;
        if ( schlevel == "3" ) useIcon = icon_high;
        if ( schlevel == "4" ) useIcon = icon_other;

	var marker = new GMarker(point, useIcon);
	GEvent.addListener(marker, "click", function() {marker.openInfoWindowHtml(html);});
	return marker;
}


function zoomMap(dir){
        //hide status bar
	closeStatus();
	//get current zoom level
	zoom = map.getZoom();
	//zooming out beyond level 11...
	if(zoom <= 11 && dir == 'out'){
	        //delete all markers
		clearMarkers();
		//zoom out to continent view
		map.setZoom(4);
	} else if(zoom < 11 && dir == 'in') {
		//if zooming in from beyond level 10...
		//zoom in to level 10 directly
		map.setZoom(11);
	} else {
	        // if zooming in/out from > level 10...
	        // perform regular zoom
		if (dir == 'in') {
			map.zoomIn();
			hideMarkers();
		} else {
		        map.zoomOut();
		}
	}
}

function openWindow(x,y){
	var n=0;
	while (n < places.length){
		if(places[n].point.lng() == x && places[n].point.lat() == y) break;
		n++;
	}
	// close info window if open
	if (!map.getInfoWindow().isHidden())
	    map.closeInfoWindow();

	places[n].openInfoWindowHtml(places[n].html);
}


function reBuild(){
	var i=0, n=sides.length;
	
	var tmp = '';
	while(i < n){
		tmp += sides[i];
		i++;
	}
	document.getElementById('schools').innerHTML = tmp;        
}


function notFound(){
	mapStatus = new StatusControl();
	map.addControl(mapStatus);
	//display error message in status bar
	document.getElementById('status').innerHTML = notfound;
	//hide status bar after 4 sec
	setTimeout("closeStatus()",2000);
}

function getXML(){
        //disable map dragging
	map.disableDragging();

	mapStatus = new StatusControl();
	map.addControl(mapStatus);
	toggleFilters('off');																	//disable search criteria while loading markers
	document.getElementById('status').innerHTML = 'loading...';

	if (loc=='') {
		//get lat/long boundaries of map
		var bounds = map.getBounds();
		var southWest = bounds.getSouthWest();
		var northEast = bounds.getNorthEast();
		var qurl = query_base+'/school-query.php?left='+southWest.lng()+'&right='+northEast.lng()+'&bottom='+southWest.lat()+'&top='+northEast.lat()+'&schtype='+fltSchtype+'&schlevel='+fltSchlevel;
	} else {
	        var qurl = query_base+'/location-query.php?loc='+loc;
	}

	GDownloadUrl(qurl, function(data, responseCode) {
		var xml = GXml.parse(data);
		if (loc=='') {
                	/**
                	 * What we expect
			 * <results>
			 *	<schools count=300/>
			 * </results>
			 *
			 * OR:
			 *
			 * <results>
			 * 	<school id="440111000309"
			 * 	         name="Warwick Veterans High"
			 * 	         schtype="1"
			 * 	         city="Warwick"
			 * 	         state="RI"
			 *		 zip="12345-6789"
			 * 	         schlevel="High School"
			 * 	         lat="41.703716"
			 * 	         lon="-71.410746"
			 * 	/>
			 * </results>
			 *
 		     	 */
 		     	
 		     	// tag schools exist?
 		     	markers = xml.documentElement.getElementsByTagName("schools");
 		     	_count = markers.length;

 		     	if ( _count > 0 && markers[0].getAttribute('count') >= 200 ) {
 		     		// too many schools
			        //display error message in status bar
				document.getElementById('status').innerHTML = toomany;
				//hide status bar after 2 sec
				setTimeout("closeStatus()",2000);
 		     	} else {
				markers = xml.documentElement.getElementsByTagName("school");
				_count = markers.length;
				for (var y=0; y<_count; y++) {
					id[y] = markers[y].getAttribute('id');
					name[y] = markers[y].getAttribute('name');
					phone[y] = markers[y].getAttribute('phone');
					schtype[y] = markers[y].getAttribute('schtype');
					addr[y] = markers[y].getAttribute('addr');
					city[y] = markers[y].getAttribute('city');
					state[y] = markers[y].getAttribute('state');
					zip[y] = markers[y].getAttribute('zip');
					schlevel[y] = markers[y].getAttribute('schlevel');
					gslo[y] = markers[y].getAttribute('gslo');
					gshi[y] = markers[y].getAttribute('gshi');
					lat_arr[y] = markers[y].getAttribute('lat');
					lng_arr[y] = markers[y].getAttribute('lon');
					leaid[y] = markers[y].getAttribute('leaid');
					agname[y] = markers[y].getAttribute('agname');
				}

	                        // if no matching schools were found...
				if (_count==0) {
	                        	toggleFilters('on');																	//disable search criteria while loading markers
				        //display error message in status bar
					document.getElementById('status').innerHTML = notfound;
					//hide status bar after 2 sec
					setTimeout("closeStatus()",2000);
				} else {
				        //if matches were found...
				        //intialize the marker counter
					i=0;
					//show markers on map
					setTimeout(showMarkers,1);
				}
			}
		} else {
                	/**
                	 * What we expect
                	 * <results>
                	 * 	<data num="2"
                	 *            lat="41.705378333333"
                	 *            lon="-71.477003333333"
                	 *            sizebar=""
                	 *      />
                         * </results>
                	*/

		        //if this query was to find coords of user-specified location...
		        //reset var to prevent from re-triggering a location query
			loc='';
			//get elements with a tag name of "data"
			var data = xml.documentElement.getElementsByTagName("data");
			//get the "num" attrubute of this element, which is the number of schools found in the user-specified location
			var num = data[0].getAttribute('num');
			//get the "sidebar" attrubute of this element, which is the html that goes into the sidebar when an ambiguous location is entered by the user
			var sidebar = data[0].getAttribute('sidebar');

			//if location was not ambiguous...
			if (sidebar == '') {
			        //if no schools were found in the specified location...
				if (num==0) {
				        // display error message in status bar
					document.getElementById('status').innerHTML = 'Either no school found in this location or the location was not understood.';
					// hide status bar after 2 seconds
					setTimeout("closeStatus()",2000);
				} else {					
				        // if schools were found in this location...
				        // get the average coords of all schools found in this location
					var lat_ctr = data[0].getAttribute('lat');
					var lng_ctr = data[0].getAttribute('lon');
					//re-center map on avg coords and zoom to level 11
					map.setCenter(new GLatLng(lat_ctr, lng_ctr), 11);
				}
			} else {
			        //hide status bar
				closeStatus();
				document.getElementById('schools').innerHTML = sidebar;
			}
		}
	});
}

function showMarkers(){
        //disable map dragging
	map.disableDragging();
	if(i < _count){
	        //select the minimum batch size of 20 schools or the remainder of total schools divided by 20
		var max = Math.min(i+20, _count);
		//loop thru all schools to be plotted in this batch
		while(i < max){
			var j=0;
			var exists = false;
		        //loop thru existing markers to see if the marker is already plotted
			while(j < places.length){
			        //check if this point is already marked
				if(lng_arr[i] == places[j].point.lng() && lat_arr[i] == places[j].point.lat()){
				        //set exist flag
					exists = true;
					//if already plotted, break out of loop
					break;
				}
				j++;
			}
			//if this marker is not already plotted...
			if (exists == false){
				//prepare marker
				var schurl = site_url + '/school/'+myurlencode(name[i])+';'+id[i]+'.html';
				var agurl = site_url + '/agency/'+myurlencode(agname[i])+';'+leaid[i]+'.html';

                                // html code for infoWindow
	                        var html = '<div style="width:250px"><div style="float:left; width:250px; font-size:11px">';
				html += '<a href="'+schurl+'" target="_parent"><b>'+name[i]+'</b></a><br>';
				html += gslo[i] + ' - ' + gshi[i] + '<br><br>';

				if ( addr[i] != '' ) html += addr[i] + '<br>';
				html += city[i] + ',&nbsp;' + state[i] + ' ' + zip[i] + '<br>';
				html += phone[i] + '<br>';
				
				// hotel link
				html += '<br>School District: <br><a href="' + agurl + '">' + agname[i]+ '</a>';
				html += '</div></div>';

				//create point
				var point = new GLatLng(lat_arr[i],lng_arr[i]);

				//create marker
				var marker = createMarker(point, html, schtype[i], schlevel[i]);

				//add marker attributes used to identify markers when search criteria are applied
				marker.point = marker.getPoint();
				marker.schtype = schtype[i];
                                marker.schlevel = schlevel[i];
                                marker.id = id[i];
                                marker.name = name[i];
                                marker.html = html;

				//build sidebar content and store sidebar data
				var tmp = '<div class="schloc_side"><a href="javascript:openWindow('+lng_arr[i]+','+lat_arr[i]+')">' + name[i] + 
				           '</a><br>';
				if ( addr[i] != '' ) tmp += addr[i] + '<br>';
				tmp += city[i] + ', ' + state[i] + ' ' + zip[i] + '</div>';
                                marker.side = tmp;

				//update status bar if it exists
				if (StatusControl) document.getElementById('status').innerHTML = 'loading school '+(i+1)+' of '+_count+'...';

				//add marker to map as overlay
				map.addOverlay(marker);
				//record marker in array of markers
				places.push(marker);
			}	//end if not already plotted
			i++;
		}	//end while

                if (StatusControl && i == _count) document.getElementById('status').innerHTML = 'sorting...';

		window.setTimeout(showMarkers, 1);
	}	//end if
	else {
            // sort places, create side bar content
            setSortby();
	}
}

//this function removes markers from the map that are no longer in the field of view to save memory
function hideMarkers(){
        //get map bounds
	var bounds=map.getBounds();
	var southWest=bounds.getSouthWest();
	var northEast=bounds.getNorthEast();
	var j=0;

	//loop thru each marker
	while(j < places.length){
	        //get latitude of current marker
		var lat=places[j].point.lat();
		//get latitude of current marker
		var lng=places[j].point.lng();
		//if marker not in map field of view...
		if (lat > northEast.lat() || lat < southWest.lat() || lng > northEast.lng() || lng < southWest.lng()) {
		        //remove marker from map
			map.removeOverlay(places[j]);
			//remove marker from array of markers
			places.splice(j,1);
			//remove marker from array of sidebar contents
			sides.splice(j,1);
		} else {
		        j++;
		}
	}
	// rebuild the sidebar listings
	reBuild();
}

function onLoad(){
	if(!GBrowserIsCompatible()) {
	        alert("This browser is not compatible with Google Map's technology.");
	        window.location=site_url;
        }

	//initialize map object
	map = new GMap2(document.getElementById("map"));
	//add scale
	map.addControl(new GScaleControl(100));

	//unselect all option boxes
	for (i=0; i<document.filters.elements.length; i++){
 	    document.filters.elements[i].selectedIndex = 0;
	}

        //set map center coords and zoom level
        map.setCenter(new GLatLng(init_lat, init_lng), zoom);

	// create event listeners
        // upon map movement...
	GEvent.addListener(map,"movestart",function(){
	        // hide status map control
		closeStatus();
		document.getElementById('schools').innerHTML = '';
	});

	//perform the following after moving map (initiated by drag, click, or zoom)...
	GEvent.addListener(map,"moveend",function(){
	        // hide status map control
		closeStatus();
		if(map.getZoom() >= 10){
		        //plot markers within these map bounds after tdly that allows map to re-center first
			setTimeout("getXML()",300);
			//hide markers no longer in the field of view
			hideMarkers();
		}
	});

        //perform the following upon clicking the map...
	GEvent.addListener(map,"click",function(overlay, point){
		//hide status map control
		closeStatus();
		//if map clicked...
		if (point) {
			if(map.getZoom() < 10) {
			        //center map on click coords and zoom in to level 10
			        map.setCenter(new GLatLng(point.lat(), point.lng()), 10);
			} else {
			        //pan to click coords at current zoom level
			        map.panTo(new GLatLng(point.lat(), point.lng()));
			}
		}
	});
	
	// now we can turn on filters
	toggleFilters('on');
}
//end function onLoad


// toggle filters on/off
function toggleFilters(sw) {
	var tmpFilters = document.filters.elements;
	var tmpLen = tmpFilters.length;
	if (sw=='off') {
		for (i=0; i<tmpLen; i++){
			tmpFilters[i].disabled = true;
			tmpFilters[i].style.color = '#666666';
		}
	} else {
		// enable filters
		for (i=0; i<tmpLen; i++){
			tmpFilters[i].disabled = false;
			tmpFilters[i].style.color = '#333333';
		}
	}
}


// goto a location entered by user
function gotoLocation(){
	map.closeInfoWindow();

	loc=document.filters.location.value;
	//if the user clicked the 'search' button without entering a location...
	if (loc=='') {
		//return error message
		notFound();
		return;
	}

	//query database using new location
	getXML();
}

// apply search filter on schtype
function setSchtype() {
        //hide status bar
	closeStatus();
	map.closeInfoWindow();

	var obj = document.filters.schtype;
	//if currently displaying all schools and user requests another type...
	/*
	if (fltSchtype == 'all') {
		var y = 0;
	        //loop thru markers and remove those
		while (y < places.length){
			if (places[y].schtype != obj.options[obj.selectedIndex].value) {
			        //clear unmatching marker
				map.removeOverlay(places[y]);
				// delete marker from array of markers
				places.splice(y,1);
				// delete marker from array of sidebar contents
				sides.splice(y,1);															//delete marker from array of markers
			} else {
			        y++;
			}
		}

                // rebuild sidebar content
		reBuild();
		// record new filter
		fltSchtype = obj.options[obj.selectedIndex].value;
		if (places.length==0) notFound();
	} else {
	        clearMarkers();
		fltSchtype = obj.options[obj.selectedIndex].value;
		getXML();
	}
	*/
        clearMarkers();
	fltSchtype = obj.options[obj.selectedIndex].value;
	getXML();
}

// apply search filter on schlevel
function setSchlevel() {
        // hide status bar
	closeStatus();
	map.closeInfoWindow();

	var obj = document.filters.schlevel;
	/*
	//if currently displaying all schools and user requests another use...
	if (fltSchlevel == 'all') {
		var y = 0;
	        //loop thru markers and remove those
		while (y < places.length){
			if (places[y].schlevel != obj.options[obj.selectedIndex].value) {
			        //clear unmatching marker
				map.removeOverlay(places[y]);
				// delete marker from array of markers
				places.splice(y,1);
				// delete marker from array of sidebar contents
				sides.splice(y,1);															//delete marker from array of markers
			} else {
			        y++;
			}
		}

                // rebuild sidebar content
		reBuild();
		// record new filter
		fltSchlevel = obj.options[obj.selectedIndex].value;
		if (places.length==0) notFound();
	} else {
	        clearMarkers();
		fltSchlevel = obj.options[obj.selectedIndex].value;
		getXML();
	}
	*/
        clearMarkers();
	fltSchlevel = obj.options[obj.selectedIndex].value;
	getXML();
}

// sort functions (by default javascript sort everything as string
function sortNameA2Z(a,b) {
  if (a.name < b.name) return -1;
  if (a.name > b.name) return 1;
  return 0;        
}

function sortNameZ2A(a,b) {
  if (a.name < b.name) return 1;
  if (a.name > b.name) return -1;
  return 0;        
}

function sortSchools(p) {
        var obj = document.filters.sortby;
        SortBy = obj.options[obj.selectedIndex].value;

        if ( SortBy == 'nameaz' ) return p.sort(sortNameA2Z);
        if ( SortBy == 'nameza' ) return p.sort(sortNameZ2A);
        return p.sort(sortNameA2Z);
}   

// apply search filter on highrate
function setSortby() {
        if (StatusControl && document.getElementById('status') == null) {
                map.disableDragging();
  	    
	        mapStatus = new StatusControl();
 	        map.addControl(mapStatus);
 	        
                // disable filters
   	        toggleFilters('off');

	        //display message in status bar
	        document.getElementById('status').innerHTML = 'sorting...';
	    
	        setTimeout(setSortby, 1);
	} else {
                // now all markers created, sort it
                places = sortSchools(places);

                // create side bar content
        	//loop thru each marker
        	sides = Array();
        	var j=0, n=places.length;
        	while(j < n) {
        		sides.push(places[j].side);
        		j++;
                }
                
                // draw side bar
                reBuild();
        
        	//hide status bar after 0.5 sec
        	setTimeout("closeStatus()", 500);
        }
}

// my own URL encode method
function myurlencode(name) {
    // change all special characters to -: < > / . ( ) { } [ ] , ' " ! ; % & $ # _ ~ ? space
    name = name.replace(/\<|\>|\:|\/|\.|\(|\)|\{|\}|\[|\]|\,|\"|\'|\;|!|%|&|\$|#|_|~|\?|\ /g, '-');

    // strip '--' to '-', repeat until no more --
    while ( name != (new_name = name.replace(/\-\-/g, '-')) ) {
        name = new_name;
    }
    
    // strip first or last - if any
    if ( name.substr(0, 1) == '-' ) name = name.substr(1, name.length-1);
    if ( name.substr(name.length-1, 1) == '-' ) name = name.substr(0, name.length-1);
    
    return name;
}
