// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package io.flutter.plugins.googlesignin;

import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.SettableFuture;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * A class for running tasks in a background thread.
 *
 * <p>TODO(jackson): If this class is useful for other plugins, consider including it in a shared
 * library or in the Flutter engine
 */
public final class BackgroundTaskRunner {

  /**
   * Interface that callers of this API can implement to be notified when a {@link
   * #runInBackground(Callable,Callback) background task} has completed.
   */
  public interface Callback<T> {
    /**
     * Invoked on the UI thread when the specified future has completed (calling {@code get()} on
     * the future is guaranteed not to block). If the future completed with an exception, then
     * {@code get()} will throw an {@code ExecutionException}.
     */
    void run(Future<T> future);
  }

  private final ThreadPoolExecutor executor;

  /**
   * Creates a new background processor with the given number of threads.
   *
   * @param threads The fixed number of threads in ther pool.
   */
  public BackgroundTaskRunner(int threads) {
    BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>();
    // Only keeps idle threads open for 1 second if we've got more threads than cores.
    executor = new ThreadPoolExecutor(threads, threads, 1, TimeUnit.SECONDS, workQueue);
  }

  /**
   * Executes the specified task in a background thread and notifies the specified callback once the
   * task has completed (either successfully or with an exception).
   *
   * <p>The callback will be notified on the UI thread.
   */
  public <T> void runInBackground(Callable<T> task, final Callback<T> callback) {
    final ListenableFuture<T> future = runInBackground(task);
    future.addListener(
        new Runnable() {
          @Override
          public void run() {
            callback.run(future);
          }
        },
        Executors.uiThreadExecutor());
  }

  /**
   * Executes the specified task in a background thread and returns a future with which the caller
   * can be notified of task completion.
   *
   * <p>Note: the future will be notified on the background thread. To be notified on the UI thread,
   * use {@link #runInBackground(Callable,Callback)}.
   */
  public <T> ListenableFuture<T> runInBackground(final Callable<T> task) {
    final SettableFuture<T> future = SettableFuture.create();

    executor.execute(
        new Runnable() {
          @Override
          public void run() {
            if (!future.isCancelled()) {
              try {
                future.set(task.call());
              } catch (Throwable t) {
                future.setException(t);
              }
            }
          }
        });

    return future;
  }
}
