//<![CDATA[
// global variables for map and geocoder
var map;
var geocoder = new GClientGeocoder();
var circleCenterLatitude = 0;
var circleCenterLongitude = 0;

// default values for testing and development
var default_zoom = 14;

// initial map loading with preliminary map center and zoom
function loadMap() {
  // document.domain = "dpdonline.org";
  if (GBrowserIsCompatible()) {
      map = new GMap2(document.getElementById("map"));
      map.addControl(new GLargeMapControl());
      map.addControl(new GMapTypeControl());
      map.addControl(new GScaleControl());
      map.disableDoubleClickZoom();

      // center map at civic center
      civic_center_point = new GLatLng(civic_center_lat,civic_center_lng);
      map.setCenter(civic_center_point, default_zoom);

      // add double-click to move map and search crimes
      GEvent.addListener(map, "dblclick", function(overlay, latlng) {
          recenterSearch(latlng);
      });
  }
  setupCalendar();
  drawPage();
}

function recenterSearch (point) {
	// get the lat and long of the double-click point
	var latitude = point.lat();
	var longitude = point.lng();
	var url = 'point_search.php?' + '&lon=' + longitude + '&lat=' + latitude;

	// does not block...
	hitHttpPoint (url);
}

function hitHttpPoint (url) {
	if (window.XMLHttpRequest) {
		req = new XMLHttpRequest();
		req.onreadystatechange = processRevGeocode;
		req.open("GET", url, true);
		req.send(null);
	} else if (window.ActiveXObject) {
		req = new ActiveXObject("Microsoft.XMLHTTP");
		if (req) {
			req.onreadystatechange = processRevGeocode;
			req.open("GET", url, true);
			req.send();
		}
	}
}

// TODO fix the error message if reverse geocode fails
function processRevGeocode () {
	if (req.readyState == 4) {
		if (req.status == 200) {
			var ret = req.responseText;
			// debugLog ('Point results: ' + ret);
			try {
				eval( ret );
			} catch (e) {
				// statusText (siteText['errorText']);
				// exceptionHandler (e.message);
			}
			findNearbyStreet(mapLocation);
		}
	}
}

// always update the date range of the current search
function newDateSearch() {

        var interval = document.getElementById ('addressSearchFormInterval').selectedIndex;
        if (!(interval > 0)) {
                interval = 1;
        }
        if (interval > 7) {
                interval = 28;
        }
        var endDate = document.getElementById ('addressSearchFormEndDate').value;

	var url = 'date_search.php?' + '&endDate=' + endDate + '&interval=' + interval;
	hitHttpDate (url);
}

function hitHttpDate (url) {
        if (window.XMLHttpRequest) {
                req = new XMLHttpRequest();
                req.onreadystatechange = processNewDate;
                req.open("GET", url, true);
                req.send(null);
        } else if (window.ActiveXObject) {
                req = new ActiveXObject("Microsoft.XMLHTTP");
                if (req) {
                        req.onreadystatechange = processNewDate;
                        req.open("GET", url, true);
                        req.send();
                }
        }
}

function processNewDate () {
        if (req.readyState == 4) {
                if (req.status == 200) {
                        var ret = req.responseText;
                        // debugLog ('Point results: ' + ret);
                        try {
                                eval(ret);
                        } catch (e) {
                                // statusText (siteText['errorText']);
                                // exceptionHandler (e.message);
                        }
			tryGeocode();
                }
        }
}

