// browser-type detection
var isW3C = false;
var isMSIE = false;
if (document.getElementById && !document.all)
  isW3C = true;
else if (document.all)
  isMSIE = true;

// globals that should be set by the calling code before initialization
var imageWidth, imageHeight;
var spatialAspectRatio;

// globals that are constant after initialization
var imageObj, boxObj;
var imageLeft, imageTop, imageRight, imageBottom;

// globals that vary for every drag operation
var startX = 0, startY = 0;
var clickInProgress = false, isAreaSelected = false;
var boxLeft, boxTop, boxRight, boxBottom;

function initRubberBandZoom() {
  if (!isW3C && !isMSIE) return;

  imageObj = document.getElementById("mapImage1");
  boxObj = document.getElementById("rubberBandBox");

  // determine the size and location of the map image on the page
  imageLeft = 0;
  imageTop = 0;
  var obj = imageObj;
  while (obj != null) {
    imageLeft += obj.offsetLeft;
    imageTop += obj.offsetTop;
    obj = obj.offsetParent;
  }

  // this tweak seems to be necessary (on most browsers?)
  // for an unknown reason
  imageLeft += 2;
  imageTop += 2;

  imageRight = (imageLeft + imageWidth) - 1;
  imageBottom = (imageTop + imageHeight) - 1;

  boxObj.style.visibility = "hidden";

  document.onmousedown = handleMouseDown;
  document.onmouseup = handleMouseUp;
}

function handleMouseDown(e) {
  if (!e) var e = window.event;
  if (e.button == 2) return true;

  // only trigger on the map image
  var target;
  if (e.target) target = e.target;
  else target = e.srcElement;
  if (target.nodeType == 3) // defeat Safari bug
    target = target.parentNode;
  if (target != document.forms[0].mapImage1) return true;

  var coords = findCoords(e);

  if (coords[0] < imageLeft || coords[1] < imageTop ||
        coords[0] > imageRight || coords[1] > imageBottom)
    return true;

  startX = coords[0];
  startY = coords[1];

  boxObj.style.width = 0;
  boxObj.style.height = 0;
  if (isW3C) {
    boxObj.style.left = startX;
    boxObj.style.top = startY;
  }
  else {
    boxObj.style.pixelLeft = startX + 1;
    boxObj.style.pixelTop  = startY + 1;
  }

  boxObj.style.visibility = "hidden";
  isAreaSelected = false;
  clickInProgress = true;

  var clickMode = getClickMode();
  if (clickMode == 0 || clickMode == 1)
    document.onmousemove = handleMouseDrag;

  return false;
}

function handleMouseDrag(e) {
  if (!e) var e = window.event;
  if (e.button == 2) return true;

  var currentX, currentY;
  var coords = findCoords(e);
  currentX = coords[0];
  currentY = coords[1];

  if (currentX > startX) {
    boxLeft = startX;
    boxRight = currentX;
  }
  else {
    boxLeft = currentX;
    boxRight = startX;
  }

  if (currentY > startY) {
    boxTop = startY;
    boxBottom = currentY;
  }
  else {
    boxTop = currentY;
    boxBottom = startY;
  }

  var forceAspectRatio = false; // set to true to force the aspect ratio

  // correct aspect ratio
  if (forceAspectRatio) correctAspectRatio(currentX, currentY);

  // shrink box to window
  if (boxRight > imageRight) boxRight = imageRight;
  if (boxLeft < imageLeft) boxLeft = imageLeft;
  if (boxTop < imageTop) boxTop = imageTop;
  if (boxBottom > imageBottom) boxBottom = imageBottom;

  // correct aspect ratio again
  if (forceAspectRatio) correctAspectRatio(currentX, currentY);

  if (isW3C) {
    boxObj.style.left = boxLeft;
    boxObj.style.top = boxTop;
    boxObj.style.width = (boxRight - boxLeft) - 1;
    boxObj.style.height = (boxBottom - boxTop) - 1;
  }
  else {
    boxObj.style.pixelLeft = boxLeft;
    boxObj.style.pixelTop = boxTop;
    boxObj.style.width = (boxRight - boxLeft) + 1;
    boxObj.style.height = (boxBottom - boxTop) + 1;
  }

  // adjust relative to the location of the image
  boxLeft -= imageLeft;
  boxTop -= imageTop;
  boxRight -= imageLeft;
  boxBottom -= imageTop;

  // require a certain size before starting to draw the box
  if (!isAreaSelected && boxRight-boxLeft > 3 && boxBottom-boxTop > 3) {
    boxObj.style.visibility = "visible";
    isAreaSelected = true;
  }

  return false;
}

