﻿

var RadiusCircle = null;
var RadiusCircleBounds = null;
var CircleObject = null;

function DrawRadius(MapObj, GLatLngCenter, RadiusMiles)
{
    var strokeColor = "#ffffff";
    var strokeWeight = 6;
    var strokeOpacity = 0.40;
    var fillColor = "#0066ff";
    var fillOpacity = 0.25;
    var opts = {};
    
    //return doDrawRadiusCircle(MapObj, GLatLngCenter, RadiusMiles, strokeColor, strokeWeight, strokeOpacity, fillColor, fillOpacity, opts);
   
    return InitializeRadiusWidget(MapObj, GLatLngCenter, RadiusMiles, strokeColor, strokeWeight, strokeOpacity, fillColor, fillOpacity, opts);
   
}

function MilesToKilometers(miles)
{
	return miles * 1.609;
}

function KilometersToMiles(km)
{
	return km / 1.609;
}

function doDrawRadiusCircle(MapObj, GLatLngCenter, RadiusMiles, strokeColor, strokeWeight, strokeOpacity, fillColor, fillOpacity, opts)
{   
	/* v.3 */
	var cOptions = {
		map: MapObj
		,center: GLatLngCenter
		,strokeColor: strokeColor
		,strokeWeight: strokeWeight
		,strokeOpacity: strokeOpacity
		,fillColor: fillColor
		,fillOpacity: fillOpacity
		,radius: 2.59 * ( ( MilesToKilometers(RadiusMiles) * oneMileKilometer ) * 1000 ) /* in square meters */
	};
		if (CircleObject != null)
		{
			CircleObject.setMap(null); // remove from map
		}
		CircleObject = new google.maps.Circle(cOptions);
		CircleObject.setMap(Map);
		
		return CircleObject.getBounds();
		
    /* v.2
    if (RadiusCircle != null)
    {
        MapObj.removeOverlay(RadiusCircle);
    }
    
	var RadiusCircleBounds = new GLatLngBounds();
 
	var circlePoints = Array();
 
	with (Math) 
	{
	    var distance = RadiusMiles/3963.189;	// radians, miles
	    
	    distance = distance + ((distance/100)*15) // fudge it 7%
	    
	    //var distance = RadiusMiles/6378.8;	// radians, kilometers
 
		var Latitude1 = (PI/180)* GLatLngCenter.lat(); // radians
		var Longitude1 = (PI/180)* GLatLngCenter.lng(); // radians
 
		for (var a = 0 ; a < 361 ; a++ ) 
		{
			var tc = (PI/180)*a;
			var y = asin(sin(Latitude1)*cos(distance)+cos(Latitude1)*sin(distance)*cos(tc));
			var DistanceLongitude = atan2(sin(tc)*sin(distance)*cos(Latitude1),cos(distance)-sin(Latitude1)*sin(y));
			var x = ((Longitude1-DistanceLongitude+PI) % (2*PI)) - PI ; // MOD function
			var point = new GLatLng(parseFloat(y*(180/PI)),parseFloat(x*(180/PI)));
			circlePoints.push(point);
			RadiusCircleBounds.extend(point);
		}
 
        //GPolygon(latlngs:GLatLng[], strokeColor?:String, strokeWeight?:Number, strokeOpacity?:Number, fillColor?:Number, fillOpacity?:Number, opts?:GPolygonOptions)
        
//		if (distance < 1.5678565720686044) 
//		{
//			RadiusCircle = new GPolygon(circlePoints, '#000000', 2, 1, '#000000', 0.25);	
//		}
//		else 
//		{
//			RadiusCircle = new GPolygon(circlePoints, '#000000', 2, 1);	
//		}

        RadiusCircle = new GPolygon(circlePoints, strokeColor, strokeWeight, strokeOpacity, fillColor, fillOpacity, opts);	

	}
	
	MapObj.addOverlay(RadiusCircle); 
	
	return RadiusCircleBounds;
	*/
}

var RadiusHandle_Center = new google.maps.MarkerImage(Static + "/reno/custom/wrappers/gabriels/images/icons/icons_google_map.png"
		,new google.maps.Size(15, 15)	// This marker is 15 pixels wide by 18 pixels tall.
		,new google.maps.Point(0, 90)	// The origin for this image on the sprite
		,new google.maps.Point(8, 8)	// The anchor for this image
	);