// reverse geocoding to find nearest street address
function findNearbyStreet(mapLocation) {

      // get lat lon and make point
      var latlng = new GLatLng(mapLocation.lat, mapLocation.lon);

      // get street name parameters from search results
      var street = mapLocation.fullname.replace(/\s{2,}/g,"");
      var stnum = mapLocation.adrf.replace(/\s{2,}/g,"");
      // var sttype = mapLocation.type;
      // var stpfx = mapLocation.predir;
      // var stsfx = mapLocation.postdir;
      var zip = mapLocation.zipl;
      // var mapAddress = stnum + ' ' + stpfx + ' ' + street + ' ' + sttype + ' ' + stsfx ;
      var mapAddress = stnum + ' ' + street;

      // put values into form
      document.getElementById ('addressSearchFormStreet').value = mapAddress;
      document.getElementById ('mapPointLatitude').value = mapLocation.lat;
      document.getElementById ('mapPointLongitude').value = mapLocation.lon;
   
      // make new crime search
      newDateSearch();
}

// make a marker with info ballon
function showGeoPoint(point,description,iconURL) {
      //
      if (iconURL!='') {
         pointIcon = new GIcon();
         pointIcon.image = iconURL;
         pointIcon.iconSize = new GSize(27,38);
	 pointIcon.iconAnchor = new GPoint(14,25);
	 pointIcon.infoWindowAnchor = new GPoint(14,14);
         var marker = new GMarker(point,pointIcon);
      } else {
         // make maker for geo point
         var marker = new GMarker(point);
      }
      // add click event to open info window at point
      GEvent.addListener(marker, 'mouseover',
          function() {
              marker.openInfoWindowHtml(description);
	  }
      );
      // add this point and info to the map
      map.addOverlay(marker);
}

// build the address string to find
function addressSearch() {
	if (document.getElementById ('addressSearchFormStreet').value > '') {
               document.getElementById ('mapPointLatitude').value = '';
               document.getElementById ('mapPointLongitude').value = '';
	}
	newDateSearch();
}

function tryGeocode() {
	
	var addressToFind;
        // city and state
	var cityState = 'Dalton' + ', ' + 'Georgia';
        // Ensure that the street, city, and/or zip are ok
        var userAddress = document.getElementById ('addressSearchFormStreet').value;
	// check for address number and street name
	if ( !(userAddress == 'Street address' || userAddress == '' || userAddress == null) )
	{	
		addressToFind = userAddress + '  ' +  cityState;
	} else {
		addressToFind = cityState;
	}

	// get Google address matches and test them
	geocoder.getLocations(addressToFind, function(matches) {
		if (!matches) {
        		alert("Unable to locate " + addressToFind ); 
		} else {
			if (matches.Status.code == 200) {
				checkAddressMatches(matches);
			} else {
        			alert("Unable to locate " + addressToFind ); 
			}
		}
	});
}

