// Copyright (c) 2008-2009 FlexiGuided GmbH, Berlin

function getAbsoluteLeft(elem) {
  var result = 0;
  while (elem) {
    result += elem.offsetLeft;
    elem = elem.offsetParent;
  }
  return result;
}
function getAbsoluteTop(elem) {
  var result = 0;
  while (elem) {
    result += elem.offsetTop;
    elem = elem.offsetParent;
  }
  return result;
}

// mechanisch
//phyMass       = 0.12;
//phyFriction   = 0.8;
//phySpring     = 25.0;
//phyTime       = 0.4;

// aggressiv
//phyMass       = 0.10;
//phyFriction   = 0.75;
//phySpring     = 25.0;
//phyTime       = 0.25;

// langsam
//phyMass       = 0.20;
//phyFriction   = 1.5;
//phySpring     = 30.0;
//phyTime       = 0.5;

// abgestimmt
//phyMass       = 0.05;
//phyFriction   = 1.0;
//phySpring     = 30.0;
//phyTime       = 0.20;

// schwingungsfrei
phyMass       = 1;
phyFriction   = 30.0;
phySpring     = 250.0;
phyTime       = 0.1;

phyFrameRate  = 25;
phyCalcCycles = 4;

phyResolution = phyFrameRate * phyCalcCycles
allPhySprings = [];

function PhySpring() {
  this.active         = false;
  this.position       = 0;
  this.impulse        = 0;
  this.anchorPosition = 0;
  this.targetPosition = 0;
  this.changed = function() {};
  allPhySprings[allPhySprings.length] = this;
}

springIntervalLate = 0;

window.setInterval(
  function(late) {
    if (allPhySprings.length == 0) return;
    var cycles = phyCalcCycles;
    if (late) {
      springIntervalLate += late;
      while (springIntervalLate > (1000 / phyResolution)) {
        springIntervalLate -= 1000 / phyResolution;
        cycles += phyCalcCycles;
      }
    }
    var springIndex;
    for (springIndex=0; springIndex<allPhySprings.length; springIndex++) {
      var spring = allPhySprings[springIndex];
      if (spring.anchorPosition != spring.targetPosition) {
        spring.active = true;
      }
      if (spring.active) {
        var cycle;
        for (cycle = 0; cycle < cycles; cycle++) {
          if (spring.targetPosition > spring.anchorPosition) {
            spring.anchorPosition += (1 / phyTime) / phyResolution;
            if (spring.anchorPosition > spring.targetPosition) {
              spring.anchorPosition = spring.targetPosition;
            }
          } else if (spring.targetPosition < spring.anchorPosition) {
            spring.anchorPosition -= (1 / phyTime) / phyResolution;
            if (spring.anchorPosition < spring.targetPosition) {
              spring.anchorPosition = spring.targetPosition;
            }
          }
          spring.position += spring.impulse / phyResolution;
          spring.impulse  -= (
            phyFriction/phyMass * spring.impulse +
            phySpring/phyMass * (spring.position - spring.anchorPosition)
          ) / phyResolution;
        }
        if (
          spring.anchorPosition == spring.targetPosition &&
          Math.abs(spring.position - spring.anchorPosition) < 0.0001 &&
          Math.abs(spring.impulse) / phyMass < 0.001
        ) {
          spring.position = spring.anchorPosition;
          spring.impulse  = 0;
          spring.active   = false;
        }
        spring.changed();
      }
    }
  },
  1000 / phyFrameRate
)

function dynamicZoom(image, options) {
  var execOnLoad = function(callback) {
    if (window.addEventListener) {
      window.addEventListener("load", callback, false);
    } else if (window.attachEvent) {
      window.attachEvent("onload", callback);
    }
  };
  execOnLoad(function() {
    var spring = new PhySpring();
    var was_active = false;
    var absLeft;
    var absTop;
    var initialWidth  = image.clientWidth;
    var initialHeight = image.clientHeight;
    if (image.parentNode.tagName == "DIV") {
      image.parentNode.style.width  = initialWidth;
      image.parentNode.style.height = initialHeight;
    }
    image.onmouseover = function() { spring.targetPosition = 1; }
    image.onmouseout  = function() { spring.targetPosition = 0; }
    spring.changed = function() {
      var is_active = spring.active || (spring.targetPosition != 0);
      if (is_active && !was_active) {
        was_active = true;
        absLeft = getAbsoluteLeft(image);
        absTop  = getAbsoluteTop(image);
        image.style.position = "absolute";
        image.style.left = absLeft;
        image.style.top  = absTop;
        image.style.border = '1px solid #777777';
      } else if (was_active && !is_active) {
        was_active = false;
        image.style.position = "static";
        image.style.left = null;
        image.style.top  = null;
        image.style.border = '1px solid #ffffff';
      }
      if (is_active) {
        var position;
        if (spring.position > -1) position = spring.position;
        else position = -1;
        var newWidth = initialWidth * (
          1 + (options.factor - 1) * position
        );
        var newHeight = initialHeight * (
          1 + (options.factor - 1) * position
        );
        var newLeft;
        var newTop;
        if (options.left != undefined && options.right == undefined) {
          newLeft = absLeft - position * options.left;
        } else if (
          options.right != undefined && options.left == undefined
        ) {
          newLeft =
            absLeft + initialWidth - newWidth + position * options.right;
        } else {
          newLeft = absLeft - (newWidth - initialWidth) / 2;
        }
        if (options.top != undefined && options.bottom == undefined) {
          newTop = absTop - position * options.top;
        } else if (
          options.bottom != undefined && options.top == undefined
        ) {
          newTop =
            absTop + initialHeight - newHeight + position * options.bottom;
        } else {
          newTop = absTop - (newHeight - initialHeight) / 2;
        }
        var newRight  = newLeft + newWidth;
        var newBottom = newTop  + newHeight;
        newLeft   = Math.round(newLeft);
        newTop    = Math.round(newTop);
        newRight  = Math.round(newRight);
        newBottom = Math.round(newBottom);
        newWidth  = newRight  - newLeft;
        newHeight = newBottom - newTop;
        image.style.left = newLeft;
        image.style.top  = newTop;
        if (newWidth > 0) image.style.width = newWidth;
        else image.style.width = 0;
        if (newHeight > 0) image.style.height = newHeight;
        else image.style.height = 0;
      }
    }
  });
}
