function getRelPos(e, gmap) {
	var pos = getMousePosition(e);
	var mapPosition = getElementPosition(gmap.getContainer());
	return {
		top : (pos.top - mapPosition.top),
		left : (pos.left - mapPosition.left)
	};
}

function getLatLng(e, gmap) {
	var relPos = getRelPos(e, gmap);
	var point = new GPoint(relPos.left, relPos.top);
	return gmap.fromContainerPixelToLatLng(point);
}

function drawCircle(center, radiusKm, numPoints) {
	var poly = [];
	var lat = center.lat();
	var lng = center.lng();
	var clat = (radiusKm / 6371) * 180 / Math.PI;
	var clng = clat / Math.cos(lat * Math.PI / 180);

	for ( var i = 0; i < numPoints; i++) {
		var theta = Math.PI * (i / (numPoints / 2));
		Cx = lng + (clng * Math.cos(theta));
		Cy = lat + (clat * Math.sin(theta));
		poly.push(new GLatLng(Cy, Cx));
	}

	poly.push(poly[0]);

	return new GPolyline(poly, '#FF0000', 3, 0.8);
}

function drawGeofence(center, radiusM) {
	return drawCircle(center, radiusM / 1000, 50);
}

var geofenceOverlays = [];

function drawGeofenceOverlay(index, center, radiusM) {
	var overlay = drawGeofence(center, radiusM);
	gmap.addOverlay(overlay);
	geofenceOverlays[index] = overlay;
	return overlay;
}

function removeGeofenceOverlay(index) {
	if( !geofenceOverlays[index] ) {
		return ;
	}
	gmap.removeOverlay(geofenceOverlays[index]);
	geofenceOverlays[index] = null;
}

var cancelGeofenceDrawingFn = nop;

var mapCover = false;
var center = false;
var circle = false;

function initGeofence(gmap, circleCallback, minRadiusM) {
	if (mapCover) {
		return mapCover;
	}

	minRadiusM = minRadiusM || 100;

	mapCover = document.createElement("div");
	mapCover.onselectstart = function() {
		return false;
	};
	style(mapCover, {
		position : 'absolute',
		display : 'block',
		overflow : 'hidden',
		cursor : 'crosshair',
		zIndex : 101,
		background : '#000',
		opacity : 0,
		filter : 'alpha(opacity=0)'
	});

	var mapSize = gmap.getSize();
	var mapWidth = mapSize.width;
	var mapHeight = mapSize.height;
	var mapRatio = mapHeight / mapWidth;

	style(mapCover, {
		top : '0px',
		left : '0px',
		width : mapWidth + 'px',
		height : mapHeight + 'px'
	});

	GEvent.addDomListener(mapCover, 'mousedown', function(e) {
		center = getLatLng(e, gmap);
	});
	GEvent.addDomListener(document, 'mousemove', function(e) {
		if (!center) {
			return;
		}
		if (circle) {
			gmap.removeOverlay(circle);
		}
		var outerLineLatLng = getLatLng(e, gmap);
		var radiusM = center.distanceFrom(outerLineLatLng);
		circle = drawGeofence(center, radiusM);
		gmap.addOverlay(circle);
	});
	GEvent.addDomListener(document, 'mouseup', function(e) {
		if (!center) {
			return;
		}
		if (circle) {
			gmap.removeOverlay(circle);
		}
		var persistCenter = center;
		center = false;
		circle = false;
		var outerLineLatLng = getLatLng(e, gmap);
		var radiusM = persistCenter.distanceFrom(outerLineLatLng);
		radiusM = radiusM < minRadiusM ? minRadiusM : radiusM;
		var overlay = drawGeofence(persistCenter, radiusM);
		gmap.addOverlay(overlay);
		circleCallback(persistCenter, radiusM, overlay);
	});

	return mapCover;
}

function createGeofence(gmap, circleCallback, minRadiusM) {
	cancelGeofenceDrawingFn = function() {
		if (circle) {
			gmap.removeOverlay(circle);
		}
		center = false;
		circle = false;
		cancelGeofenceDrawingFn = nop;
		circleCallback(false, false, false);
	};

	gmap.getContainer().appendChild(
			initGeofence(gmap, circleCallback, minRadiusM));

	return mapCover;
}