// check all the address matches found by Google
function checkAddressMatches(matches) {
	var info;
	var point;
	var coordinates;
	var lat;
	var lon;
	var addLon;
	var addLat;
	var clkLat = document.getElementById ('mapPointLatitude').value;
	var clkLon = document.getElementById ('mapPointLongitude').value;
	var dltLon;
	var dltLat;
	var details;
	var community;
	var streetAddress;
	var placeName;
	var zipcode;
	var localPlace;
	var found = new Boolean(false);
	var placemarks = matches.Placemark;
	var address = matches.name;
	var addressFound;

	for (match in placemarks) {
		// check each match for valid city
		details = placemarks[match].AddressDetails;
		coordinates = placemarks[match].Point.coordinates;
                addLon = coordinates[0];
                addLat = coordinates[1];
		addressFound = placemarks[match].address;
		addressFound = addressFound.replace(/,.*/,"");

                //
                if (clkLon > '' && clkLat > '') {
                        dltLon = Math.abs(addLon - clkLon);
                        dltLat = Math.abs(addLat - clkLat);
                        if (dltLon > 0.0015 || dltLat > 0.0015) {
                                continue;
                        }
                }

		if (details.Accuracy < 3) {
			continue;
		}

		// Limit search to US addresses
		countryCode = details.Country.CountryNameCode;
		if (!(countryCode == 'US')) {
			continue;
		} else if (details.Accuracy == 1) {
			// alert('country level');
			if (testSpatialDomain(coordinates)) {
				localPlace = placemarks[match].address;
				placeName = localPlace.replace(/,.*/, "");
				found = Boolean(true);
				break;
			} else {
				continue;
			}
		}

		// Limit search to California
		if (!(details.Country.AdministrativeArea == null)) {
			state = details.Country.AdministrativeArea.AdministrativeAreaName;
			if (!(state == 'GA')) {
				continue;
			}
		}

		// if the premise found, use it 
		if (details.Accuracy == 9) {
			if (!(details.Country.Premise == null)) {
				placeName = details.Country.Premise.PremiseName;
				found = Boolean(true);
				break;
			}
		}

		// test for Locality as child of AdministrativeArea, in case zipcode only match
		if (!(details.Country.AdministrativeArea.Locality == null)) {
			if (!(details.Country.AdministrativeArea.Locality.LocalityName == null)) {
				city = details.Country.AdministrativeArea.Locality.LocalityName;
			}
			if (!(details.Country.AdministrativeArea.Locality.PostalCode == null)) {
				zipcode = details.Country.AdministrativeArea.Locality.PostalCode.PostalCodeNumber;
			}
			if (!(details.Country.AdministrativeArea.Locality.Thoroughfare == null)) {
				streetAddress = details.Country.AdministrativeArea.Locality.Thoroughfare.ThoroughfareName;
			}
			if (!(details.Country.AdministrativeArea.Locality.DependentLocality == null)) {
				placeName = details.Country.AdministrativeArea.Locality.DependentLocality.DependentLocalityName;
			}
		}

		// test for Locality as child of SubAdministrativeArea, more than zipcode match
		if (!(details.Country.AdministrativeArea.SubAdministrativeArea == null)) {
			if (!(details.Country.AdministrativeArea.SubAdministrativeArea.Locality == null)) {
				if (!(details.Country.AdministrativeArea.SubAdministrativeArea.Locality.LocalityName == null)) {
					city = details.Country.AdministrativeArea.SubAdministrativeArea.Locality.LocalityName;
				}
				if (!(details.Country.AdministrativeArea.SubAdministrativeArea.Locality.PostalCode == null)) {
					zipcode = details.Country.AdministrativeArea.SubAdministrativeArea.Locality.PostalCode.PostalCodeNumber;
				}
				if (!(details.Country.AdministrativeArea.SubAdministrativeArea.Locality.Thoroughfare == null)) {
					streetAddress = details.Country.AdministrativeArea.SubAdministrativeArea.Locality.Thoroughfare.ThoroughfareName;
				}
				if (!(details.Country.AdministrativeArea.SubAdministrativeArea.Locality.DependentLocality == null)) {
					community = details.Country.AdministrativeArea.SubAdministrativeArea.Locality.DependentLocality.DependentLocalityName;
				}
			}
			if (!(details.Country.AdministrativeArea.SubAdministrativeArea.SubAdministrativeAreaName == null)) {
				county = details.Country.AdministrativeArea.SubAdministrativeArea.SubAdministrativeAreaName;
			}
		}

		// test the city name, we only want to match 
		if (!(city == 'Dalton') && !(county == 'Whitfield') && !(county == 'Whitfield' + ' County')) {
			continue;
		} else if (!(testSpatialDomain(coordinates))) {
			continue;
		} else {
			found = Boolean(true);
			break;
		}
	}

	//
	if (!(addressFound == null) && (placeName == null)) {
		placeName = addressFound;
	}
	if (city == null) {
		city = county;
	}
	if (streetAddress == city) {
		streetAddress = '';
	}
	if (placeName == city) {
		placeName = '';
	}

	// test if addres match point found in disired area
	if (found.toString() == 'true') {
		// search for crimes at the selected user address match point
		point = makeAddressPoint(coordinates);
		newCrimeSearch(point, default_zoom, placeName, streetAddress, city, state, zipcode);
	} else {
                document.getElementById ('addressSearchFormStreet').value = '';
		if (clkLon.length == 0 || clkLat.length == 0) {
			clkLon = civic_center_lng;
			clkLat = civic_center_lat;
		}
                point = makeAddressPoint([clkLon,clkLat]);
                newCrimeSearch(point, default_zoom, '', '', city, state, '');

                // alert("Unable to locate " + address );
	}
}