var RadiusHandle_Distance = new google.maps.MarkerImage(Static + "/reno/custom/wrappers/gabriels/images/icons/icons_google_map.png"
		,new google.maps.Size(15, 15)	// This marker is 15 pixels wide by 18 pixels tall.
		,new google.maps.Point(20, 90)	// The origin for this image on the sprite
		,new google.maps.Point(8, 8)	// The anchor for this image
	);
 /**
* A distance widget that will display a circle that can be resized and will
* provide the radius in km.
*
* @param {google.maps.Map} map The map to attach to.
*
* @constructor
*/
function DistanceWidget(MapObj, GLatLngCenter, RadiusMiles, strokeColor, strokeWeight, strokeOpacity, fillColor, fillOpacity, opts) 
{
	this.set('map', MapObj);
	this.set('position', GLatLngCenter);

	var marker = new google.maps.Marker({
	  draggable: true,
	  title: 'Drag to move the center point; Double-click to recenter',
	  icon: RadiusHandle_Center,
	  zIndex: 100000000
	});

	google.maps.event.addListener(marker, 'dragend', function() 
	{
		displayInfo(distanceWidget);
	});
	google.maps.event.addListener(marker, 'dblclick', function() 
	{
		this.get('map').fitBounds(DWCircle.getBounds());
	});
	
	// Bind the marker map property to the DistanceWidget map property
	marker.bindTo('map', this);

	// Bind the marker position property to the DistanceWidget position
	// property
	marker.bindTo('position', this);

	// Create a new radius widget
	var radiusWidget = new RadiusWidget(MapObj, GLatLngCenter, RadiusMiles, strokeColor, strokeWeight, strokeOpacity, fillColor, fillOpacity, opts);

	this.set('radiusWidget', radiusWidget);
	this.set('marker', marker);
	
	// Bind the radiusWidget map to the DistanceWidget map
	radiusWidget.bindTo('map', this);

	// Bind the radiusWidget center to the DistanceWidget position
	radiusWidget.bindTo('center', this, 'position');

	// Bind to the radiusWidgets' distance property
	this.bindTo('distance', radiusWidget);

	// Bind to the radiusWidgets' bounds property
	this.bindTo('bounds', radiusWidget);
	
}

DistanceWidget.prototype = new google.maps.MVCObject();
var DWCircle = new google.maps.MVCObject(); // public
var DWCircleOptions; // public
var DWCircleOptionsEdit = {
	strokeColor: "000000"
	,strokeOpacity: 1.00
	,strokeWeight: 2
	,fillColor: "000000"
};

DistanceWidget.prototype.Remove = function()
{
	DWCircle.setMap(null);
	this.get('radiusWidget').unbindAll();
	this.unbindAll();
};
//var fudge = 1.10;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//	Radius Widget
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function RadiusWidget(MapObj, GLatLngCenter, RadiusMiles, strokeColor, strokeWeight, strokeOpacity, fillColor, fillOpacity, opts) 
{

	DWCircleOptions = {
		strokeColor: strokeColor
		,strokeWeight: strokeWeight
		,strokeOpacity: strokeOpacity
		,fillColor: fillColor
		,fillOpacity: fillOpacity
	};
	
	DWCircle = new google.maps.Circle(DWCircleOptions);
	DWCircle.setOptions({
		center: GLatLngCenter
		,radius: MilesToKilometers(RadiusMiles) * 1000 /* in meters */
	});

	// Set the distance property value, default to 50km.
	this.set('distance', MilesToKilometers(RadiusMiles));

	// Bind the RadiusWidget bounds property to the circle bounds property.
	this.bindTo('bounds', DWCircle);

	// Bind the circle center to the RadiusWidget center property
	DWCircle.bindTo('center', this);

	// Bind the circle map to the RadiusWidget map
	DWCircle.bindTo('map', this);

	// Bind the circle radius property to the RadiusWidget radius property
	DWCircle.bindTo('radius', this);

	// Add the sizer marker
	this.addSizer_();
}

