// Copyright (c) 2023, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

package com.android.tools.r8.threading;

import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.ThrowingAction;
import com.android.tools.r8.utils.UncheckedExecutionException;
import com.google.common.util.concurrent.Futures;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.function.Consumer;
import java.util.function.Predicate;

public class TaskCollection<T> {

  private final ThreadingModule threadingModule;
  private final ExecutorService executorService;
  private final List<Future<T>> futures;

  public TaskCollection(
      ThreadingModule threadingModule, ExecutorService executorService, int initialCapacity) {
    this.threadingModule = threadingModule;
    this.executorService = executorService;
    this.futures = initialCapacity > 0 ? new ArrayList<>(initialCapacity) : new ArrayList<>();
  }

  public TaskCollection(ThreadingModule threadingModule, ExecutorService executorService) {
    this(threadingModule, executorService, -1);
  }

  public TaskCollection(InternalOptions options, ExecutorService executorService) {
    this(options, executorService, -1);
  }

  public TaskCollection(
      InternalOptions options, ExecutorService executorService, int initialCapacity) {
    this(options.getThreadingModule(), executorService, initialCapacity);
  }

  /**
   * Submit a task for execution.
   *
   * <p>The task may start running immediately and on the same thread as the caller, or may run
   * later with completion ensured by a call to {@link #await(Consumer)}.
   *
   * <p>This is the main implementation of adding a task for execution.
   *
   * @param task Task to submit for execution.
   */
  public void submit(Callable<T> task) throws ExecutionException {
    futures.add(threadingModule.submit(task, executorService));
  }

  /**
   * Await the completion of all tasks.
   *
   * <p>This is the main implementation of awaiting task executions.
   *
   * @param consumer Consumer to get each task result. Use null if no results are needed.
   */
  public void await(Consumer<T> consumer) throws ExecutionException {
    threadingModule.awaitFutures(futures);
    if (consumer != null) {
      for (Future<T> future : futures) {
        consumer.accept(Futures.getDone(future));
      }
    }
    futures.clear();
  }

  // Final helper methods for the collection.

  /** Number of current tasks in the collection. */
  public final int size() {
    return futures.size();
  }

  /** True if no tasks are in the collection. */
  public final boolean isEmpty() {
    return size() == 0;
  }

  // Internal getter for subclasses.
  final List<Future<T>> internalGetAndClearFutures() {
    List<Future<T>> copy = new ArrayList<>(futures);
    futures.clear();
    return copy;
  }

  // Internal getter for subclasses.
  final ThreadingModule internalGetThreadingModule() {
    return threadingModule;
  }

  // All methods below are derived from the two primitives above.
  // This ensures that the synchronized impl remains sound.

  /** Derived submit to allow throwing tasks. */
  public final <E extends Exception> void submit(ThrowingAction<E> task) throws ExecutionException {
    submit(
        () -> {
          task.execute();
          return null;
        });
  }

  /** Derived submit to hide the execution exception */
  public final void submitUnchecked(Callable<T> task) {
    try {
      submit(task);
    } catch (ExecutionException e) {
      throw new UncheckedExecutionException(e);
    }
  }

  /** Derived submit to hide the execution exception */
  public final <E extends Exception> void submitUnchecked(ThrowingAction<E> task) {
    try {
      submit(task);
    } catch (ExecutionException e) {
      throw new UncheckedExecutionException(e);
    }
  }

  /** Derived await when no results are needed. */
  public final void await() throws ExecutionException {
    await(null);
  }

  /** Derived await to get all the results in a list. */
  public final List<T> awaitWithResults() throws ExecutionException {
    List<T> results = new ArrayList<>(size());
    await(results::add);
    return results;
  }

  /** Derived await to get a subset of the results in a list. */
  public final List<T> awaitWithResults(Predicate<T> predicate) throws ExecutionException {
    if (predicate == null) {
      return awaitWithResults();
    }
    List<T> filtered = new ArrayList<>();
    await(
        result -> {
          if (predicate.test(result)) {
            filtered.add(result);
          }
        });
    return filtered;
  }
}
