var progressSpinner = function(cvs, ctx, ldr, img_url, callback) {
  var TICK_RATE    = 30;

  var canvas       = cvs,
      context      = ctx,
      loader       = ldr,
      image        = new Image(),
      active       = false,
      complete     = false,
      preComplete  = false,
      curAngle     = 0,
      targetAngle  = 0,
      ticksToDest  = 0,
      completeCallback = callback,
      imgX, imgY, ctrX, ctrY;

  var preLoadComplete = function() {
    imgX = (canvas.width  - image.width ) / 2;
    imgY = (canvas.height - image.height) / 2;
    ctrX = image.width  / 2;
    ctrY = image.height / 2;

    ldr.startLoading(finished, resetTicks);
    resetTicks();
    active = true;
  }

  var tick = function() {
    if(!active || complete) { return; }

    if(ticksToDest > 0) {
      curAngle += (targetAngle - curAngle) / ticksToDest;
      ticksToDest -= 1;
    } else {
      if(preComplete) {
        complete = true;
      }
      curAngle = targetAngle;
    }
  };

  var resetTicks = function() {
    ticksToDest = TICK_RATE;
    targetAngle = 2 * Math.PI * loader.loadCount() / loader.toBeLoaded();
  };

  var finished = function() {
    preComplete = true;
    resetTicks();
    if(completeCallback) {
      completeCallback();
    }
  };

  var draw = function() {
    context.save();
    context.translate(imgX + ctrX, imgY + ctrY);
    context.rotate(curAngle);
    context.translate(-ctrX, -ctrY);
    context.drawImage(image, 0, 0);
    context.restore();
  };

  var setAngle = function(newAngle, newTicks) {
    targetAngle = newAngle;
    ticksToDest = newTicks;
  };

  image.src    = img_url;
  image.onload = preLoadComplete;

  return {
    complete: function() { return complete; },
    setAngle: setAngle,
    draw:     draw,
    tick:     tick
  };
}