RadiusWidget.prototype = new google.maps.MVCObject();


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//	Update the radius when the distance has changed.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
RadiusWidget.prototype.distance_changed = function() 
{
	this.set('radius', this.get('distance') * 1000);
};


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//	Add the sizer marker to the map.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
RadiusWidget.prototype.addSizer_ = function() 
{
	var sizer = new google.maps.Marker({
	  draggable: true,
	  title: 'Drag to change the radius',
	  icon: RadiusHandle_Distance,
	  zIndex: 100000000
	});

	sizer.bindTo('map', this);
	sizer.bindTo('position', this, 'sizer_position');

	var me = this;
	google.maps.event.addListener(sizer, 'drag', function() 
	{
		// Set the circle distance (radius)
		me.setDistance();
		if (KilometersToMiles(me.get('distance_absolute')) <= 250)
		{
			me.set('sizer_position_legal', me.get('sizer_position'));
		}
	});
	google.maps.event.addListener(sizer, 'dragend', function() 
	{
		displayInfo(distanceWidget);
		
		if (KilometersToMiles(me.get('distance_absolute')) > 250)
		{
			me.set('sizer_position', me.get('sizer_position_legal'));
		}
	});
	
};


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//	Update the center of the circle and position the sizer back on the line.
//
//	Position is bound to the DistanceWidget so this is expected to change when
//	the position of the distance widget is changed.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
RadiusWidget.prototype.center_changed = function() 
{
	var bounds = this.get('bounds');

	// Bounds might not always be set so check that it exists first.
	if (bounds) 
	{
		var lng = bounds.getNorthEast().lng();

		// Put the sizer at center, right on the circle.
		var position = new google.maps.LatLng(this.get('center').lat(), lng);
		this.set('sizer_position', position);
		DWCircle.setOptions(DWCircleOptionsEdit);
	}
};


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//	Calculates the distance between two latlng points in km.
//	@see http://www.movable-type.co.uk/scripts/latlong.html
//	
//	@param {google.maps.LatLng} p1 The first lat lng point.
//	@param {google.maps.LatLng} p2 The second lat lng point.
//	@return {number} The distance between the two points in km.
//	@private
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
RadiusWidget.prototype.distanceBetweenPoints_ = function(p1, p2) 
{
	if (!p1 || !p2) 
	{
	  return 0;
	}

	var R = 6371; // Radius of the Earth in km
	var dLat = (p2.lat() - p1.lat()) * Math.PI / 180;
	var dLon = (p2.lng() - p1.lng()) * Math.PI / 180;
	var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
	  Math.cos(p1.lat() * Math.PI / 180) * Math.cos(p2.lat() * Math.PI / 180) *
	  Math.sin(dLon / 2) * Math.sin(dLon / 2);
	var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
	var d = R * c;
	return d;
};


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//	Set the distance of the circle based on the position of the sizer.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
RadiusWidget.prototype.setDistance = function() 
{
	// As the sizer is being dragged, its position changes.  Because the
	// RadiusWidget's sizer_position is bound to the sizer's position, it will
	// change as well.
	var pos = this.get('sizer_position');
	var center = this.get('center');
	var distance = this.distanceBetweenPoints_(center, pos);
	this.set('distance_absolute', distance); // if the user drags too far
	
	if (KilometersToMiles(distance) > 250) // capped at 250 miles
	{
		distance = MilesToKilometers(250);
	}
	// Set the distance property for any objects that are bound to it
	this.set('distance', distance);
	DWCircle.setOptions(DWCircleOptionsEdit);
	if (DistanceDiv == null)
	{
		DistanceDiv = new DistanceOverlay();
	}
	if (DistanceDiv.get('div') != null)
	{
		DistanceDiv.get('div').innerHTML = "" + Math.round(KilometersToMiles(distance)*100)/100 + " mi";
	}
};




var distanceWidget = null; // public
var DistanceDiv = null; // public

function InitializeRadiusWidget(MapObj, GLatLngCenter, RadiusMiles, strokeColor, strokeWeight, strokeOpacity, fillColor, fillOpacity, opts) 
{
	if (distanceWidget != null)
	{
		distanceWidget.Remove();
	}
	distanceWidget = new DistanceWidget(MapObj, GLatLngCenter, RadiusMiles, strokeColor, strokeWeight, strokeOpacity, fillColor, fillOpacity, opts);
	DWCircle.setOptions(DWCircleOptions);
//	google.maps.event.addListener(distanceWidget, 'distance_changed', function() {
//	  displayInfo(distanceWidget);
//	});

//	google.maps.event.addListener(distanceWidget, 'position_changed', function() {
//	  displayInfo(distanceWidget);
//	});
	
	
		
	return distanceWidget.get('bounds');
}

var override_DistanceWidgetGetAllData = false;

