function mapLoaded(a,r) {
	//<![CDATA[
	
	_mSvgEnabled = true ;
	_mSvgForced  = true ;

	var center ;
	var circle ;
	var radius = r;
	var marker = [] ;
	var poly = [] ;
	var line ;
	
	var map = new google.maps.Map2(document.getElementById("map"));
	map.setCenter(new google.maps.LatLng(43.5425,-96.6964), 13);
	
	map.addControl(new GLargeMapControl());
	map.addControl(new GMapTypeControl());
	map.addControl(new GScaleControl());
	map.addControl(new GOverviewMapControl());
	
	var geocoder = new GClientGeocoder();
	
	var icon = new GIcon();
	icon.image = "http://labs.google.com/ridefinder/images/mm_20_red.png";
	icon.shadow = "http://labs.google.com/ridefinder/images/mm_20_shadow.png";
	icon.iconSize = new GSize(12, 20);
	icon.shadowSize = new GSize(22, 20);
	icon.iconAnchor = new GPoint(6, 20);
	
	var gicon = new GIcon(icon);
	gicon.image = "http://labs.google.com/ridefinder/images/mm_20_green.png";
	gicon.iconAnchor = new GPoint(-20, 20);
	
	var zoomLevel;
	
	if (r == 5) {
		zoomLevel = 9;
	} else if (r==10) {
		zoomLevel = 7;
	} else if (r==25) {
		zoomLevel = 6;
	} else if (r==50) {
		zoomLevel = 5;
	} else if (r==100) {
		zoomLevel = 4;
	} else {
		zoomLevel = 3;
	}
	
	
	showAddress(a,r,zoomLevel);
		
	










	/*********************************************************************\
	*                                                                     *
	* epolys.js                                          by Mike Williams *
	*                                                                     *
	* A Google Maps API Extension                                         *
	*                                                                     *
	* Adds various Methods to GPolygon and GPolyline                      *
	*                                                                     *
	* .Contains(latlng) returns true is the poly contains the specified   *
	*                   GLatLng                                           *
	*                                                                     *
	* .Area()           returns the approximate area of a poly that is    *
	*                   not self-intersecting                             *
	*                                                                     *
	* .Distance()       returns the length of the poly path               *
	*                                                                     *
	* .Bounds()         returns a GLatLngBounds that bounds the poly      *
	*                                                                     *
	* .GetPointAtDistance() returns a GLatLng at the specified distance   *
	*                   along the path.                                   *
	*                   The distance is specified in metres               *
	*                   Reurns null if the path is shorter than that      *
	*                                                                     *
	* .GetIndexAtDistance() returns the vertex number at the specified    *
	*                   distance along the path.                          *
	*                   The distance is specified in metres               *
	*                   Reurns null if the path is shorter than that      *
	*                                                                     *
	* .Bearing(v1?,v2?) returns the bearing between two vertices          *
	*                   if v1 is null, returns bearing from first to last *
	*                   if v2 is null, returns bearing from v1 to next    *
	*                                                                     *
	*                                                                     *
	***********************************************************************
	*                                                                     *
	*   This Javascript is provided by Mike Williams                      *
	*   Blackpool Community Church Javascript Team                        *
	*   http://www.commchurch.freeserve.co.uk/                            *
	*   http://econym.googlepages.com/index.htm                           *
	*                                                                     *
	*   This work is licenced under a Creative Commons Licence            *
	*   http://creativecommons.org/licenses/by/2.0/uk/                    *
	*                                                                     *
	***********************************************************************
	*                                                                     *
	* Version 1.1       6-Jun-2007                                        *
	* Version 1.2       1-Jul-2007 - fix: Bounds was omitting vertex zero *
	*                                add: Bearing                         *
	*                                                                     *
	\*********************************************************************/


	// === A method for testing if a point is inside a polygon
	// === Returns true if poly contains point
	// === Algorithm shamelessly stolen from http://alienryderflex.com/polygon/ 
	GPolygon.prototype.Contains = function(point) {
	  var j=0;
	  var oddNodes = false;
	  var x = point.lng();
	  var y = point.lat();
	  for (var i=0; i < this.getVertexCount(); i++) {
	    j++;
	    if (j == this.getVertexCount()) {j = 0;}
	    if (((this.getVertex(i).lat() < y) && (this.getVertex(j).lat() >= y))
	    || ((this.getVertex(j).lat() < y) && (this.getVertex(i).lat() >= y))) {
	      if ( this.getVertex(i).lng() + (y - this.getVertex(i).lat()) / (this.getVertex(j).lat()-this.getVertex(i).lat()) * (this.getVertex(j).lng() - this.getVertex(i).lng())<x ) {
	        oddNodes = !oddNodes
	      }
	    }
	  }
	  return oddNodes;
	}

	// === A method which returns the approximate area of a non-intersecting polygon in square metres ===
	// === It doesn't fully account for spechical geometry, so will be inaccurate for large polygons ===
	// === The polygon must not intersect itself ===
	GPolygon.prototype.Area = function() {
	  var a = 0;
	  var j = 0;
	  var b = this.Bounds();
	  var x0 = b.getSouthWest().lng();
	  var y0 = b.getSouthWest().lat();
	  for (var i=0; i < this.getVertexCount(); i++) {
	    j++;
	    if (j == this.getVertexCount()) {j = 0;}
	    var x1 = this.getVertex(i).distanceFrom(new GLatLng(this.getVertex(i).lat(),x0));
	    var x2 = this.getVertex(j).distanceFrom(new GLatLng(this.getVertex(j).lat(),x0));
	    var y1 = this.getVertex(i).distanceFrom(new GLatLng(y0,this.getVertex(i).lng()));
	    var y2 = this.getVertex(j).distanceFrom(new GLatLng(y0,this.getVertex(j).lng()));
	    a += x1*y2 - x2*y1;
	  }
	  return Math.abs(a * 0.5);
	}

	// === A method which returns the length of a path in metres ===
	GPolygon.prototype.Distance = function() {
	  var dist = 0;
	  for (var i=1; i < this.getVertexCount(); i++) {
	    dist += this.getVertex(i).distanceFrom(this.getVertex(i-1));
	  }
	  return dist;
	}

	// === A method which returns the bounds as a GLatLngBounds ===
	GPolygon.prototype.Bounds = function() {
	  var bounds = new GLatLngBounds();
	  for (var i=0; i < this.getVertexCount(); i++) {
	    bounds.extend(this.getVertex(i));
	  }
	  return bounds;
	}

	// === A method which returns a GLatLng of a point a given distance along the path ===
	// === Returns null if the path is shorter than the specified distance ===
	GPolygon.prototype.GetPointAtDistance = function(metres) {
	  // some awkward special cases
	  if (metres == 0) return this.getVertex(0);
	  if (metres < 0) return null;
	  var dist=0;
	  var olddist=0;
	  for (var i=1; (i < this.getVertexCount() && dist < metres); i++) {
	    olddist = dist;
	    dist += this.getVertex(i).distanceFrom(this.getVertex(i-1));
	  }
	  if (dist < metres) {return null;}
	  var p1= this.getVertex(i-2);
	  var p2= this.getVertex(i-1);
	  var m = (metres-olddist)/(dist-olddist);
	  return new GLatLng( p1.lat() + (p2.lat()-p1.lat())*m, p1.lng() + (p2.lng()-p1.lng())*m);
	}

	// === A method which returns the Vertex number at a given distance along the path ===
	// === Returns null if the path is shorter than the specified distance ===
	GPolygon.prototype.GetIndexAtDistance = function(metres) {
	  // some awkward special cases
	  if (metres == 0) return this.getVertex(0);
	  if (metres < 0) return null;
	  var dist=0;
	  var olddist=0;
	  for (var i=1; (i < this.getVertexCount() && dist < metres); i++) {
	    olddist = dist;
	    dist += this.getVertex(i).distanceFrom(this.getVertex(i-1));
	  }
	  if (dist < metres) {return null;}
	  return i;
	}

	// === A function which returns the bearing between two vertices in decgrees from 0 to 360===
	// === If v1 is null, it returns the bearing between the first and last vertex ===
	// === If v1 is present but v2 is null, returns the bearing from v1 to the next vertex ===
	// === If either vertex is out of range, returns void ===
	GPolygon.prototype.Bearing = function(v1,v2) {
	  if (v1 == null) {
	    v1 = 0;
	    v2 = this.getVertexCount()-1;
	  } else if (v2 ==  null) {
	    v2 = v1+1;
	  }
	  if ((v1 < 0) || (v1 >= this.getVertexCount()) || (v2 < 0) || (v2 >= this.getVertexCount())) {
	    return;
	  }
	  var from = this.getVertex(v1);
	  var to = this.getVertex(v2);
	  if (from.equals(to)) {
	    return 0;
	  }
	  var lat1 = from.latRadians();
	  var lon1 = from.lngRadians();
	  var lat2 = to.latRadians();
	  var lon2 = to.lngRadians();
	  var angle = - Math.atan2( Math.sin( lon1 - lon2 ) * Math.cos( lat2 ), Math.cos( lat1 ) * Math.sin( lat2 ) - Math.sin( lat1 ) * Math.cos( lat2 ) * Math.cos( lon1 - lon2 ) );
	  if ( angle < 0.0 ) angle  += Math.PI * 2.0;
	  angle = angle * 180.0 / Math.PI;
	  return parseFloat(angle.toFixed(1));
	}




	// === Copy all the above functions to GPolyline ===
	GPolyline.prototype.Contains             = GPolygon.prototype.Contains;
	GPolyline.prototype.Area                 = GPolygon.prototype.Area;
	GPolyline.prototype.Distance             = GPolygon.prototype.Distance;
	GPolyline.prototype.Bounds               = GPolygon.prototype.Bounds;
	GPolyline.prototype.GetPointAtDistance   = GPolygon.prototype.GetPointAtDistance;
	GPolyline.prototype.GetIndexAtDistance   = GPolygon.prototype.GetIndexAtDistance;
	GPolyline.prototype.Bearing              = GPolygon.prototype.Bearing;



















	
	
	
	// Draw
	function draw() {
		
		var bounds ;

		var html = '' ;
		poly = [] ; 

		for(var i = 0 ; i < marker.length ;i++) {
			poly.push(marker[i].getPoint()) ;
			html += marker[i].getPoint().toUrlValue() + "<br>\n" ;
		}
		
		if(line) {
			map.removeOverlay(line) ;
		}

		poly.push(marker[0].getPoint()) ;

		//html += marker[0].getPoint().toUrlValue() + "<br>\n" ;

		line = new GPolyline(poly,'#FF0000', 3, 1) ;
		// map.addOverlay(line) ;

		// html = "Polygon Coordinates:<br>\n" + html + "<br>" ;

		// document.getElementById("sidebar").innerHTML = html ;
		return ( poly )
	}
	
	// Draw a circle...
	function drawCircle( ) {
		for(var n = 0 ; n < marker.length; n++) {
			map.removeOverlay( marker[n] );
		}
		marker = [];
		var points = [];
		var point = center.getPoint();
		var lat = point.lat();
		var lng = point.lng();
		if (center.oldpoint) {                // Move radius when center is moved
			var p = radius.getPoint();
			var x = point.lat() - center.oldpoint.lat();
			var y = point.lng() - center.oldpoint.lng();
			radius.setPoint( new GLatLng( p.lat() + x, p.lng() + y) ) ;
		}
		center.oldpoint = point;
		var Cradius = point.distanceFrom(radius.getPoint()) * 0.000621371192 ;
		// document.addr.radius.value = Math.round(Cradius * 100)/100 ;
		var b = radius.getPoint() ;
		var meters = distance(point.lat(),point.lng(),b.lat(),b.lng()) ;
		var Ccolor = '#0000ff' ;               // color blue
		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 Clng = Clat/Math.cos(lat*d2r);
		var Cpoints = [] ;
		var list = '' ;
		for (var i = 0 ; i < 13 ; i++) {
			var theta = Math.PI * (i/6) ;
			Cx = lng + (Clng * Math.cos(theta)) ;
			Cy = lat + (Clat * Math.sin(theta)) ;
			Cpoints.push(new GLatLng(Cy,Cx)) ;
			points.push(new GLatLng(Cy,Cx)) ;
		}

		for(var n = 0 ; n < (points.length -1) ; n++) {
			marker[n] = new GMarker(points[n], {icon:gicon, draggable: true, title: n});
			/*
			map.addOverlay(marker[n]);
			marker[n].enableDragging();
			GEvent.addListener(marker[n],'dragend',function() {draw()});
			*/
		}

		var poly = draw() ;

		map.setCenter(center.getPoint(), map.getBoundsZoomLevel(getMBR( poly ))) ;
		
		var r_gpolyline = new GPolyline(poly,'#FF0000', 3, 1);
		var r_gpolygon = new GPolygon(poly,'#FF0000',3,0.8,'#FF0000',0.25);
		
		// map.addOverlay(r_gpolygon);
		
		return {
			'MBR':getMBR(poly),
			'gPolyline':r_gpolyline,
			'gPoly':r_gpolygon
		}
	}

	// Find the address using the geocoder...
	function showAddress(address,miles, zoomLevel) {
		geocoder.getLatLng(address, function(point) {
			if (!point) {
				alert(address + " not found")
			} else {
				findDealers(point,miles);
				map.setCenter(point,zoomLevel);
				toggleForm();
				
				/*
				if (center) {
					map.removeOverlay(center);
					map.removeOverlay(radius);
				}
				center = new GMarker(point, {icon:gicon, draggable: true,  title: address});
				center.enableDragging();
				map.addOverlay(center);
				GEvent.addListener(center,'dragend',function() {drawCircle()});
				var oldpoint = center.getPoint();
				radius = new GMarker(getRadius(miles,center), {icon:gicon, draggable: true,  title: "Radius"});
				*/
				/*
				map.addOverlay(radius);
				radius.enableDragging();
				GEvent.addListener(radius,'dragend',function() {drawCircle()});
				*/
				
				//var areaInfo = drawCircle();
				
				// Let's find the dealers
				/*
				findDealers(areaInfo,point,address, miles);
				toggleForm();
				*/
			}
		});
	}

	// Calculate the distance...
	function distance(lat1,lng1,lat2,lng2) {
		var O = Math.PI/180 ;
		var b = lat1 * O ;
		var c = lat2 * O ;
		var d = b - c ;
		var e = (lng1 * O) - (lng2 * O) ;
		var f = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(d/2),2)+Math.cos(b)*Math.cos(c)*Math.pow(Math.sin(e/2),2)));
		return f*6378137
	}

	// Figure out the radial point...
	function getRadius( miles, center ) {
		var point = center.getPoint() ;
		var lat = point.lat() ;
		var lng = point.lng() ;
		var d2r = Math.PI/180 ;                // degrees to radians
		var r2d = 180/Math.PI ;                // radians to degrees
		var Clat = (miles/3963) * r2d ;       //  using 3963 as earth's radius
		var Clng = Clat/Math.cos(lat*d2r);
		Clng = lng + (Clng * Math.cos(0)) ;
		Clat = lat + (Clat * Math.sin(0)) ;
		return(new GLatLng(Clat,Clng)) ;
	}

	// Minimum Bounding Rectangle...
	function getMBR (points) {
		var minx = 0;
		var miny = 0;
		var maxx = 0;
		var maxy = 0;
		
		// console.log(points);

		if ( points.length < 4 ) {
			return ( GLatLngBounds(new GLatlng(minx,miny), new GLatlng(maxx,maxy)) ) ;
		}

		minx = points[0].lat() ;
		miny = points[0].lng() ;
		maxx = points[0].lat() ;
		maxy = points[0].lng() ;

		for(var i = 1; i < points.length ; i++ ) {
			if ( points[i].lat() > maxx ) {
				maxx = points[i].lat() ;
			}
			if ( points[i].lat() < minx ) {
				minx = points[i].lat() ;
			}
			if ( points[i].lng() > maxy ) {
				maxy = points[i].lng() ;
			}
			if ( points[i].lng() < miny ) {
				miny = points[i].lng() ;
			}
		}

		return ( new GLatLngBounds(new GLatLng(maxx,miny), new GLatLng(minx,maxy)) ) ;
		// return ( new GLatLngBounds( new GLatLng(miny,maxx), new GLatLng(maxy,minx)));
	}
	
	function findDealers(startPoint,miles) {
		var addLat = startPoint.lat();//46.53;
		var addLon = startPoint.lng();//-96.73
		var addType =  $('#dtype').val();//'A';
	// Query the DB for Dealers
		$.ajax({
			type: 'POST',
			url: '/cr/php/dbq.php',
			dataType:'json',
			data: {
				//dtype: $('#dtype').val(),
				dtype: addType,
				//minlat: startPoint.lat(),
				minlat: addLat,
				//minlon: startPoint.lon(),
				minlon: addLon,
				drad: miles
				//drad: 25
			},
			success: function(data) {
				$(data).each(function(n,o) {
					var pt = new GLatLng(this.lat,this.lon);
					var info = {
						'dtype':this.dtype,
						'name':ucwords(this.name),
						'addr':this.addr_1,
						'csz':this.city+' '+this.state+', '+this.zip,
						'phone':this.phone,
						'email':this.email
					}
					var mk = new GMarker(pt, {icon:icon,title: this.name});
					GEvent.addListener(mk,'click',function() {
						showInfo(pt,info);
						//showDirections(pt,startPoint);
					});
					map.addOverlay(mk);
				});
			}
		});
	}

	
	function showInfo(pt,info) {
		map.panTo(pt);
		var html = '<h2>'+info.name+'</h2>'+
			'<p>'+info.addr+'<br>'+info.csz+'</p>'+
			'<p><strong>Phone:</strong> '+info.phone+'<br>';
		if (info.email != '') {
			html = html + '<strong>Email: </strong><A href=mailto:'+info.email+'>'+info.email+'</a>';
		}
		html = html + '</p>';
		map.openInfoWindowHtml(pt,html);
	}
	
	function showDirections(to,from) {
		var gdir = new GDirections(map);
		gdir.load('from: '+from+' to: '+to);
		GEvent.addListener(gdir,'load',function() {
			// console.log(this.getDistance());
		});
	}
	
	function onGDirLoad() {
		// console.log(gdir.getStatus().code);
	}
	
	
}	

function jqLoaded () {
	$('form#locator').submit(function() {
		var f = ['uaddr','ucity','ustate','uzip'];
		var addArray = [];
		$(f).each(function(n,k) {
			var v = $('form#locator #'+k).val();
			if (v != '') addArray.push(v);
		});
		var add = addArray.join(', ');
		var rad = $('select#drad').val();
		if (add != '' && rad != '' && rad < 251) {
			mapLoaded(add,rad);
		}
		return false;
	});
	$('li#show-form').click(function() {
		toggleForm(true);
	});
}

function toggleForm() {
	var state = (arguments[0])?arguments[0]:false;
	if ($('form#locator:visible').length && !state) {
		$('form#locator').fadeOut(400);
		$('li#show-form').fadeIn(200);
	} else {	
		$('form#locator').fadeIn(200);
		$('li#show-form').fadeOut(400);
	}
}

function ucwords( str ) {
	str.toLowerCase();
	return (str+'').replace(/^(.)|\s(.)/g, function ( $1 ) { return $1.toUpperCase( ); } );
}

google.load("maps","2", {"callback":jqLoaded});