/// initializes the radial line labels.  Called in the onLoad()
///
function initRadialLabels()
{
	_lbl05 = new GIcon();
	_lbl05.image = "http://www.aptimg.com/review/i/__5mile_label.png";
	_lbl05.iconSize = new GSize(65, 25);
	_lbl05.iconAnchor = new GPoint((65/2), 25);

	_lbl1 = new GIcon();
	_lbl1.image = "http://www.aptimg.com/review/i/_1mile_label.png";
	_lbl1.iconSize = new GSize(65, 25);
	_lbl1.iconAnchor = new GPoint((65/2), 25);

	_lbl2 = new GIcon();
	_lbl2.image = "http://www.aptimg.com/review/i/_2mile_label.png";
	_lbl2.iconSize = new GSize(65, 25);
	_lbl2.iconAnchor = new GPoint((65/2), 25);

	_lbl3 = new GIcon();
	_lbl3.image = "http://www.aptimg.com/review/i/_3mile_label.png";
	_lbl3.iconSize = new GSize(65, 25);
	_lbl3.iconAnchor = new GPoint((65/2), 25);

	_lbl5 = new GIcon();
	_lbl5.image = "http://www.aptimg.com/review/i/_5mile_label.png";
	_lbl5.iconSize = new GSize(65, 25);
	_lbl5.iconAnchor = new GPoint((65/2), 25);		

	_lbl7 = new GIcon();
	_lbl7.image = "http://www.aptimg.com/review/i/_7mile_label.png";
	_lbl7.iconSize = new GSize(65, 25);
	_lbl7.iconAnchor = new GPoint((65/2), 25);

	_lbl9 = new GIcon();
	_lbl9.image = "http://www.aptimg.com/review/i/_9mile_label.png";
	_lbl9.iconSize = new GSize(65, 25);
	_lbl9.iconAnchor = new GPoint((65/2), 25);

	_lbl12 = new GIcon();
	_lbl12.image = "http://www.aptimg.com/review/i/_12mile_label.png";
	_lbl12.iconSize = new GSize(65, 25);
	_lbl12.iconAnchor = new GPoint((65/2), 25);

	_lbl15 = new GIcon();
	_lbl15.image = "http://www.aptimg.com/review/i/_15mile_label.png";
	_lbl15.iconSize = new GSize(65, 25);
	_lbl15.iconAnchor = new GPoint((65/2), 25);

	_lbl25 = new GIcon();
	_lbl25.image = "http://www.aptimg.com/review/i/_25mile_label.png";
	_lbl25.iconSize = new GSize(65, 25);
	_lbl25.iconAnchor = new GPoint((65/2), 25);

	_lbl35 = new GIcon();
	_lbl35.image = "http://www.aptimg.com/review/i/_35mile_label.png";
	_lbl35.iconSize = new GSize(65, 25);
	_lbl35.iconAnchor = new GPoint((65/2), 25);

	_lbl50 = new GIcon();
	_lbl50.image = "http://www.aptimg.com/review/i/_50mile_label.png";
	_lbl50.iconSize = new GSize(65, 25);
	_lbl50.iconAnchor = new GPoint((65/2), 25);

	_lbl100 = new GIcon();
	_lbl100.image = "http://www.aptimg.com/review/i/_100mile_label.png";
	_lbl100.iconSize = new GSize(65, 25);
	_lbl100.iconAnchor = new GPoint((65/2), 25);
}


var Cradius = 50;         	// mile radius
var Ccolor = '#cc0000';  	// color of circle
var Cwidth = 3;          	// width pixels
var d2r = Math.PI/180;   	// degrees to radians
var r2d = 180/Math.PI;   	// radians to degrees
var Clat = (Cradius/3963)*r2d;  // using 3963 as earth's radius
//var CRadPoint1 = null;		// point d1 on the circle's diameter.
//var CRadPoint2 = null;		// point d2 on the circle's diameter.

/// draws a circle centered on x,y, with the parameters defined above.
///
function drawCircle(lngStr,latStr) {

	lng = parseFloat(lngStr);
	lat = parseFloat(latStr);

	var Clng = Clat/Math.cos(lat*d2r);
	var Cpoints = [];

	for (var i=0; i < 33; i++) {
		var theta = Math.PI * (i/16);
		Cx = lng + (Clng * Math.cos(theta));
		Cy = lat + (Clat * Math.sin(theta));

		tmpPnt = new GPoint(Cx,Cy);

		Cpoints.push(tmpPnt);
/*
		//find the right diameter point.
		if( i==0 ) 
		{
			CRadPoint1 = new GPoint(Cx,Cy);

			// uncomment to actually see the d1 point.
			//map.addOverlay( new GMarker(CRadPoint1) );
		}

		//find the left diameter point.
		else 
*/			
		if( i==16 )
		{			
			CRadPoint2 = new GPoint(Cx,Cy);

			// uncomment to actually see the d2 point.
			//map.addOverlay( new GMarker(CRadPoint2) );
		}


//			map.addOverlay(new GMarker(new GPoint(Cx,Cy)));
	};

	
	/// draw the circle.
	try {
		if( map )
		{
			map.addOverlay( new GPolyline(Cpoints,Ccolor,Cwidth) );
		}
	} catch(ig) {}
	
	try {
		if( _map )
		{
			_map.addOverlay( new GPolyline(Cpoints,Ccolor,Cwidth) );
		}
	} catch(ig) {}

	/*
	if( navigator.appName == "Netscape" )
	{		
		/// draw the radial line.
		var RadLine = [];
		RadLine.push( CRadPoint2 );
		RadLine.push( groundZero );
		map.addOverlay(new GPolyline(RadLine,Ccolor,Cwidth));

		doRadialLinelabel();
	}
	*/
} 