// test spatial range of coordinate point
function testSpatialDomain(coordinates) {
	var localPoint = new Boolean(true);
	var lat = coordinates[1];
	var lon = coordinates[0];
	if ((lat < minLat)||(lat > maxLat)) {
		localPoint = false;
	}
	if ((lon < minLon)||(lon > maxLon)) {
		localPoint = false;
	}
	return localPoint;
}

// make point from address match
function makeAddressPoint(coordinates) {
	var lat = coordinates[1];
	var lon = coordinates[0];
	point = new GLatLng(lat, lon);
	return point;
}

// find crimes near the user address point
function newCrimeSearch(point, zoom, placeName, streetAddress, city, state, zipcode) {
	var firstline;
	var lastline;
	var searchURL;
	var searchQuery;
	var searchDate;
	var searchInterval;
	var searchRadius;
	var searchLatitude;
	var searchLongitude;
	var searchType;
	var county = 'Whitfield' + ' County';

	// get search parameters from the user form
	var radius =  document.getElementById ('addressSearchFormRadius').selectedIndex;
	if (radius == 0 ) {
		radius = 1;
		document.getElementById ('addressSearchFormRadius').selectedIndex = 1;
	}
	var interval = document.getElementById ('addressSearchFormInterval').selectedIndex;
	if (interval == 0) {
		interval = 1;
		document.getElementById ('addressSearchFormInterval').selectedIndex = 1;
	}
	if (interval > 7) {
		interval = 28;
	}
	var endDate = document.getElementById ('addressSearchFormEndDate').value;

	// 
	var incidents1 = '&c[1]';
	var incidents2 = '&c[2]';
	var incidents3 = '&c[3]';
	var incidents4 = '&c[4]';
	var incidents5 = '&c[5]';
	var incidents6 = '&c[6]';
	var incidents7 = '&c[7]';

	//
	var incidents = '';
	for (var i = 1; i <= 7; i++) {
		if (document.getElementById ('c' + i).checked == true) {
			incidents += '&c[' + i + ']=1';
		}
	}

	// center and zoom map on new point
	map.setCenter(point,map.getZoom());

	// search for crime near this point
	latitude = point.lat();
	longitude = point.lng();
	circleCenterLatitude = latitude;
	circleCenterLongitude = longitude;

	// create firstline of address or place
	if (placeName == null) {
		placeName = '';
	}
	if (streetAddress == null) {
		streetAddress = '';
		firstline = placeName;
	} else {
		if ((placeName == streetAddress) || (placeName == '')) {
			firstline = streetAddress;
		} else {
			firstline = placeName + ', ' + streetAddress;
		}
	}

	// Georgia only addresses
	if (state == null) {
		state = 'GA';
	}
	if (city == null) {
		city = county;
	}

	// append last line of address or location
	lastline = city + ', ' + state;
	if (!(zipcode == null)) {
		lastline = lastline + ' ' + zipcode;
	}

	// generate form for search point info
	// TODO allow users to report inicidents on map
        var inputForm = document.createElement("form");
	inputForm.setAttribute("action", "");
	inputForm.onsubmit = function() {reportIncident(); return false;};

	// populate web form with address and serach point info
	inputForm.innerHTML = '<fieldset style="width:150px;">'
	  + '<legend>'
	  + '<span id="search-title" style="font-family: Arial,sans-serif; font-size: small;">'
	  + 'Crime Search Location</span>'
	  + '</legend>'
	  + '<span id="search-address" style="font-family: Arial,sans-serif; font-size: small;width:100%">' 
	  + firstline + '</span><br />'
	  + '<span id="search-lastline" style="font-family: Arial,sans-serif; font-size: small;width:100%">' 
	  + lastline + '</span>'
	  + '<span id="search-precinct" style="font-family: Arial,sans-serif; font-size: small;width:100%">'
	  + '</span>'
	  + '<input type="hidden" id="longitude" value="' + longitude + '"/>'
	  + '<input type="hidden" id="latitude" value="' + latitude + '"/>'
	  + '</span>'
	  + '</fieldset>';

	// update the nav bar
	var displayAddress = firstline + '<br />' + lastline;

	// TODO fix the endDate when missing at start-up
	// var endDate = '12/17/2007';
	var startDate = this.DateRange.START_DATE;
	var endDate = this.DateRange.END_DATE;

	// display the search parameters in the nav bar
	userAddress(displayAddress,'','',startDate,endDate,radius,'mile(s)');

	// show the crime search center
	map.clearOverlays();
	drawCircle(point,radius);
	// show center of search, user address or map click
        showGeoPoint(point,inputForm,searchIconURL);

	// setup search query parameters
	searchDate = 'endDate=';
	searchInterval = '&interval=';
	searchRadius = '&radius=';
	searchLatitude = '&lat=';
	searchLongitude = '&lon=';

	// attach URL encoded parameter values
	searchDate = searchDate + endDate;
	searchInterval = searchInterval + interval;
	searchRadius = searchRadius + radius;
	searchLongitude = searchLongitude + longitude;
	searchLatitude = searchLatitude + latitude;
	searchQuery = searchDate + searchInterval + searchRadius + searchLongitude + searchLatitude + incidents;

	// for now, make the KML true, then switch to false to use JSON
        if (false) {
                // get the KML crime list
		searchURL = 'http://dpdonline.org/crime_search_kml.php?';
                crimeOverlay = new GGeoXml(searchURL + searchQuery);
                map.addOverlay(crimeOverlay);
                findLocalStation(latitude, longitude);
        } else {
                // here's the different code, call the function that makes AJAX call
		searchURL = 'http://' + document.domain + '/crime_search_json.php?';
                hitHttpJsonCrimeData(searchURL + searchQuery);
        }

}

