/**
 * Throttle a function call.
 *
 * It delays `callback` by `delay` ms and ignores any
 * repeated calls from `caller` within at most `maxWait`
 * milliseconds.
 *
 * Used to react to server events in cases where we get
 * a separate notification for each row of a bulk update.
 */
function throttle (callback, caller, delay = 100, maxWait = 500) {

  const schedule = async () => {
    caller.triggeredAt = Date.now();
    caller.timer = setTimeout(async () => {
      await callback();
      caller.timer = null;
    }, delay);
  }

  if (!caller.timer) {
    schedule();
  } else {
    const elapsed = Date.now() - caller.triggeredAt;
    if (elapsed > maxWait) {
      cancelTimeout(caller.timer);
      schedule();
    }
  }

}

module.exports = throttle;