/// displays the radial line's label.
///
function doRadialLinelabel()
{
	curRad = document.getElementById( 'radius_distance' ).value;

	switch( curRad )
	{
		case '.5':
			myLbl = _lbl05;
			break;
		case '1':
			myLbl = _lbl1;
			break;
		case '2':
			myLbl = _lbl2;
			break;
		case '3':
			myLbl = _lbl3;
			break;
		case '5':
			myLbl = _lbl5;
			break;
		case '7':
			myLbl = _lbl7;
			break;
		case '9':
			myLbl = _lbl9;
			break;
		case '12':
			myLbl = _lbl12;
			break;
		case '15':
			myLbl = _lbl15;
			break;
		case '25':
			myLbl = _lbl25;
			break;
		case '35':
			myLbl = _lbl35;
			break;
		case '50':
			myLbl = _lbl50;
			break;
		case '100':
			myLbl = _lbl100;
			break;

		default: 			
			myLbl = _lbl05;
			break;
	}

	map.addOverlay(new GMarker(getMidGPoint(CRadPoint2, groundZero), myLbl));
}

/// changes the radius of the circles drawn by drawCircle()
///
function changeDrawCircleRadius( miles )
{
	Cradius = miles;
	Clat = (Cradius/3963)*r2d;
}

/// true if the camera can rezoom to fit the circle, false if it cannot.
var bRecalcOn = true;

/// triggered by the user changing the radius dropdown
///
function onRadiusChange()
{	
	bRecalcOn = true;
	changeLocation();
}


/// the user's control for zooming in on the map
///
function onZoomIn()
{
	//Returns the integer zoom level of the map.
	zoomLevel = map.getZoomLevel() 	

	zoomLevel--;

	//Zooms to the given integer zoom level, ignoring the request if the given zoom level is outside the bounds of the current map type.
	map.zoomTo( zoomLevel ); 

	// disallow best-fit zooming after the zoom level has been manually adjusted.
	bRecalcOn = false;
}

/// the user's control for zooming in on the map
///
function onZoomOut()
{
	//Returns the integer zoom level of the map.
	zoomLevel = map.getZoomLevel() 	

	zoomLevel++;

	//Zooms to the given integer zoom level, ignoring the request if the given zoom level is outside the bounds of the current map type.
	map.zoomTo( zoomLevel ); 

	// disallow best-fit zooming after the zoom level has been manually adjusted.
	bRecalcOn = false;
}

/// A helper function that returns true if the 
/// point is within the bounds, false if not.
function isPointInBounds( _gpoint, _gbounds )
{
	/*
	minX 	The x coordinate of the top left corner of the bounds.
	minY 	The y coordinate of the top left corner of the bounds.
	maxX 	The x coordinate of the bottom right corner of the bounds.
	maxY 	The y coordinate of the bottom right corner of the bounds.
	*/

	if(  
		_gbounds.minX <= _gpoint.x &&
		_gbounds.maxX >= _gpoint.x &&

		_gbounds.minY <= _gpoint.y &&
		_gbounds.maxY >= _gpoint.y
	) {
		return true;
	}

	return false;	
}

var noTrigger = false;

/// Changes the centerpoint of the map to reflect the current location, 
/// and alters the zoom level if the current radius circle is truncated.
///
/// Called anything any of the search fields are changed, and on initial load.
///
function changeLocation()
{
	/// clears the map.
	map.clearOverlays();

	oldZoom = map.getZoomLevel();

	newZoom = zoomLookupTable();

	/// This whole tree could be reduced into two execution cases.
	/// we only want to pan if the new centerpoint is already within the current mapview's bounds.
	if( bRecalcOn )
	{
		if( newZoom == oldZoom && isPointInBounds(groundZero, map.getBoundsLatLng()) )
		{
			noTrigger = true;

			map.recenterOrPanToLatLng( groundZero );

			noTrigger = false;
		}
		else
		{
			noTrigger = true;

			map.centerAndZoom( groundZero, newZoom );

			noTrigger = false;
		}
	}
	else
	{

		if( isPointInBounds(groundZero, map.getBoundsLatLng()) )
		{
			/// recenters and pans
			noTrigger = true;

			map.recenterOrPanToLatLng( groundZero );

			noTrigger = false;
		}
		else
		{
			noTrigger = true;

			map.centerAndZoom( groundZero, oldZoom );

			noTrigger = false;
		}		
	}
}

