/*
 * Copyright (C) 2006 The Guava Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */

package com.google.common.util.concurrent;

import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Function;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * A {@link ListenableFuture} that supports fluent chains of operations. For example:
 *
 * <pre>{@code
 * ListenableFuture<Boolean> adminIsLoggedIn =
 *     FluentFuture.from(usersDatabase.getAdminUser())
 *         .transform(User::getId, directExecutor())
 *         .transform(ActivityService::isLoggedIn, threadPool)
 *         .catching(RpcException.class, e -> false, directExecutor());
 * }</pre>
 *
 * <h3>Alternatives</h3>
 *
 * <h4>Frameworks</h4>
 *
 * <p>When chaining together a graph of asynchronous operations, you will often find it easier to
 * use a framework. Frameworks automate the process, often adding features like monitoring,
 * debugging, and cancellation. Examples of frameworks include:
 *
 * <ul>
 *   <li><a href="http://google.github.io/dagger/producers.html">Dagger Producers</a>
 * </ul>
 *
 * <h4>{@link java.util.concurrent.CompletableFuture} / {@link java.util.concurrent.CompletionStage}
 * </h4>
 *
 * <p>Users of {@code CompletableFuture} will likely want to continue using {@code
 * CompletableFuture}. {@code FluentFuture} is targeted at people who use {@code ListenableFuture},
 * who can't use Java 8, or who want an API more focused than {@code CompletableFuture}. (If you
 * need to adapt between {@code CompletableFuture} and {@code ListenableFuture}, consider <a
 * href="https://github.com/lukas-krecan/future-converter">Future Converter</a>.)
 *
 * <h3>Extension</h3>
 *
 * If you want a class like {@code FluentFuture} but with extra methods, we recommend declaring your
 * own subclass of {@link ListenableFuture}, complete with a method like {@link #from} to adapt an
 * existing {@code ListenableFuture}, implemented atop a {@link ForwardingListenableFuture} that
 * forwards to that future and adds the desired methods.
 *
 * @since 23.0
 */
@Beta
@GwtCompatible(emulated = true)
public abstract class FluentFuture<V> extends GwtFluentFutureCatchingSpecialization<V> {

  /**
   * A less abstract subclass of AbstractFuture. This can be used to optimize setFuture by ensuring
   * that {@link #get} calls exactly the implementation of {@link AbstractFuture#get}.
   */
  abstract static class TrustedFuture<V> extends FluentFuture<V>
      implements AbstractFuture.Trusted<V> {
    @CanIgnoreReturnValue
    @Override
    public final V get() throws InterruptedException, ExecutionException {
      return super.get();
    }

    @CanIgnoreReturnValue
    @Override
    public final V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException {
      return super.get(timeout, unit);
    }

    @Override
    public final boolean isDone() {
      return super.isDone();
    }

    @Override
    public final boolean isCancelled() {
      return super.isCancelled();
    }

    @Override
    public final void addListener(Runnable listener, Executor executor) {
      super.addListener(listener, executor);
    }

    @CanIgnoreReturnValue
    @Override
    public final boolean cancel(boolean mayInterruptIfRunning) {
      return super.cancel(mayInterruptIfRunning);
    }
  }

  FluentFuture() {}

  /**
   * Converts the given {@code ListenableFuture} to an equivalent {@code FluentFuture}.
   *
   * <p>If the given {@code ListenableFuture} is already a {@code FluentFuture}, it is returned
   * directly. If not, it is wrapped in a {@code FluentFuture} that delegates all calls to the
   * original {@code ListenableFuture}.
   */
  public static <V> FluentFuture<V> from(ListenableFuture<V> future) {
    return future instanceof FluentFuture
        ? (FluentFuture<V>) future
        : new ForwardingFluentFuture<V>(future);
  }

  /**
   * Returns a {@code Future} whose result is taken from this {@code Future} or, if this {@code
   * Future} fails with the given {@code exceptionType}, from the result provided by the {@code
   * fallback}. {@link Function#apply} is not invoked until the primary input has failed, so if the
   * primary input succeeds, it is never invoked. If, during the invocation of {@code fallback}, an
   * exception is thrown, this exception is used as the result of the output {@code Future}.
   *
   * <p>Usage example:
   *
   * <pre>{@code
   * // Falling back to a zero counter in case an exception happens when processing the RPC to fetch
   * // counters.
   * ListenableFuture<Integer> faultTolerantFuture =
   *     fetchCounters().catching(FetchException.class, x -> 0, directExecutor());
   * }</pre>
   *
   * <p>When selecting an executor, note that {@code directExecutor} is dangerous in some cases. See
   * the discussion in the {@link #addListener} documentation. All its warnings about heavyweight
   * listeners are also applicable to heavyweight functions passed to this method.
   *
   * <p>This method is similar to {@link java.util.concurrent.CompletableFuture#exceptionally}. It
   * can also serve some of the use cases of {@link java.util.concurrent.CompletableFuture#handle}
   * and {@link java.util.concurrent.CompletableFuture#handleAsync} when used along with {@link
   * #transform}.
   *
   * @param exceptionType the exception type that triggers use of {@code fallback}. The exception
   *     type is matched against the input's exception. "The input's exception" means the cause of
   *     the {@link ExecutionException} thrown by {@code input.get()} or, if {@code get()} throws a
   *     different kind of exception, that exception itself. To avoid hiding bugs and other
   *     unrecoverable errors, callers should prefer more specific types, avoiding {@code
   *     Throwable.class} in particular.
   * @param fallback the {@link Function} to be called if the input fails with the expected
   *     exception type. The function's argument is the input's exception. "The input's exception"
   *     means the cause of the {@link ExecutionException} thrown by {@code this.get()} or, if
   *     {@code get()} throws a different kind of exception, that exception itself.
   * @param executor the executor that runs {@code fallback} if the input fails
   */
  @Partially.GwtIncompatible("AVAILABLE but requires exceptionType to be Throwable.class")
  public final <X extends Throwable> FluentFuture<V> catching(
      Class<X> exceptionType, Function<? super X, ? extends V> fallback, Executor executor) {
    return (FluentFuture<V>) Futures.catching(this, exceptionType, fallback, executor);
  }

  /**
   * Returns a {@code Future} whose result is taken from this {@code Future} or, if this {@code
   * Future} fails with the given {@code exceptionType}, from the result provided by the {@code
   * fallback}. {@link AsyncFunction#apply} is not invoked until the primary input has failed, so if
   * the primary input succeeds, it is never invoked. If, during the invocation of {@code fallback},
   * an exception is thrown, this exception is used as the result of the output {@code Future}.
   *
   * <p>Usage examples:
   *
   * <pre>{@code
   * // Falling back to a zero counter in case an exception happens when processing the RPC to fetch
   * // counters.
   * ListenableFuture<Integer> faultTolerantFuture =
   *     fetchCounters().catchingAsync(
   *         FetchException.class, x -> immediateFuture(0), directExecutor());
   * }</pre>
   *
   * <p>The fallback can also choose to propagate the original exception when desired:
   *
   * <pre>{@code
   * // Falling back to a zero counter only in case the exception was a
   * // TimeoutException.
   * ListenableFuture<Integer> faultTolerantFuture =
   *     fetchCounters().catchingAsync(
   *         FetchException.class,
   *         e -> {
   *           if (omitDataOnFetchFailure) {
   *             return immediateFuture(0);
   *           }
   *           throw e;
   *         },
   *         directExecutor());
   * }</pre>
   *
   * <p>When selecting an executor, note that {@code directExecutor} is dangerous in some cases. See
   * the discussion in the {@link #addListener} documentation. All its warnings about heavyweight
   * listeners are also applicable to heavyweight functions passed to this method. (Specifically,
   * {@code directExecutor} functions should avoid heavyweight operations inside {@code
   * AsyncFunction.apply}. Any heavyweight operations should occur in other threads responsible for
   * completing the returned {@code Future}.)
   *
   * <p>This method is similar to {@link java.util.concurrent.CompletableFuture#exceptionally}. It
   * can also serve some of the use cases of {@link java.util.concurrent.CompletableFuture#handle}
   * and {@link java.util.concurrent.CompletableFuture#handleAsync} when used along with {@link
   * #transform}.
   *
   * @param exceptionType the exception type that triggers use of {@code fallback}. The exception
   *     type is matched against the input's exception. "The input's exception" means the cause of
   *     the {@link ExecutionException} thrown by {@code this.get()} or, if {@code get()} throws a
   *     different kind of exception, that exception itself. To avoid hiding bugs and other
   *     unrecoverable errors, callers should prefer more specific types, avoiding {@code
   *     Throwable.class} in particular.
   * @param fallback the {@link AsyncFunction} to be called if the input fails with the expected
   *     exception type. The function's argument is the input's exception. "The input's exception"
   *     means the cause of the {@link ExecutionException} thrown by {@code input.get()} or, if
   *     {@code get()} throws a different kind of exception, that exception itself.
   * @param executor the executor that runs {@code fallback} if the input fails
   */
  @Partially.GwtIncompatible("AVAILABLE but requires exceptionType to be Throwable.class")
  public final <X extends Throwable> FluentFuture<V> catchingAsync(
      Class<X> exceptionType, AsyncFunction<? super X, ? extends V> fallback, Executor executor) {
    return (FluentFuture<V>) Futures.catchingAsync(this, exceptionType, fallback, executor);
  }

  /**
   * Returns a future that delegates to this future but will finish early (via a {@link
   * TimeoutException} wrapped in an {@link ExecutionException}) if the specified timeout expires.
   * If the timeout expires, not only will the output future finish, but also the input future
   * ({@code this}) will be cancelled and interrupted.
   *
   * @param timeout when to time out the future
   * @param unit the time unit of the time parameter
   * @param scheduledExecutor The executor service to enforce the timeout.
   */
  @GwtIncompatible // ScheduledExecutorService
  @SuppressWarnings("GoodTime") // should accept a java.time.Duration
  public final FluentFuture<V> withTimeout(
      long timeout, TimeUnit unit, ScheduledExecutorService scheduledExecutor) {
    return (FluentFuture<V>) Futures.withTimeout(this, timeout, unit, scheduledExecutor);
  }

  /**
   * Returns a new {@code Future} whose result is asynchronously derived from the result of this
   * {@code Future}. If the input {@code Future} fails, the returned {@code Future} fails with the
   * same exception (and the function is not invoked).
   *
   * <p>More precisely, the returned {@code Future} takes its result from a {@code Future} produced
   * by applying the given {@code AsyncFunction} to the result of the original {@code Future}.
   * Example usage:
   *
   * <pre>{@code
   * FluentFuture<RowKey> rowKeyFuture = FluentFuture.from(indexService.lookUp(query));
   * ListenableFuture<QueryResult> queryFuture =
   *     rowKeyFuture.transformAsync(dataService::readFuture, executor);
   * }</pre>
   *
   * <p>When selecting an executor, note that {@code directExecutor} is dangerous in some cases. See
   * the discussion in the {@link #addListener} documentation. All its warnings about heavyweight
   * listeners are also applicable to heavyweight functions passed to this method. (Specifically,
   * {@code directExecutor} functions should avoid heavyweight operations inside {@code
   * AsyncFunction.apply}. Any heavyweight operations should occur in other threads responsible for
   * completing the returned {@code Future}.)
   *
   * <p>The returned {@code Future} attempts to keep its cancellation state in sync with that of the
   * input future and that of the future returned by the chain function. That is, if the returned
   * {@code Future} is cancelled, it will attempt to cancel the other two, and if either of the
   * other two is cancelled, the returned {@code Future} will receive a callback in which it will
   * attempt to cancel itself.
   *
   * <p>This method is similar to {@link java.util.concurrent.CompletableFuture#thenCompose} and
   * {@link java.util.concurrent.CompletableFuture#thenComposeAsync}. It can also serve some of the
   * use cases of {@link java.util.concurrent.CompletableFuture#handle} and {@link
   * java.util.concurrent.CompletableFuture#handleAsync} when used along with {@link #catching}.
   *
   * @param function A function to transform the result of this future to the result of the output
   *     future
   * @param executor Executor to run the function in.
   * @return A future that holds result of the function (if the input succeeded) or the original
   *     input's failure (if not)
   */
  public final <T> FluentFuture<T> transformAsync(
      AsyncFunction<? super V, T> function, Executor executor) {
    return (FluentFuture<T>) Futures.transformAsync(this, function, executor);
  }

  /**
   * Returns a new {@code Future} whose result is derived from the result of this {@code Future}. If
   * this input {@code Future} fails, the returned {@code Future} fails with the same exception (and
   * the function is not invoked). Example usage:
   *
   * <pre>{@code
   * ListenableFuture<List<Row>> rowsFuture =
   *     queryFuture.transform(QueryResult::getRows, executor);
   * }</pre>
   *
   * <p>When selecting an executor, note that {@code directExecutor} is dangerous in some cases. See
   * the discussion in the {@link #addListener} documentation. All its warnings about heavyweight
   * listeners are also applicable to heavyweight functions passed to this method.
   *
   * <p>The returned {@code Future} attempts to keep its cancellation state in sync with that of the
   * input future. That is, if the returned {@code Future} is cancelled, it will attempt to cancel
   * the input, and if the input is cancelled, the returned {@code Future} will receive a callback
   * in which it will attempt to cancel itself.
   *
   * <p>An example use of this method is to convert a serializable object returned from an RPC into
   * a POJO.
   *
   * <p>This method is similar to {@link java.util.concurrent.CompletableFuture#thenApply} and
   * {@link java.util.concurrent.CompletableFuture#thenApplyAsync}. It can also serve some of the
   * use cases of {@link java.util.concurrent.CompletableFuture#handle} and {@link
   * java.util.concurrent.CompletableFuture#handleAsync} when used along with {@link #catching}.
   *
   * @param function A Function to transform the results of this future to the results of the
   *     returned future.
   * @param executor Executor to run the function in.
   * @return A future that holds result of the transformation.
   */
  public final <T> FluentFuture<T> transform(Function<? super V, T> function, Executor executor) {
    return (FluentFuture<T>) Futures.transform(this, function, executor);
  }

  /**
   * Registers separate success and failure callbacks to be run when this {@code Future}'s
   * computation is {@linkplain java.util.concurrent.Future#isDone() complete} or, if the
   * computation is already complete, immediately.
   *
   * <p>The callback is run on {@code executor}. There is no guaranteed ordering of execution of
   * callbacks, but any callback added through this method is guaranteed to be called once the
   * computation is complete.
   *
   * <p>Example:
   *
   * <pre>{@code
   * future.addCallback(
   *     new FutureCallback<QueryResult>() {
   *       public void onSuccess(QueryResult result) {
   *         storeInCache(result);
   *       }
   *       public void onFailure(Throwable t) {
   *         reportError(t);
   *       }
   *     }, executor);
   * }</pre>
   *
   * <p>When selecting an executor, note that {@code directExecutor} is dangerous in some cases. See
   * the discussion in the {@link #addListener} documentation. All its warnings about heavyweight
   * listeners are also applicable to heavyweight callbacks passed to this method.
   *
   * <p>For a more general interface to attach a completion listener, see {@link #addListener}.
   *
   * <p>This method is similar to {@link java.util.concurrent.CompletableFuture#whenComplete} and
   * {@link java.util.concurrent.CompletableFuture#whenCompleteAsync}. It also serves the use case
   * of {@link java.util.concurrent.CompletableFuture#thenAccept} and {@link
   * java.util.concurrent.CompletableFuture#thenAcceptAsync}.
   *
   * @param callback The callback to invoke when this {@code Future} is completed.
   * @param executor The executor to run {@code callback} when the future completes.
   */
  public final void addCallback(FutureCallback<? super V> callback, Executor executor) {
    Futures.addCallback(this, callback, executor);
  }
}
