/**
 * Creates a timer that accepts a `timerCalc` function to perform calculated timeout retries, such as exponential backoff.
 *
 * @example
 *    let reconnectTimer = new Timer(() => this.connect(), function(tries){
 *      return [1000, 5000, 10000][tries - 1] || 10000
 *    })
 *    reconnectTimer.scheduleTimeout() // fires after 1000
 *    reconnectTimer.scheduleTimeout() // fires after 5000
 *    reconnectTimer.reset()
 *    reconnectTimer.scheduleTimeout() // fires after 1000
 */
export default class Timer {
  timer: number | undefined = undefined
  tries: number = 0

  constructor(
    public callback: Function,
    public timerCalc: Function
  ) {
    this.callback = callback
    this.timerCalc = timerCalc
  }

  reset() {
    this.tries = 0
    clearTimeout(this.timer)
    this.timer = undefined
  }

  // Cancels any previous scheduleTimeout and schedules callback
  scheduleTimeout() {
    clearTimeout(this.timer)

    this.timer = <any>setTimeout(
      () => {
        this.tries = this.tries + 1
        this.callback()
      },
      this.timerCalc(this.tries + 1)
    )
  }
}
