package flaky

import (
	
	
)

// BackoffProvider provides a potentially stateful backoff function for
// executing an operation.
type BackoffProvider interface {
	Backoff() Backoff
}

// Backoff is a function that, given the current count of retries, returns
// backoff delay before the next attempt, or false if an executor should stop
// with the last error.
type Backoff func(n uint) (time.Duration, bool)

// Backoff implements the BackoffProvider interface.
func ( Backoff) () Backoff {
	return 
}

// Limit limits the number of retries for the given backoff. That is, it stops
// the backoff once retries counter reaches the given limit. Passing a limit of
// zero retries is equivalent to no backoff.
func ( uint,  Backoff) Backoff {
	return func( uint) (time.Duration, bool) {
		if  >=  {
			return 0, false
		}
		return ()
	}
}

// Constant returns a constant backoff that uses nth duration for the arguments.
// It returns the last element if the attempt count is greater than the number
// of arguments. Passing no arguments is equivalent to no backoff.
func ( ...time.Duration) Backoff {
	return func( uint) (time.Duration, bool) {
		 := uint(len())
		if 0 ==  {
			return 0, false
		}
		if  >=  {
			return [-1], true
		}
		return [], true
	}
}

// Exp2 returns an exponential backoff that returns base-2 exponential of
// failed attempts count times the given duration unit.
//
// Note that the backoff stops after wait duration reaches max positive value of
// time.Duration or once n is equal to math.MaxUint.
func ( time.Duration) Backoff {
	return func( uint) (time.Duration, bool) {
		if  == math.MaxUint {
			return 0, false
		}
		 :=  << ( + 1)
		if  <= 0 {
			return 0, false
		}
		return , true
	}
}