var l1 = 10;
var l2 = 10;
var k = 0.1;
var g = 0.0002;
var m = 1;

var x0 = 0, y0 = 0;
var x1 = l1/Math.sqrt(2), y1 = l1/Math.sqrt(2);
var vx1 = 0, vy1 = 0;
var x2 = x1, y2 = y1 + l2;
var vx2 = 0.01, vy2 = 0;
var mousePos = {x : 0, y : 0};

var rad = l1/8;
var time = 0;

var width = 140.0;
var height = 140.0;
var l2p = height / (2.5*(l1+l2));
var origin = {x : width/2, y : height/2};
var inside = false;

var lastMouseOver;
var sleeping = false;


function getTime() {
    return new Date().getTime();
}

function registerTimeout() {
  setTimeout('loop()', 30);
}

// finds the position of an html element in a page. attempts to be cross-platform.
function findPosition(obj) {
    var curleft = 0;
    var curtop = 0;
    if(obj.offsetParent) {
        while(1) {
          curleft += obj.offsetLeft;
          curtop += obj.offsetTop;
          if(!obj.offsetParent)
            break;
          obj = obj.offsetParent;
        }
    }
    else if(obj.x) {
        curleft += obj.x;
        curtop += obj.y;
    }
    return {x : curleft, y : curtop};
}
  
// gets the mouse coordinates relative to the page. attempts to be cross platform.
function getMouseCoords(evt) {
    if (evt.pageX)
        return {x : evt.pageX, y : evt.pageY};
    else if (evt.clientX)
       return { x : evt.clientX + (document.documentElement.scrollLeft ?
                    document.documentElement.scrollLeft :
                    document.body.scrollLeft),
                y : evt.clientX + (document.documentElement.scrollTop ?
                    document.documentElement.scrollTop :
                    document.body.scrollTop) };
    else return null;
}

function handleMouseMove(event) {
    var canvas = document.getElementById('simCanvas');
    cpos = findPosition(canvas);
    mpos = getMouseCoords(event);
    mousePos.x = (mpos.x - cpos.x - origin.x) / l2p;
    mousePos.y = (mpos.y - cpos.y - origin.y) / l2p;

    lastMouseOver = getTime();
    if (sleeping) {
        sleeping = false;
        registerTimeout();
    }
}

function handleMouseOver(event) {
  inside = true;
}

function handleMouseOut(event) {
  inside = false;
}

function accumulateInternalForces(dt) {
    var dx1 = x1 - x0;
    var dy1 = y1 - y0;
    var dx2 = x2 - x1;
    var dy2 = y2 - y1;
    var dl1 = Math.sqrt(dx1*dx1 + dy1*dy1);
    var dl2 = Math.sqrt(dx2*dx2 + dy2*dy2);
    
    var a1 = (k/m) * (l1 - dl1);
    var a2 = (k/m) * (l2 - dl2);

    vx1 += dt * ((dx1/dl1) * a1 - (dx2/dl2) * a2);
    vy1 += dt * ((dy1/dl1) * a1 - (dy2/dl2) * a2 + g);
    vx2 += dt * ((dx2/dl2) * a2);
    vy2 += dt * ((dy2/dl2) * a2 + g);
}

function accumulateMouseForces(dt) {
    var dx1 = x1 - mousePos.x;
    var dy1 = y1 - mousePos.y;
    var dx2 = x2 - mousePos.x;
    var dy2 = y2 - mousePos.y;
    var d1 = Math.sqrt(dx1*dx1 + dy1*dy1);
    var d2 = Math.sqrt(dx2*dx2 + dy2*dy2);
    
    var a1 = (g/m) * (l1+l2) / Math.max(d1,(l1+l2)/4);
    var a2 = (g/m) * (l1+l2) / Math.max(d2,(l1+l2)/4);

    vx1 += dt * (dx1/d1) * a1;
    vy1 += dt * (dy1/d1) * a1;
    vx2 += dt * (dx2/d2) * a2;
    vy2 += dt * (dy2/d2) * a2;
}

function accumulateDragForces(dt) {
    var gamma1 = 0.0;
    var gamma2 = 0.001;
    v1 = Math.sqrt(vx1*vx1 + vy1*vy1);
    v2 = Math.sqrt(vx2*vx2 + vy2*vy2);
    vx1 -= dt * (vx1/v1) * (v1 * gamma1 + v1*v1 * gamma2);
    vy1 -= dt * (vy1/v1) * (v1 * gamma1 + v1*v1 * gamma2);
    vx2 -= dt * (vx2/v2) * (v2 * gamma1 + v2*v2 * gamma2);
    vy2 -= dt * (vy2/v2) * (v2 * gamma1 + v2*v2 * gamma2);
}

function updatePositions() {
    var delta_time = getTime() - time;
    time = time + delta_time;
    delta_time = Math.min(delta_time, 100);
    
    var i;
    var loops = 50;
    var dt = delta_time / loops;
    for (i = 0; i < loops; i++) {
        accumulateInternalForces(dt);
        accumulateDragForces(dt);
        if (inside) {
            accumulateMouseForces(dt);
        }
        x1 += dt*vx1;
        y1 += dt*vy1;
        x2 += dt*vx2;
        y2 += dt*vy2;
    }
}

function drawPendulum() {
  var canvas = document.getElementById('simCanvas');
  var ctx = canvas.getContext('2d');
  ctx.clearRect(0, 0, width, height);
  
//  if (inside) {
//     ctx.lineWidth = 4;
//     ctx.strokeStyle = "#C0C0FF";
//     ctx.strokeRect(0, 0, width, height);
//  }
  
  ctx.save();
  ctx.translate(origin.x, origin.y);
  
  ctx.fillStyle = "#606060";
  ctx.fillRect(-l2p*rad/2, -l2p*rad/2, l2p*rad, l2p*rad);
  
  ctx.lineWidth = 2;  
  ctx.strokeStyle = "#6060A0";
  ctx.beginPath();
  ctx.moveTo(l2p*x0, l2p*y0);
  ctx.lineTo(l2p*x1, l2p*y1);
  ctx.lineTo(l2p*x2, l2p*y2);
  ctx.stroke();

  if (inside)
    ctx.fillStyle = "#E04000";
  else  
    ctx.fillStyle = "#40E000";
  ctx.beginPath();
  ctx.arc(l2p*x1, l2p*y1, l2p*rad, 0, 2*Math.PI, 0);
  ctx.arc(l2p*x2, l2p*y2, l2p*rad, 0, 2*Math.PI, 0);
  ctx.fill();
  
  ctx.restore();
}

function mainLoop() {
  var canvas = document.getElementById('simCanvas');
  canvas.onmousemove = handleMouseMove;
  canvas.onmouseover = handleMouseOver;
  canvas.onmouseout = handleMouseOut;

  lastMouseOver = getTime();
  loop();
}

function loop() {
  updatePositions();
  drawPendulum();

  var deltaSeconds = (getTime() - lastMouseOver)/1000.;
  sleeping = deltaSeconds > 120;
  if (!sleeping) {
    registerTimeout();
  }
}
