import random


def calc_next_exponential_backoff_delay(
    current_delay_secs,
    backoff_factor,
    max_delay_secs,
    with_jitter=False
):
    """Calculate the delay (in seconds) before next retry based on
    current delay using exponential backoff, with optional jitter.

    See http://www.awsarchitectureblog.com/2015/03/backoff.html for
    information about exponential backoff and jitter.

    Args:
        current_delay_secs (float): current backoff delay in seconds.
        backoff_factor (int): the constant used for exponential backoff.
        max_delay_secs (float): maximum backoff delay in seconds.
        with_jitter(Optional[bool]): whether to use jitter.  Default to False.

    Returns (float):
        Next backoff delay in seconds.
    """
    next_delay_secs = min(
        max_delay_secs,
        current_delay_secs * backoff_factor
    )
    if with_jitter:
        next_delay_secs = random.uniform(0, next_delay_secs)
    return next_delay_secs