package de.braintags.vertx.util.async;

import java.util.concurrent.Callable;
import java.util.function.Function;

import io.vertx.core.Future;
import io.vertx.core.Vertx;

/**
 * Retries an execution for number of times if it fails
 * 
 * @author mpluecker
 *
 */
public class RetryingFuture<F extends Future<?>> extends SharedFutureImpl<F> {

  private final Callable<F> execution;
  private int currentTry = -1;
  private final Vertx vertx;
  private final Function<Integer, Integer> retryDelayMs;
  private final Function<Integer, Boolean> retryDecider;

  /**
   * 
   * @param retryDelayMs
   *          function from retry to delay - first retry is called with 0
   */
  public RetryingFuture(final Vertx vertx, final Callable<F> execution, final Function<Integer, Boolean> retryDecider,
      final Function<Integer, Integer> retryDelayMs) {
    this.vertx = vertx;
    this.execution = execution;
    this.retryDecider = retryDecider;
    this.retryDelayMs = retryDelayMs;
    execute();
  }

  private void execute() {
    try {
      currentTry++;
      F current = execution.call();
      current.setHandler(res -> {
        if (res.succeeded()) {
          complete(current);
        } else {
          retry(res.cause());
        }
      });
    } catch (Exception e) {
      fail(e);
    }
  }

  private void retry(final Throwable cause) {
    if (retryDecider.apply(currentTry)) {
      vertx.setTimer(retryDelayMs.apply(currentTry), timerId -> execute());
    } else {
      fail(cause);
    }
  }
  
  
}

@@ -586,16 +586,203 @@
 *%0D%0A   * 
+@param retryDecider%0D%0A   *          Function that decides if another retry is made. The function is called with the current number of retries%0D%0A   *          (first retry is called with 0).
 %0D%0A   * @
@@ -815,17 +815,17 @@
         
-f
+F
 unction 
@@ -847,25 +847,98 @@
 elay
- - first retry is
+. The function is called with the current number of retries (first retry is%0D%0A   *         
  cal
@@ -947,16 +947,18 @@
 d with 0
+).
 %0D%0A   */%0D

improve comment