var map;
var dotIcon;

dotIcon = new GIcon();
dotIcon.image = 'dot-icon.gif';
dotIcon.shadow = '';
dotIcon.iconSize = new GSize(10,10);
dotIcon.shadowSize = new GSize(0, 0);
dotIcon.iconAnchor = new GPoint(5, 5);
dotIcon.infoWindowAnchor = new GPoint(5, 5);

/* the GOverlay */
function YoLabelLabel(yoLabel) 
{
	this.yoLabel = yoLabel;
}
YoLabelLabel.prototype = new GOverlay();

YoLabelLabel.prototype.initialize = function(map) 
{
	var div = document.createElement('div');
	div.yoLabel = this.yoLabel;

	div.innerHTML = "hello, i'm a label";

	div.style.border = '2px solid #666';
	div.style.backgroundColor = '#fff';
	div.style.width = '8em'; 
	div.style.height = '3em'; 
	div.style.padding = '3px';

	map.getPane(G_MAP_MARKER_PANE).appendChild(div);

	this.element = div;
}

YoLabelLabel.prototype.remove = function() 
{
	this.element.parentNode.removeChild(this.element);
}

YoLabelLabel.prototype.copy = function() 
{
	return new YoLabelLabel(this.yoLabel);
}

YoLabelLabel.prototype.redraw = function(force) 
{
	if (!force) return;

	var topLeft = this.yoLabel.getLabelTopLeftDivPixel();
	this.draggable = new GDraggableObject(this.element, {left:topLeft.x, top:topLeft.y});
	this.draggable.yoLabel = this.yoLabel;
	GEvent.addListener(this.draggable, 'drag', markerDrag);
	this.yoLabel.redrawArrow();
}
function getPoint(rotation, rel, r, theta)
{
	var x = rel.x + r * Math.cos(rotation + theta);
	var y = rel.y + r * Math.sin(rotation + theta);
	return new GPoint(x, y);
}

YoLabel.prototype.getLabelTopLeftDivPixel = function()
{
	var origin = map.fromLatLngToDivPixel(this.marker.getPoint());
	var x = origin.x + this.labelOffset.x - this.label.element.clientWidth / 2;
	var y = origin.y + this.labelOffset.y - this.label.element.clientHeight / 2;
	return new GPoint(x, y);
}

YoLabel.prototype.getLabelCenterLatLng = function()
{
	var origin = map.fromLatLngToDivPixel(this.marker.getPoint());
	var x = origin.x + this.labelOffset.x;
	var y = origin.y + this.labelOffset.y;
	return map.fromDivPixelToLatLng(new GPoint(x, y));

}

function YoLabel()
{
}

YoLabel.prototype.redrawArrow = function()
{
	if (this.arrowPolyline)
		map.removeOverlay(this.arrowPolyline);

	var projection = map.getCurrentMapType().getProjection();
	var fromPoint = projection.fromLatLngToPixel(this.getLabelCenterLatLng(), map.getZoom());
	var toPoint = projection.fromLatLngToPixel(this.marker.getPoint(), map.getZoom());

	var rotation = Math.atan2(toPoint.y - fromPoint.y, toPoint.x - fromPoint.x);

	var arrowPoints = [];
	var arrowDim1 = 3;
	var arrowDim2 = 16;

	with (Math)
	{
		arrowPoints.push(getPoint(rotation, fromPoint, arrowDim1, PI/2));
		arrowPoints.push(getPoint(rotation, toPoint, sqrt(arrowDim1*arrowDim1 + arrowDim2*arrowDim2), PI - atan2(arrowDim1,arrowDim2)));
		arrowPoints.push(getPoint(rotation, toPoint, sqrt(arrowDim2*arrowDim2 + arrowDim2*arrowDim2), 3*PI/4));
		arrowPoints.push(getPoint(rotation, toPoint, 0, 0));
		arrowPoints.push(getPoint(rotation, toPoint, sqrt(arrowDim2*arrowDim2 + arrowDim2*arrowDim2), -3*PI/4));
		arrowPoints.push(getPoint(rotation, toPoint, sqrt(arrowDim1*arrowDim1 + arrowDim2*arrowDim2), -PI + atan2(arrowDim1,arrowDim2)));
		arrowPoints.push(getPoint(rotation, fromPoint, arrowDim1, -PI/2));
		arrowPoints.push(getPoint(rotation, fromPoint, arrowDim1, PI/2));
	}

	var arrowLatLngs = [];
	for (var i = 0; i < arrowPoints.length; i++)
		arrowLatLngs[i] = projection.fromPixelToLatLng(arrowPoints[i], map.getZoom());

	this.arrowPolyline = new GPolyline(arrowLatLngs, '#ff0033', 12, 0.90);
	map.addOverlay(this.arrowPolyline);
}

function markerDrag()
{
	this.yoLabel.recalcLabelOffset();
	this.yoLabel.redrawArrow();
}

YoLabel.prototype.recalcLabelOffset = function()
{
	var origin = map.fromLatLngToDivPixel(this.marker.getPoint());

	var x = this.label.draggable.left + this.label.element.clientWidth / 2;
	var y = this.label.draggable.top  + this.label.element.clientHeight / 2;

	this.labelOffset = new GPoint(x - origin.x, y - origin.y);
}

/*
 * YoLabel
 * {
 *   GMarker marker;
 *   YoLabelLabel label;
 *   GPoint labelOffset;
 * }
 */
function addLabel(point)
{
	var yoLabel = new YoLabel();

	yoLabel.label = new YoLabelLabel(yoLabel);
	yoLabel.labelOffset = new GPoint(-100,-60);
	yoLabel.marker = new GMarker(point, {icon:dotIcon,draggable:true});
	yoLabel.marker.yoLabel = yoLabel;
	GEvent.addListener(yoLabel.marker, 'drag', markerDrag);

	yoLabel.redrawArrow();
	map.addOverlay(yoLabel.marker);
	map.addOverlay(yoLabel.label);
}

function mapClick(overlay, point)
{
	if (point && !overlay)
		addLabel(point);
}

function load() 
{
	if (GBrowserIsCompatible()) 
	{
		map = new GMap2(document.getElementById('map'));
		map.addControl(new GLargeMapControl());
		map.addControl(new GMapTypeControl());
		map.setCenter(new GLatLng(42.425314,-83.100892), 19);
		map.setMapType(G_HYBRID_MAP);

		GEvent.addListener(map, 'click', mapClick);
	}
}

