// Path: iterableapi/src/main/java/com/iterable/iterableapi/util/Future.java
// public class Future<T> {
//     private static final ExecutorService EXECUTOR = Executors.newCachedThreadPool();
// 
//     public static <T> Future<T> runAsync(Callable<T> callable) {
//         return new Future<>(callable);
//     }
// 
//     private Handler callbackHandler;
//     private final List<SuccessCallback<T>> successCallbacks = new ArrayList<>();
//     private final List<FailureCallback> failureCallbacks = new ArrayList<>();
// 
//     private Future(final Callable<T> callable) {
//         // Set up a Handler for the callback based on the current thread
//         Looper looper = Looper.myLooper();
//         if (looper == null) {
//             looper = Looper.getMainLooper();
//         }
//         callbackHandler = new Handler(looper);
// 
//         EXECUTOR.submit(new Runnable() {
//             @Override
//             public void run() {
//                 try {
//                     T result = callable.call();
//                     handleSuccess(result);
//                 } catch (Exception e) {
//                     handleFailure(e);
//                 }
//             }
//         });
//     }
// 
//     private void handleSuccess(final T result) {
//         callbackHandler.post(new Runnable() {
//             @Override
//             public void run() {
//                 List<SuccessCallback<T>> callbacks;
//                 synchronized (successCallbacks) {
//                     callbacks = new ArrayList<>(successCallbacks);
//                 }
//                 for (SuccessCallback<T> callback : callbacks) {
//                     if (callback != null) {
//                         callback.onSuccess(result);
//                     }
//                 }
//             }
//         });
//     }
// 
//     private void handleFailure(final Throwable t) {
//         callbackHandler.post(new Runnable() {
//             @Override
//             public void run() {
//                 List<FailureCallback> callbacks;
//                 synchronized (failureCallbacks) {
//                     callbacks = new ArrayList<>(failureCallbacks);
//                 }
//                 for (FailureCallback callback : callbacks) {
//                     if (callback != null) {
//                         callback.onFailure(t);
//                     }
//                 }
//             }
//         });
//     }
// 
//     public Future<T> onSuccess(SuccessCallback<T> successCallback) {
//         synchronized (successCallbacks) {
//             successCallbacks.add(successCallback);
//         }
//         return this;
//     }
// 
//     public Future<T> onFailure(FailureCallback failureCallback) {
//         synchronized (failureCallbacks) {
//             failureCallbacks.add(failureCallback);
//         }
//         return this;
//     }
// 
//     public interface SuccessCallback<T> {
//         void onSuccess(T result);
//     }
// 
//     public interface FailureCallback {
//         void onFailure(Throwable throwable);
//     }
// }


