



















/**
 * Schedule a repeating task, with the specified gap between runs.
 */
export function makePeriodicTask(
  task,
  msGap,
  opts = {}
) {
  const { onError = () => {} } = opts

  // A started task will keep bouncing between running & waiting.
  // The `running` flag will be true in the running state,
  // and `timeout` will have a value in the waiting state.
  let running = false
  let timeout

  function startRunning() {
    timeout = undefined
    if (!out.started) return
    running = true
    new Promise(resolve => resolve(task()))
      .catch(onError)
      .then(resumeWaiting, resumeWaiting)
  }

  function startWaiting(nextGap) {
    running = false
    if (!out.started) return
    timeout = setTimeout(startRunning, nextGap)
  }

  function resumeWaiting() {
    startWaiting(msGap)
  }

  const out = {
    started: false,

    setDelay(milliseconds) {
      msGap = milliseconds
    },

    start(opts = {}) {
      const { wait } = opts
      out.started = true
      if (!running && timeout == null) {
        if (typeof wait === 'number') startWaiting(wait)
        else if (wait === true) startWaiting(msGap)
        else startRunning()
      }
    },

    stop() {
      out.started = false
      if (timeout != null) {
        clearTimeout(timeout)
        timeout = undefined
      }
    }
  }
  return out
}