function correctAspectRatio(currentX, currentY) {
  if ((boxRight-boxLeft)/(boxBottom-boxTop) < spatialAspectRatio) {
    if (currentX > startX) {
      boxRight = ((boxBottom-boxTop) * spatialAspectRatio) + boxLeft;
      boxRight = Math.round(boxRight);
    }
    else {
      boxLeft = boxRight - ((boxBottom-boxTop) * spatialAspectRatio);
      boxLeft = Math.round(boxLeft);
    }
  }
  else {
    if (currentY > startY) {
      boxBottom = ((boxRight-boxLeft) / spatialAspectRatio) + boxTop;
      boxBottom = Math.round(boxBottom);
    }
    else {
      boxTop = boxBottom - ((boxRight-boxLeft) / spatialAspectRatio);
      boxTop = Math.round(boxTop);
    }
  }
}

function handleMouseUp(e) {
  if (!clickInProgress) return true;

  if (!e) var e = window.event;
  if (e.button == 2) return true;

  var clickMode, actionName;

  clickMode = getClickMode();

  if (clickMode == 0)
    actionName = "zoomIn";
  else if (clickMode == 1)
    actionName = "zoomOut";
  else if (clickMode == 2)
    actionName = "recenter";
  else
    actionName = "query";

  if (isAreaSelected) {
    var selectionRatioX = ((boxRight-boxLeft)+1) / imageWidth;
    var selectionRatioY = ((boxBottom-boxTop)+1) / imageHeight;
    var selectionRatio = Math.max(selectionRatioX, selectionRatioY);
    submitMapAction(actionName, (boxLeft+boxRight)/2.0,
                    (boxTop+boxBottom)/2.0, selectionRatio);
    isAreaSelected = false;
  }
  else {
    var coords = findCoords(e);
    if (coords[0] < imageLeft || coords[1] < imageTop ||
        coords[0] > imageRight || coords[1] > imageBottom)
      return true;

    clickX = coords[0] - imageLeft;
    clickY = coords[1] - imageTop;
    submitMapAction(actionName, clickX, clickY, 0);
  }

  clickInProgress = false;
  boxObj.style.visibility = "hidden";
  document.onmousemove = null;
  return false;
}

function handleKeyPress(e) {
  if (isAreaSelected) {
    // cancel mouse drag
    boxObj.style.visibility = "hidden";
    isAreaSelected = false;
    clickInProgress = false;
    document.onmousemove = null;
    return false;
  }
  else {
    // Enter/Return should submit the form
    if (!e) var e = window.event;
    if (e.keyCode == 13)
      submitAction("showMainPage");
    else
      return true;
  }
}

function getClickMode() {
  var clickModeObj, index;

  clickModeObj = document.forms[0].clickMode;
  for (index=0; index<clickModeObj.length; index++) {
    if (clickModeObj[index].checked)
      return index;
  }

  return 2; // recenter by default
}

function findCoords(e) {
  if (e.pageX)
    return [e.pageX, e.pageY];
  else if (e.clientX)
    return [e.clientX + document.body.scrollLeft - 2,
            e.clientY + document.body.scrollTop - 2];
  else return [0, 0];
}

function submitMapAction(actionName, actionPointX, actionPointY, boxRatio) {
  var form = document.forms[0];
  form.action.value = actionName;
  form.actionPointX.value = actionPointX;
  form.actionPointY.value = actionPointY;
  form.boxRatio.value = boxRatio;
  form.submit();
}