import android.util.Base64;
import androidx.annotation.VisibleForTesting;
import com.iterable.iterableapi.util.Future;
import org.json.JSONObject;
import java.io.UnsupportedEncodingException;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Callable;
            long triggerExpirationRefreshTime = expirationTimeSeconds * 1000L - expiringAuthTokenRefreshPeriod - IterableUtil.currentTimeMillis();
            if (triggerExpirationRefreshTime > 0) {
                scheduleAuthTokenRefresh(triggerExpirationRefreshTime);
            } else {
                IterableLogger.w(TAG, "The expiringAuthTokenRefreshPeriod has already passed for the current JWT");
            }
        } catch (Exception e) {
            IterableLogger.e(TAG, "Error while parsing JWT for the expiration", e);
        }
    }

    void resetFailedAuth() {
        hasFailedPriorAuth = false;
    }

    void reSyncAuth() {
        if (requiresAuthRefresh) {
            requiresAuthRefresh = false;
            requestNewAuthToken(false);
        }
    }

    private void scheduleAuthTokenRefresh(long timeDuration) {
        timer = new Timer(true);
        try {
            timer.schedule(new TimerTask() {
                @Override
                public void run() {
                    api.getAuthManager().requestNewAuthToken(false);
                }
// Path: iterableapi/src/main/java/com/iterable/iterableapi/util/Future.java
// public class Future<T> {
//     private static final ExecutorService EXECUTOR = Executors.newCachedThreadPool();
// 
//     public static <T> Future<T> runAsync(Callable<T> callable) {
//         return new Future<>(callable);
//     }
// 
//     private Handler callbackHandler;
//     private final List<SuccessCallback<T>> successCallbacks = new ArrayList<>();
//     private final List<FailureCallback> failureCallbacks = new ArrayList<>();
// 
//     private Future(final Callable<T> callable) {
//         // Set up a Handler for the callback based on the current thread
//         Looper looper = Looper.myLooper();
//         if (looper == null) {
//             looper = Looper.getMainLooper();
//         }
//         callbackHandler = new Handler(looper);
// 
//         EXECUTOR.submit(new Runnable() {
//             @Override
//             public void run() {
//                 try {
//                     T result = callable.call();
//                     handleSuccess(result);
//                 } catch (Exception e) {
//                     handleFailure(e);
//                 }
//             }
//         });
//     }
// 
//     private void handleSuccess(final T result) {
//         callbackHandler.post(new Runnable() {
//             @Override
//             public void run() {
//                 List<SuccessCallback<T>> callbacks;
//                 synchronized (successCallbacks) {
//                     callbacks = new ArrayList<>(successCallbacks);
//                 }
//                 for (SuccessCallback<T> callback : callbacks) {
//                     if (callback != null) {
//                         callback.onSuccess(result);
//                     }
//                 }
//             }
//         });
//     }
// 
//     private void handleFailure(final Throwable t) {
//         callbackHandler.post(new Runnable() {
//             @Override
//             public void run() {
//                 List<FailureCallback> callbacks;
//                 synchronized (failureCallbacks) {
//                     callbacks = new ArrayList<>(failureCallbacks);
//                 }
//                 for (FailureCallback callback : callbacks) {
//                     if (callback != null) {
//                         callback.onFailure(t);
//                     }
//                 }
//             }
//         });
//     }
// 
//     public Future<T> onSuccess(SuccessCallback<T> successCallback) {
//         synchronized (successCallbacks) {
//             successCallbacks.add(successCallback);
//         }
//         return this;
//     }
// 
//     public Future<T> onFailure(FailureCallback failureCallback) {
//         synchronized (failureCallbacks) {
//             failureCallbacks.add(failureCallback);
//         }
//         return this;
//     }
// 
//     public interface SuccessCallback<T> {
//         void onSuccess(T result);
//     }
// 
//     public interface FailureCallback {
//         void onFailure(Throwable throwable);
//     }
// }


// Path: iterableapi/src/main/java/com/iterable/iterableapi/IterableAuthManager.java
import android.util.Base64;
import androidx.annotation.VisibleForTesting;
import com.iterable.iterableapi.util.Future;
import org.json.JSONObject;
import java.io.UnsupportedEncodingException;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Callable;

            long triggerExpirationRefreshTime = expirationTimeSeconds * 1000L - expiringAuthTokenRefreshPeriod - IterableUtil.currentTimeMillis();
            if (triggerExpirationRefreshTime > 0) {
                scheduleAuthTokenRefresh(triggerExpirationRefreshTime);
            } else {
                IterableLogger.w(TAG, "The expiringAuthTokenRefreshPeriod has already passed for the current JWT");
            }
        } catch (Exception e) {
            IterableLogger.e(TAG, "Error while parsing JWT for the expiration", e);
        }
    }

    void resetFailedAuth() {
        hasFailedPriorAuth = false;
    }

    void reSyncAuth() {
        if (requiresAuthRefresh) {
            requiresAuthRefresh = false;
            requestNewAuthToken(false);
        }
    }

    private void scheduleAuthTokenRefresh(long timeDuration) {
        timer = new Timer(true);
        try {
            timer.schedule(new TimerTask() {
                @Override
                public void run() {
                    api.getAuthManager().requestNewAuthToken(false);
                }
            }, timeDuration);