function displayInfo(widget) 
{
	//var info = document.getElementById('info');
	var point = widget.get('position');
	//alert(point);
	var lat = Math.round(point.lat() * 1000000000000) / 1000000000000;
	var lng = Math.round(point.lng() * 1000000000000) / 1000000000000;
	var distance = parseFloat(widget.get('distance'));
	var dis = Math.round(KilometersToMiles(distance) * 100) / 100;
	var seo = String.Format("/{0}-{1}-{2}-radius", lat, lng, dis);
	
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//	Strip any previous radius and add to new query
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	var NewQuery = CacheObject.SEOQuery;
		NewQuery = NewQuery.replace(/\/[0-9\-\.]+radius/g,'');
		NewQuery += seo;
	DWCircle.setOptions(DWCircleOptions);
	if (DistanceDiv != null)
	{
		DistanceDiv.setMap(null);
		DistanceDiv = null;
	}
	//alert(NewQuery);
	var url = "/reno/Locations/GetRadiusSearch.aspx?SEOQuery={0}&Center={1},{2}";
		url = String.Format(url, escape(NewQuery), lat, lng);
		$.get(url, function(data)
		{
			if (data.indexOf("Error:") > -1)
			{
				alert(data);
			}
			else
			{
				//alert(data);
				if (override_DistanceWidgetGetAllData == true)
				{
					ReloadListByMap(trim(data));
				}
				else // only return seoquery
				{
					ReloadListByMap(trim(data).split('|')[0]);
				}
			}
		});
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//	Overlay to display distance to the user
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function DistanceOverlay() 
{
  // We define a property to hold the image's
  // div. We'll actually create this div
  // upon receipt of the add() method so we'll
  // leave it null for now.
  this.div_ = null;

  this.set('div', this.div_);
  
  // Explicitly call setMap() on this overlay
  this.setMap(Map);
}

DistanceOverlay.prototype = new google.maps.OverlayView();

DistanceOverlay.prototype.onAdd = function() 
{
	// Note: an overlay's receipt of onAdd() indicates that
	// the map's panes are now available for attaching
	// the overlay to the map via the DOM.

	// Create the DIV and set some basic attributes.
	var div = document.createElement('DIV');
	div.style.border = "1px solid #000";
	div.style.position = "absolute";
	div.style.backgroundColor = "#ffffff";
	div.style.padding = "3px 8px 3px 8px";
	div.style.font = "bold 12px arial,sans-serif";
	div.style.color = "#000000";
	div.style.width = "55px";
	// Set the overlay's div_ property to this DIV
	this.div_ = div;
	this.set('div', div);
	// We add an overlay to a map via one of the map's panes.
	// We'll add this overlay to the overlayImage pane.
	var panes = this.getPanes();
	panes.floatPane.appendChild(div);
};

DistanceOverlay.prototype.draw = function() 
{
  // position the overlay. 
  // We need to retrieve the projection from this overlay to do this.
  var overlayProjection = this.getProjection();

  // get coords for overlay
  var position = overlayProjection.fromLatLngToDivPixel(distanceWidget.get('position'));

	if (position != null)
	{
		// position the div
		this.div_.style.left = (position.x - 35) + 'px';
		this.div_.style.top = (position.y - 18) + 'px';
	}
};

DistanceOverlay.prototype.onRemove = function() 
{
  this.div_.parentNode.removeChild(this.div_);
  this.div_ = null;
};

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//	Radius Search Helper Control
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

var SearchHelperControlAdded = false;

function DrawRadiusSearchHelperControl(map)
{
	if (SearchHelperControlAdded)
	{
		return;
	}
	// Create div for Control
	var controlDiv = document.createElement('DIV');
		controlDiv.style.display = "inline";
		
	// Set CSS for the control border
	var controlUI = document.createElement('DIV');
	controlUI.style.display = "block";
	controlUI.style.backgroundColor = 'white';
	controlUI.style.borderStyle = 'solid';
	controlUI.style.borderWidth = '1px';
	controlUI.style.borderColor = '#777';
	controlUI.style.cursor = 'pointer';
	controlUI.style.width = '100px';
	controlUI.className = 'round opacity-80';
	controlDiv.appendChild(controlUI);

	// Set CSS for the control interior
	var controlText = document.createElement('DIV');
	controlText.style.display = "block";
	controlText.style.fontFamily = 'Arial,sans-serif';
	controlText.style.fontSize = '10px';
	controlText.style.lineHeight = '12px';
	controlText.style.padding = '6px';
	controlText.innerHTML = 'Move or resize radius by handles';
	controlUI.appendChild(controlText);

	// Set CSS styles for the DIV containing the control
	// Setting padding to 5 px will offset the control
	// from the edge of the map
	controlDiv.style.padding = '5px';
	controlDiv.index = 1;
	map.controls[google.maps.ControlPosition.TOP_LEFT].push(controlDiv);
	SearchHelperControlAdded = true;
	
}
