package com.workfusion.odf;

public class Retry {

  public static interface CallToRetry<T> {
    <T> T doIt() throws Exception;
  }
  
  public static <T> T withRetry(int maxTimes, long initialWait, int waitMultiplier, CallToRetry<T> callToRetry) throws Exception {
    if(maxTimes <= 0) {
      throw new IllegalArgumentException("Must run at least one time");
    }
    if(initialWait <= 0) {
      throw new IllegalArgumentException("Initial wait must be at least 1");
    }
    if(waitMultiplier <= 0) {
      throw new IllegalArgumentException("Wait multiplier must be at least 1");
    }
    if(callToRetry == null) {
      throw new IllegalArgumentException("No call to retry provided");
    }
    Exception thrown = null;
    for(int i = 0; i < maxTimes; i++) {
      try {
        return callToRetry.doIt();
      } catch(Exception e) {
        System.out.println("Failed with " + e.getMessage() + ". Retrying");
        thrown = e;
      }
      try {
        Thread.sleep(initialWait + (waitMultiplier * i));
      } catch(InterruptedException wakeAndAbort){
        break;
      }
    }
    if(thrown == null) {
      throw new IllegalStateException("Failure calling " + callToRetry + ", but no thrown exception found!");
    }
    throw thrown;
  }
  
}