function drawCircle(point,radius) {
	// draw the search radius circle
	var pointList = Array();
	var mapProj = G_NORMAL_MAP.getProjection();
	var mapZoom = map.getZoom();
	var pixelPoint = mapProj.fromLatLngToPixel(point, mapZoom);
	// temporary circle parameters
	var polySides = 60;
	var sideLength = 6;
	var radiusFactor = 0;
        var radiusBase = 13;
	// determine pixel radius by zoom level and selected search distance
	switch(mapZoom) {
		case 11: 
			radiusFactor = radiusBase * 1;
			break;
		case 12:
			radiusFactor = radiusBase * 2;
			break;
		case 13:
			radiusFactor = radiusBase * 4;
			break;
		case 14:
			radiusFactor = radiusBase * 8;
			break;
		case 15:
			radiusFactor = radiusBase * 16;
			break;
		case 16:
			radiusFactor = radiusBase * 32;
			break;
	}

	var circleRadius = radius * radiusFactor;
	if (circleRadius > 0 && circleRadius < 1001)
	{
	// generate list of circle points
		for (var a = 0; a<(polySides+1); a++)
		{
			var radialPoint = sideLength*a*(Math.PI/180);
			var Xpixel = pixelPoint.x + circleRadius * Math.cos(radialPoint);
			var Ypixel = pixelPoint.y + circleRadius * Math.sin(radialPoint);
			var circlePixel = new GPoint(Xpixel,Ypixel);
			var circlePoint = mapProj.fromPixelToLatLng(circlePixel,mapZoom);
			pointList.push(circlePoint);
		}
		// make the cirle now
		var circle = new GPolygon(pointList,"#000000",2,.8,"#000000",0);
		map.addOverlay(circle);
	}
}

