class RandomJitter implements Jitter {

	@Override
	public Duration apply(BackoffDelay backoff) {
		//check the invariant
		if (backoff.delay.compareTo(backoff.min) < 0) {
			throw InvalidArgumentException.fromMessage("jitter can only be applied on a delay that is >= to min backoff");
		}
		if (backoff.delay.compareTo(backoff.max) > 0) {
			throw InvalidArgumentException.fromMessage("jitter can only be applied on a delay that is <= to max backoff");
		}

		//short-circuit delay == 0 case
		if (backoff.delay.isZero()) {
			return backoff.delay;
		}

		ThreadLocalRandom random = ThreadLocalRandom.current();

		long jitterOffset = jitterOffsetCapped(backoff);
		long lowBound = lowJitterBound(backoff, jitterOffset);
		long highBound = highJitterBound(backoff, jitterOffset);

		long jitter;
		if (highBound == lowBound) {
			if (highBound == 0) jitter = 0;
			else jitter = random.nextLong(highBound);
		}
		else {
			jitter = random.nextLong(lowBound, highBound);
		}
		return backoff.delay.plusMillis(jitter);
	}

	public  RandomJitter(double randomFactor);

}