/// Summon an ajax call to the location lookup, 
/// change groundZero to the returned location, 
/// allow rezooming to happen,
/// and invoke changeLocation()
///
function doLocationFind()
{
	hideInvalidLocationMessage();

	var addr  = document.getElementById( 'addr' ).value;
	var city  = document.getElementById( 'city' ).value;
	var state = document.getElementById( 'state' ).value;

	if( !addr && !city ) return;

	var url = "/rate/GetLatLon/?state="+state+"&address="+addr+"&city="+city;

	try {
	    // branch for native XMLHttpRequest object
	    if (window.XMLHttpRequest) {
		reqPop = new XMLHttpRequest();
		reqPop.onreadystatechange = setGroundZero;
		reqPop.open("GET", url, true);
		reqPop.send(null);
	    // branch for IE/Windows ActiveX version
	    } else if (window.ActiveXObject) {
		reqPop = new ActiveXObject("Microsoft.XMLHTTP");
		if (reqPop) {
		    reqPop.onreadystatechange = setGroundZero;
		    reqPop.open("GET", url, true);
		    reqPop.send();
		}
	    }
	} catch( e ) { alert( "ajaxNewNeighb ERROR: '"+e+"'" ) }
}

/// Summon an ajax call to the zip lookup, 
/// change groundZero to the returned location, 
/// allow rezooming to happen,
/// and invoke changeLocation()
///
function doZipFind()
{
	hideInvalidLocationMessage();

	var zip = document.getElementById( 'zip' ).value;

	if( !zip ) return;

	var url = "/rate/GetLatLon/?zip=" + zip;

	try {
	    // branch for native XMLHttpRequest object
	    if (window.XMLHttpRequest) {
		reqPop = new XMLHttpRequest();
		reqPop.onreadystatechange = setGroundZero;
		reqPop.open("GET", url, true);
		reqPop.send(null);
	    // branch for IE/Windows ActiveX version
	    } else if (window.ActiveXObject) {
		reqPop = new ActiveXObject("Microsoft.XMLHTTP");
		if (reqPop) {
		    reqPop.onreadystatechange = setGroundZero;
		    reqPop.open("GET", url, true);
		    reqPop.send();
		}
	    }
	} catch( e ) { alert( "ajaxNewNeighb ERROR: '"+e+"'" ) }
}

/// set the new ground zero based upon the xml returned.
///
function setGroundZero()
{
	// only if req shows "complete"
	if (reqPop.readyState == 4) {
		// only if "OK"

		if (reqPop.status == 200) {
			// ...processing statements go here...

			var xmlDoc = reqPop.responseXML;

			var neighbList = false;
			try {
				coord = xmlDoc.documentElement.getElementsByTagName("geo");
			} catch(exp1) {
				coord = false;
			}

			if( coord && coord.length == 1 )
			{
				groundZero = new GPoint( coord[0].getAttribute("lon"),coord[0].getAttribute("lat") );

				bRecalcOn = true;
				changeLocation();
			}
			else
			{
				showInvalidLocationMessage();
			}
		}
	}
}

/// Returns a gpoint halfway between the two given ones.
///
function getMidGPoint( _gpt1, _gpt2 )
{
	gMG_x = (_gpt1.x+_gpt2.x)/2;
	gMG_y = (_gpt1.y+_gpt2.y)/2;

	return new GPoint(gMG_x,gMG_y);
}

/// hide the message that says "yo, that search was terrible!"
///	
function hideInvalidLocationMessage()
{
	msgNode = document.getElementById( 'badSearchMsg' );

	msgNode.style.display = 'none';
}

/// show the message that says "yo, that search was terrible!"
///	
function showInvalidLocationMessage()
{
	msgNode = document.getElementById( 'badSearchMsg' );

	msgNode.style.display = 'block';
}

/// returns a zoom int based upon a 'best guess' concerning 
/// This table needs to be remade if you ever change the w/h of the map,
/// 
///
/// presently specced for: 160,112)
function zoomLookupTable()
{
	curRad = document.getElementById( 'radius_distance' ).value;

	if( curRad <= .5 )
		return 4;
	if( curRad <= 1 )
		return 5;
	if( curRad <= 2 )
		return 6;
	if( curRad <= 3 )
		return 7;
	if( curRad <= 5 )
		return 8;
	if( curRad <= 7 )
		return 8;
	if( curRad <= 9 )
		return 9;
	if( curRad <= 12 )
		return 9;
	if( curRad <= 15 )
		return 9;
	if( curRad <= 25 )
		return 10;
	if( curRad <= 35 )
		return 11;
	if( curRad <= 50 )
		return 11;
	if( curRad <= 100 )
		return 12;

	return 12;
}

function saveLocation()
{
	curRad = document.getElementById( 'radius_distance' ).value;

	alert( map.getCenterLatLng() );
	alert( curRad + " mile radius" );
}