var mapx1, mapx2, mapy1, mapy2, maparea;
var zoomx1, zoomy1, zoomx2, zoomx2, zoomarea;
var mapwidth, mapheight;
var mousex, mousey;
var zoomLayer;
var startTracking = false;
var gpstart, gpend;
var multiplier;

var ZOOMAREA_KEYCODE = 90; // 'z' key zooms an area when the mouse is moved (not dragged).

var zoomLevelAreas = new Array(
 0.000044782205316291115,
 0.00017912880077214252,
 0.0007165152014842625,
 0.0028660594751396392,
 0.01146422704873143,
 0.04585681809304249,
 0.18342716717851734,
 0.7337069855714002,
 2.9348010091822907,
 11.738430973389503,
 46.94408531995497,
 187.64344725577126,
 748.5823131256056,
 2961.473356669126,
 11242.849261491675,
 36095.54334444813,
 86649.85238489839,
 177134.48041308092
);

function getObjectTop(refobj) {
 var y = refobj.offsetTop;
 var obj = refobj.offsetParent;
  while (obj != null) {
    y += obj.offsetTop;
    obj = obj.offsetParent;
  }
 return y;
}

function getObjectLeft(refobj) {
 var x = refobj.offsetLeft;
 var obj = refobj.offsetParent;
  while (obj != null) {
    x += obj.offsetLeft;
    obj = obj.offsetParent;
  }
 return x;
}

function xInBounds(x) {
 if ((x < mapx2) && (x > mapx1))
  return true;
 return false;
}

function yInBounds(y) {
 if ((y < mapy2) && (y > mapy1))
  return true;
 return false;
}

//simple method to get next zoomlevel
//could be made smarter - binary search with closest match?
function getNextZoomLevel(maparea) {
 var i = 0;
 while (zoomLevelAreas[i] < maparea)
  i++;
  
 return i;
}

function getLatLonFromPixel(x, y) {
 var origin =  map.getCurrentMapType().getBitmapCoordinate(map.getBoundsLatLng().maxY, map.getBoundsLatLng().minX, map.getZoomLevel());
 return map.getCurrentMapType().getLatLng(origin.x + x, origin.y + y, map.getZoomLevel()); 
}

function setValidZoomArea(e) {
 mousex = e.clientX;
 mousey = e.clientY;

 if (mousex > mapx2) mousex = mapx2; 
 if (mousex < mapx1) mousex = mapx1;
 if (mousey < mapy1) mousey = mapy1;
 if (mousey > mapy2) mousey = mapy2;
}

function mouseMoveHandler(e){
 if (!e) e = window.event;

 mousex = e.clientX;
 mousey = e.clientY;

 setValidZoomArea(e)

 if (!startTracking)
  return;

 w = parseFloat(mousex) - parseFloat(zoomx1);
 h = parseFloat(mousey) - parseFloat(zoomy1);
 
 if (w < 0) {
  w = Math.abs(w);
  zoomLayer.style.left = mousex;
 }  
 zoomLayer.style.width = w;

 if (h < 0) {
  h = Math.abs(h);
  zoomLayer.style.top = mousey;
 }
 zoomLayer.style.height = h;
}

function keyDownHandler(e)
{
	if (!e) var e = window.event;

	if ((startTracking == false) && (e.shiftKey) &&(e.keyCode == ZOOMAREA_KEYCODE))
	{
		zoomx1 = mousex;
		zoomy1 = mousey;

		if ((xInBounds(zoomx1)) && (yInBounds(zoomy1)))
		{
			startTracking = true;
			gpstart = getLatLonFromPixel(zoomx1 - mapx1, zoomy1 - mapy1); 
 
			zoomLayer.style.visibility = "visible";
			zoomLayer.style.left = zoomx1;
			zoomLayer.style.top = zoomy1;
			zoomLayer.style.width = 0;
			zoomLayer.style.height = 0;
			document.body.style.cursor = "crosshair";
		}
	}
}

function keyUpHandler(e){
 startTracking = false;
 if (!e) e = window.event;
 if (e.keyCode != ZOOMAREA_KEYCODE)
  return;
  
 if(typeof(gpstart) == 'undefined')
  return;
 
 zoomLayer.style.visibility = "hidden";
 document.body.style.cursor = "default";
 zoomx2 = mousex;
 zoomy2 = mousey;
 gpend = getLatLonFromPixel(mousex - mapx1, mousey - mapy1); 
 zoomarea = Math.abs((gpend.x - gpstart.x) * (gpend.y - gpstart.y));
 
 if (zoomarea == 0)
  return;
 
 centerx = ((gpend.x + gpstart.x)/2);
 centery = ((gpend.y + gpstart.y)/2);
 
 var zoomLevel = getNextZoomLevel(zoomarea);
 
 if (zoomLevel < 0)
  zoomLevel = 0;
 map.centerAndZoom(new GPoint(centerx, centery), zoomLevel);
}

function initCoords() {
 var mapElement = document.getElementById("map");
 zoomLayer = document.getElementById("ZoomLayer");
 zoomLayer.style.visibility = "hidden";
 mapx1 = getObjectLeft(mapElement);
 mapy1 = getObjectTop(mapElement);
 mapwidth = parseFloat(mapElement.style.width);
 mapheight = parseFloat(mapElement.style.height);
 mapx2 = mapx1 + mapwidth;
 mapy2 = mapy1 + mapheight;
 maparea = mapwidth * mapheight;
}

document.onmousemove = mouseMoveHandler;
document.onkeydown = keyDownHandler;
document.onkeyup = keyUpHandler;

initCoords(); 