function switchLayerVisiblity() {
	//
	for (var i = 1; i <= 7; i++) {
		if (document.getElementById ('c' + i).checked == true) {
			// switch the layer visiblity on	
			eval('crimeOverlay' + i + '.show()');
		} else {
			// switch the layer visiblity off
			eval('crimeOverlay' + i + '.hide()');
		}	
	}
}

// allow user to report an incident at a location
function reportIncident() {

}

/**
 * helper function, parse integer value safely
 * when IEEE format (scientific notation).
 */
function safeParseInt( val ) {
	return Math.round(parseFloat(val));
};


// generate content in upper right nav bar, the current search location or proximity
function userAddress (address, division, divURL, startDate, endDate, Radius, mileString) {

	// demo setting
	divURL = 'sample';
	var st = document.getElementById ('searchTable')	;
	st.innerHTML = '';
	st.innerHTML = '<table width="100%" border="0" cellpadding="0" cellspacing="0" class="padding5">\
	<tr>\
		<td>\
			<table width="100%" border="0" cellspacing="0" cellpadding="0">\
				<tr>\
					<td align="left" valign="top"><img src="images/mapNEW_r1_c5.gif" width="20" height="26" border="0" alt=""></td>\
					<td align="left" valign="top">&nbsp;</td>\
					<td align="left" valign="top" class="darkgreyTEXT11">' + address + '<br>\
					<span id="SearchTablePrecinct">' + division + ' \
					&nbsp;</span></td>\
				</tr>\
			</table>\
		</td>\
	</tr>\
	<tr>\
		<td height="10"></td>\
	</tr>\
	<tr>\
		<td align="left" valign="top" class="darkgreyTEXT11">Date Range Shown:<br>\
			<span class="orangeHIGHLIGHT">' + startDate + ' to ' + endDate + '</span><br>\
			Radius: <span class="orangeHIGHLIGHT">' + Radius + ' ' + mileString + '</span>\
		</td>\
	</tr>\
</table>';

}

function updateAddressInfo() {

	var pt = document.getElementById ('SearchTablePrecinct');
	var beat = Division.Beat;
	var officer = Division.officer;
	var email = Division.email;
	var extension = Division.extension;
	var rank = Division.rank;
	if (beat) {
		pt.innerHTML = "Beat:&nbsp;" + beat;
	}
}

function findLocalStation(latitude, longitude) {
	var url = 'division_search.php?' + '&lat=' + latitude + '&lon=' + longitude;
	hitHttpPrecinct (url);
}

function hitHttpPrecinct(url) {
        if (window.XMLHttpRequest) {
                req = new XMLHttpRequest();
                req.onreadystatechange = processLocalPrecinct;
                req.open("GET", url, true);
                req.send(null);
        } else if (window.ActiveXObject) {
                req = new ActiveXObject("Microsoft.XMLHTTP");
                if (req) {
                        req.onreadystatechange = processLocalPrecinct;
                        req.open("GET", url, true);
                        req.send();
                }
        }
}

function processLocalPrecinct() {
        if (req.readyState == 4) {
                if (req.status == 200) {
                        var ret = req.responseText;
                        // debugLog ('Point results: ' + ret);
                        try {
                                eval(ret);
                        } catch (e) {
                                // statusText (siteText['errorText']);
                                // exceptionHandler (e.message);
                        }
                        updateAddressInfo();
                }
        }
}

// change zoom level to match user selected search radius
// 1 mile to 5 miles
function changeZoom() {
	// "addressSearchFormRadius"
	var radius =  document.getElementById ('addressSearchFormRadius').selectedIndex;
	var zoomLevel = 17 - radius;
	// Change map zoom but keep same center.
	// map.setCenter(map.getCenter(),zoomLevel);
	newDateSearch();
}

//]]>
