/* There are two relevant javascript classes in this file: Circle, and CircleBoundaryMarker.
 * 
 * Circle represents the primary ground overlay and keeps track of the residence coordinate,
 * the radius being used, and the boundaries of the overlay. As per Google API restrictions,
 * it cannot be dragged.
 * 
 * CircleBoundaryMarker is a class that creates a draggable marker that is similar in
 * appearance to the circle overlay. It can be dragged.
 * 
 * These two classes must interact with each other:
 *  - when a Circle's radius changes, the CircleBoundaryMarker's size must change
 *  - when a CircleBoundaryMarker gets dragged, the centerpoint of the Circle must change
 * 
 */

var Circle = Class.create();
Circle.prototype = {
	initialize: function( privacyCenter, residenceCenter, radius ){
		this.center = privacyCenter;
		this.residence = residenceCenter; 
		this.radius = radius; // in kilometers
		this.overlay = null; // the google overlay that will contain the circle graphic
		this.boundaries = null; // the boundaries that will bound the overlay
		this.dragMarker = null; // the ghost circle that can be dragged

		this.setBoundaries(); // initialize the boundaries.
		this.drawOverlay(); // draw the overlay.
		this.dragMarker = new CircleBoundaryMarker(this);
		return this;
	},
	setBoundaries: function(){
		//debug("Setting boundaries...");
		//debug("Using radius of " + this.radiusInMeters() + " meters...");
		
		var sw = new GLatLng(
			this.center.pointFromOriginal( this.radius, 180).lat(), // due south latitude
			this.center.pointFromOriginal( this.radius, 270).lng() // due west longitude
		);
			
		var ne = new GLatLng(
			this.center.pointFromOriginal( this.radius, 0).lat(), // due north latitude
			this.center.pointFromOriginal( this.radius, 90).lng() // due east longitude
		);
		this.boundaries = new GLatLngBounds( sw, ne );
	},
	drawOverlay: function(){
		if( this.overlay ){ map.removeOverlay( this.overlay ); }
		this.overlay = new GGroundOverlay("/images/circle_overlay.png", this.boundaries);
		map.addOverlay( this.overlay );
	},
	changeRadius: function(radius){
		if (this.radius == radius){ return; }
		map.removeOverlay( this.dragMarker.marker);
		//this.dragMarker.marker.hide();
		this.radius = radius; // in kilometers
		this.setBoundaries();
		this.drawOverlay();
		this.dragMarker = new CircleBoundaryMarker(this);
	},
	radiusInMeters: function(){
		return this.radius * 1000;
	},
	diameterInMeters: function(){
		var sw = this.boundaries.getSouthWest();
		var ne = this.boundaries.getNorthEast();
		var topMiddle = new GLatLng( ne.lat(), (ne.lng()-(ne.lng()-sw.lng())/2) );
		var bottomMiddle = new GLatLng( sw.lat(), topMiddle.lng() );
		
		// If you want to draw the diameter line...
		// var diameterLine = new GPolyline([topMiddle,bottomMiddle]);
		// console.log("The diameter line is "+diameterLine.getLength()+" meters long.");
		// map.addOverlay(diameterLine);
		return bottomMiddle.distanceFrom( topMiddle );
	},
	diameterInMiles: function(){
		return metersToMiles(this.diameterInMeters());
	},
	areaInMeters: function(){
		var radius = this.diameterInMeters() / 2;
		var rsquared = Math.pow( radius, 2 );
		return (Math.PI * rsquared);
	}
}

var CircleBoundaryMarker = Class.create();
CircleBoundaryMarker.prototype = {
	initialize: function(circle){
		this.circle = circle;
		this.centerPoint = circle.center;
		this.icon = this.initializeIcon();
		this.marker = this.initializeMarker();
		this.distanceFromResidence = 0;
		GEvent.addListener(map, 'zoomend', function(){
			//debug(' Zoom Level Changed');
			circle.dragMarker.redraw();
		})

	},
	initializeIcon: function(){
		var size = 341;
		
		try {
			size = $$('img[src=/images/circle_overlay.png]')[0].getWidth();
		} catch(error){
			// We could create a matrix of zoomlevels and radiuses... 
			//switch(this.circle.radius){
			//	case 0.8: size = 454; break;
			//}
			//size = 341;
		}
		//debug("The draggable marker should get resized to "+size);
		icon = new GIcon();
		icon.image = '/images/circle_overlay.png';
		icon.iconSize = new GSize(size, size);
		icon.iconAnchor = new GPoint(size/2,size/2);
		return icon;
	},
	initializeMarker: function(){
		try{$('mtgt_boundary_marker').remove();} catch(e){}
		marker = new GMarker(this.centerPoint, {
			icon: this.icon, draggable: true, bouncy: false, autoPan: false, id:'boundary_marker'
		})
		
		GEvent.addListener(marker, "dragstart", function(){
			circle.overlay.hide();
		});
		GEvent.addListener(marker, "dragend", function(latlng){
			circle.dragMarker.centerPoint = latlng;
			circle.center = latlng;
			circle.setBoundaries();
			circle.drawOverlay();
			map.panTo( latlng );
			//debug("Boundary center is now "+circle.center);
			//debug("Residence is still "+circle.residence);
			if( this.distanceFromResidence > circle.radiusInMeters() ){
				circle.center = circle.residence;
				circle.setBoundaries();
				circle.drawOverlay();
				circle.dragMarker.redraw();
				map.panTo( circle.residence );
			}
			// Update regardless of validity
			
			try {
				updatePrivacyCenter(circle.center);
			} catch(error){
				
			}
		});
		GEvent.addListener(marker, "drag", function(latlng){
			this.distanceFromResidence = latlng.distanceFrom( circle.residence );
			if( this.distanceFromResidence > circle.radiusInMeters() ) {
				marker.setImage('/images/circle_overlay_red.png')
			} else {
				marker.setImage('/images/circle_overlay.png')
			}
		});
		map.addOverlay( marker );
		return marker;
	},
	redraw: function(){
		this.centerPoint = circle.center;
		//debug("Redrawing draggable marker...");
		this.icon = this.initializeIcon();
		map.removeOverlay( this.marker );
		this.marker = this.initializeMarker();
	}

}