/*
 * Copyright (C) 2014 Google, Inc.
 *
 * 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 dagger.producers.internal;

import com.google.common.base.Function;
import com.google.common.collect.ImmutableSet;
import com.google.common.util.concurrent.FutureFallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import dagger.producers.Produced;
import dagger.producers.Producer;
import java.util.Set;
import javax.inject.Provider;

import static com.google.common.base.Preconditions.checkNotNull;

/**
 * Utility methods for use in generated producer code.
 *
 * @author Jesse Beder
 * @since 2.0
 */
public final class Producers {
  /**
   * Returns a future of {@link Produced} that represents the completion (either success or failure)
   * of the given future. If the input future succeeds, then the resulting future also succeeds with
   * a successful {@code Produced}; if the input future fails, then the resulting future succeeds
   * with a failing {@code Produced}.
   *
   * <p>Cancelling the resulting future will propagate the cancellation to the input future; but
   * cancelling the input future will trigger the resulting future to succeed with a failing
   * {@code Produced}.
   */
  // TODO(user): Document what happens with an InterruptedException after you figure out how to
  // trigger one in a test.
  public static <T> ListenableFuture<Produced<T>> createFutureProduced(ListenableFuture<T> future) {
    // TODO(dpb): Switch to Futures.catchAsync once guava_jdk5 gets to v19.
    return Futures.withFallback(
        Futures.transform(
            future,
            new Function<T, Produced<T>>() {
              @Override
              public Produced<T> apply(final T value) {
                return Produced.successful(value);
              }
            }),
        Producers.<T>futureFallbackForProduced());

  }

  private static final FutureFallback<Produced<Object>> FUTURE_FALLBACK_FOR_PRODUCED =
      new FutureFallback<Produced<Object>>() {
    @Override public ListenableFuture<Produced<Object>> create(final Throwable t) {
      Produced<Object> produced = Produced.failed(t);
      return Futures.immediateFuture(produced);
    }
  };

  @SuppressWarnings({"unchecked", "rawtypes"})  // bivariant implementation
  private static <T> FutureFallback<Produced<T>> futureFallbackForProduced() {
    return (FutureFallback) FUTURE_FALLBACK_FOR_PRODUCED;
  }

  /**
   * Returns a future of a {@code Set} that contains a single element: the result of the input
   * future.
   */
  public static <T> ListenableFuture<Set<T>> createFutureSingletonSet(ListenableFuture<T> future) {
    return Futures.transform(future, new Function<T, Set<T>>() {
      @Override public Set<T> apply(T value) {
        return ImmutableSet.of(value);
      }
    });
  }

  /**
   * Returns a producer that immediately executes the binding logic for the given provider every
   * time it is called.
   */
  public static <T> Producer<T> producerFromProvider(final Provider<T> provider) {
    checkNotNull(provider);
    return new AbstractProducer<T>() {
      @Override
      protected ListenableFuture<T> compute() {
        return Futures.immediateFuture(provider.get());
      }
    };
  }

  /** Returns a producer that succeeds with the given value. */
  public static <T> Producer<T> immediateProducer(final T value) {
    return new Producer<T>() {
      @Override
      public ListenableFuture<T> get() {
        return Futures.immediateFuture(value);
      }
    };
  }

  /** Returns a producer that fails with the given exception. */
  public static <T> Producer<T> immediateFailedProducer(final Throwable throwable) {
    return new Producer<T>() {
      @Override
      public ListenableFuture<T> get() {
        return Futures.immediateFailedFuture(throwable);
      }
    };
  }

  private Producers() {}
}

@@ -753,30 +753,29 @@
 current.
-FutureFallback
+AsyncFunction
 ;%0Aimport
@@ -1999,31 +1999,14 @@
     
-// TODO(dpb): Switch to
+return
  Fut
@@ -2019,74 +2019,16 @@
 atch
+ing
 Async
- once guava_jdk5 gets to v19.%0A    return Futures.withFallback
 (%0A  
@@ -2280,16 +2280,41 @@
     %7D),%0A
+        Throwable.class,%0A
         
@@ -2385,31 +2385,41 @@
 c final 
-FutureFallback%3C
+AsyncFunction%3CThrowable, 
 Produced
@@ -2469,31 +2469,41 @@
     new 
-FutureFallback%3C
+AsyncFunction%3CThrowable, 
 Produced
@@ -2512,24 +2512,28 @@
 bject%3E%3E() %7B%0A
+    
     @Overrid
@@ -2525,32 +2525,40 @@
        @Override
+%0A       
  public Listenab
@@ -2588,36 +2588,50 @@
 t%3E%3E 
-create(final Throwable t) %7B%0A
+apply(Throwable t) throws Exception %7B%0A    
     
@@ -2682,24 +2682,28 @@
 d(t);%0A      
+    
 return Futur
@@ -2736,18 +2736,26 @@
 d);%0A    
-%7D%0A
+    %7D%0A    
   %7D;%0A%0A  
@@ -2798,17 +2798,16 @@
 types%22%7D)
- 
  // biva
@@ -2852,23 +2852,33 @@
 %3CT%3E 
-FutureFallback%3C
+AsyncFunction%3CThrowable, 
 Prod
@@ -2932,22 +2932,21 @@
 rn (
-FutureFallback
+AsyncFunction
 ) FU

Stop using deprecated Futures method. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=105631120