package waiter

import (
	
	
	

	
)

// ComputeDelay computes delay between waiter attempts. The function takes in a current attempt count,
// minimum delay, maximum delay, and remaining wait time for waiter as input. The inputs minDelay and maxDelay
// must always be greater than 0, along with minDelay lesser than or equal to maxDelay.
//
// Returns the computed delay and if next attempt count is possible within the given input time constraints.
// Note that the zeroth attempt results in no delay.
func ( int64, , ,  time.Duration) ( time.Duration,  error) {
	// zeroth attempt, no delay
	if  <= 0 {
		return 0, nil
	}

	// remainingTime is zero or less, no delay
	if  <= 0 {
		return 0, nil
	}

	// validate min delay is greater than 0
	if  == 0 {
		return 0, fmt.Errorf("minDelay must be greater than zero when computing Delay")
	}

	// validate max delay is greater than 0
	if  == 0 {
		return 0, fmt.Errorf("maxDelay must be greater than zero when computing Delay")
	}

	// Get attempt ceiling to prevent integer overflow.
	 := (math.Log(float64(/)) / math.Log(2)) + 1

	if  > int64() {
		 = 
	} else {
		// Compute exponential delay based on attempt.
		 := 1 << uint64(-1)
		// compute delay
		 =  * time.Duration()
	}

	if  !=  {
		// randomize to get jitter between min delay and delay value
		,  := rand.CryptoRandInt63n(int64( - ))
		if  != nil {
			return 0, fmt.Errorf("error computing retry jitter, %w", )
		}

		 = time.Duration() + 
	}

	// check if this is the last attempt possible and compute delay accordingly
	if - <=  {
		 =  - 
	}

	return , nil
}