const MAX_TIMEOUT = 300000

/*
 * Executes a callback with exponential backoff. The timer goes off at
 * 5, 20, 45, 90, ... seconds, up until 5 minutes.
 */
export default class Timeout {
  #counter = 0
  #timeout: ReturnType<typeof setTimeout> | null = null

  public clear(): void {
    if (this.#timeout) {
      clearTimeout(this.#timeout)
      this.#counter = 0
      this.#timeout = null
    }
  }

  public start(callback: () => unknown): void {
    if (this.#timeout) clearTimeout(this.#timeout)
    this.#timeout = this.#setup(callback)
  }

  #setup(callback: () => unknown): ReturnType<typeof setTimeout> {
    return setTimeout(
      () => {
        callback()
        this.#counter++
        this.#timeout = this.#setup(callback)
      },
      Math.min(5000 * Math.pow(this.#counter + 1, 2), MAX_TIMEOUT)
    )
  }
}
