// Copyright 2015 The Bazel Authors. All rights reserved.
//
// 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.devtools.build.lib.skyframe;

import static com.google.common.util.concurrent.Futures.immediateCancelledFuture;
import static com.google.common.util.concurrent.Futures.immediateFailedFuture;
import static com.google.common.util.concurrent.MoreExecutors.directExecutor;

import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.common.util.concurrent.Uninterruptibles;
import com.google.devtools.build.lib.cmdline.BatchCallback;
import com.google.devtools.build.lib.cmdline.BatchCallback.SafeBatchCallback;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.PackageIdentifier;
import com.google.devtools.build.lib.cmdline.QueryExceptionMarkerInterface;
import com.google.devtools.build.lib.cmdline.RepositoryName;
import com.google.devtools.build.lib.cmdline.ResolvedTargets;
import com.google.devtools.build.lib.cmdline.TargetParsingException;
import com.google.devtools.build.lib.cmdline.TargetPatternResolver;
import com.google.devtools.build.lib.concurrent.MultisetSemaphore;
import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadCompatible;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.ExtendedEventHandler;
import com.google.devtools.build.lib.io.InconsistentFilesystemException;
import com.google.devtools.build.lib.io.ProcessPackageDirectoryException;
import com.google.devtools.build.lib.packages.NoSuchPackageException;
import com.google.devtools.build.lib.packages.NoSuchThingException;
import com.google.devtools.build.lib.packages.Package;
import com.google.devtools.build.lib.packages.Target;
import com.google.devtools.build.lib.pkgcache.FilteringPolicies;
import com.google.devtools.build.lib.pkgcache.FilteringPolicy;
import com.google.devtools.build.lib.pkgcache.RecursivePackageProvider;
import com.google.devtools.build.lib.pkgcache.TargetPatternResolverUtil;
import com.google.devtools.build.lib.query2.engine.QueryException;
import com.google.devtools.build.lib.server.FailureDetails.TargetPatterns;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

/** A {@link TargetPatternResolver} backed by a {@link RecursivePackageProvider}. */
@ThreadCompatible
public final class RecursivePackageProviderBackedTargetPatternResolver
    extends TargetPatternResolver<Target> {

  // TODO(janakr): Move this to a more generic place and unify with SkyQueryEnvironment's value?
  static final int MAX_PACKAGES_BULK_GET = 1000;

  protected final FilteringPolicy policy;
  private final RecursivePackageProvider recursivePackageProvider;
  private final ExtendedEventHandler eventHandler;
  private final MultisetSemaphore<PackageIdentifier> packageSemaphore;
  private final PackageIdentifierBatchingCallback.Factory packageIdentifierBatchingCallbackFactory;

  public RecursivePackageProviderBackedTargetPatternResolver(
      RecursivePackageProvider recursivePackageProvider,
      ExtendedEventHandler eventHandler,
      FilteringPolicy policy,
      MultisetSemaphore<PackageIdentifier> packageSemaphore,
      PackageIdentifierBatchingCallback.Factory packageIdentifierBatchingCallbackFactory) {
    this.recursivePackageProvider = recursivePackageProvider;
    this.eventHandler = eventHandler;
    this.policy = policy;
    this.packageSemaphore = packageSemaphore;
    this.packageIdentifierBatchingCallbackFactory = packageIdentifierBatchingCallbackFactory;
  }

  @Override
  public void warn(String msg) {
    eventHandler.handle(Event.warn(msg));
  }

  /**
   * Gets a {@link Package} from the {@link RecursivePackageProvider}. May return a {@link Package}
   * that has errors.
   */
  private Package getPackage(PackageIdentifier pkgIdentifier)
      throws NoSuchPackageException, InterruptedException {
    return recursivePackageProvider.getPackage(eventHandler, pkgIdentifier);
  }

  private Map<PackageIdentifier, Package> bulkGetPackages(Iterable<PackageIdentifier> pkgIds)
      throws NoSuchPackageException, InterruptedException {
    return recursivePackageProvider.bulkGetPackages(pkgIds);
  }

  @Override
  public Target getTargetOrNull(Label label)
      throws InterruptedException, InconsistentFilesystemException {
    try {
      if (!isPackage(label.getPackageIdentifier())) {
        return null;
      }
      return recursivePackageProvider.getTarget(eventHandler, label);
    } catch (NoSuchThingException e) {
      return null;
    }
  }

  @Override
  public ResolvedTargets<Target> getExplicitTarget(Label label)
      throws TargetParsingException, InterruptedException {
    try {
      Target target = recursivePackageProvider.getTarget(eventHandler, label);
      return policy.shouldRetain(target, true)
          ? ResolvedTargets.of(target)
          : ResolvedTargets.empty();
    } catch (NoSuchThingException e) {
      throw new TargetParsingException(e.getMessage(), e, e.getDetailedExitCode());
    }
  }

  @Override
  public Collection<Target> getTargetsInPackage(
      String originalPattern, PackageIdentifier packageIdentifier, boolean rulesOnly)
      throws TargetParsingException, InterruptedException {
    FilteringPolicy actualPolicy =
        rulesOnly ? FilteringPolicies.and(FilteringPolicies.RULES_ONLY, policy) : policy;
    try {
      Package pkg = getPackage(packageIdentifier);
      return TargetPatternResolverUtil.resolvePackageTargets(pkg, actualPolicy);
    } catch (NoSuchThingException e) {
      String message =
          TargetPatternResolverUtil.getParsingErrorMessage(e.getMessage(), originalPattern);
      throw new TargetParsingException(message, e, e.getDetailedExitCode());
    }
  }

  private Map<PackageIdentifier, Collection<Target>> bulkGetTargetsInPackage(
      String originalPattern, Iterable<PackageIdentifier> pkgIds, FilteringPolicy policy)
      throws InterruptedException {
    try {
      Map<PackageIdentifier, Package> pkgs = bulkGetPackages(pkgIds);
      if (pkgs.size() != Iterables.size(pkgIds)) {
        throw new IllegalStateException(
            "Bulk package retrieval missing results: "
                + Sets.difference(ImmutableSet.copyOf(pkgIds), pkgs.keySet()));
      }
      ImmutableMap.Builder<PackageIdentifier, Collection<Target>> result = ImmutableMap.builder();
      for (PackageIdentifier pkgId : pkgIds) {
        Package pkg = pkgs.get(pkgId);
        result.put(pkgId, TargetPatternResolverUtil.resolvePackageTargets(pkg, policy));
      }
      return result.build();
    } catch (NoSuchThingException e) {
      String message =
          TargetPatternResolverUtil.getParsingErrorMessage(e.getMessage(), originalPattern);
      throw new IllegalStateException(
          "Mismatch: Expected given pkgIds to correspond to valid Packages. " + message, e);
    }
  }

  @Override
  public boolean isPackage(PackageIdentifier packageIdentifier)
      throws InterruptedException, InconsistentFilesystemException {
    return recursivePackageProvider.isPackage(eventHandler, packageIdentifier);
  }

  @Override
  public String getTargetKind(Target target) {
    return target.getTargetKind();
  }

  @Override
  public <E extends Exception & QueryExceptionMarkerInterface> void findTargetsBeneathDirectory(
      final RepositoryName repository,
      final String originalPattern,
      String directory,
      boolean rulesOnly,
      ImmutableSet<PathFragment> forbiddenSubdirectories,
      ImmutableSet<PathFragment> excludedSubdirectories,
      BatchCallback<Target, E> callback,
      Class<E> exceptionClass)
      throws TargetParsingException, E, InterruptedException, ProcessPackageDirectoryException {
    ListenableFuture<Void> future;
    try {
      future =
          findTargetsBeneathDirectoryAsyncImpl(
              repository,
              originalPattern,
              directory,
              rulesOnly,
              forbiddenSubdirectories,
              excludedSubdirectories,
              callback,
              MoreExecutors.newDirectExecutorService());
    } catch (QueryException e) {
      Throwables.propagateIfPossible(e, exceptionClass);
      throw new IllegalStateException(e);
    } catch (NoSuchPackageException e) {
      // Can happen during a Skyframe no-keep-going evaluation.
      throw new TargetParsingException(
          "error loading package under directory '" + directory + "': " + e.getMessage(),
          e,
          e.getDetailedExitCode());
    }
    if (!isSuccessful(future)) {
      // Don't get the future if it finished successfully: all that will do is throw an
      // interrupted exception if this thread was interrupted, but that's not helpful for a done
      // future.
      try {
        future.get();
      } catch (ExecutionException e) {
        Throwables.propagateIfPossible(e.getCause(), InterruptedException.class, exceptionClass);
        throw new IllegalStateException(e.getCause());
      }
    }
  }

  @Override
  public <E extends Exception & QueryExceptionMarkerInterface>
      ListenableFuture<Void> findTargetsBeneathDirectoryAsync(
          RepositoryName repository,
          String originalPattern,
          String directory,
          boolean rulesOnly,
          ImmutableSet<PathFragment> forbiddenSubdirectories,
          ImmutableSet<PathFragment> excludedSubdirectories,
          BatchCallback<Target, E> callback,
          Class<E> exceptionClass,
          ListeningExecutorService executor) {
    try {
      return findTargetsBeneathDirectoryAsyncImpl(
          repository,
          originalPattern,
          directory,
          rulesOnly,
          forbiddenSubdirectories,
          excludedSubdirectories,
          callback,
          executor);
    } catch (TargetParsingException e) {
      return immediateFailedFuture(e);
    } catch (InterruptedException e) {
      return immediateCancelledFuture();
    } catch (ProcessPackageDirectoryException | NoSuchPackageException e) {
      throw new IllegalStateException(
          "Async find targets beneath directory isn't called from within Skyframe: traversing "
              + directory
              + " for "
              + originalPattern,
          e);
    } catch (QueryException e) {
      if (exceptionClass.isInstance(e)) {
        return immediateFailedFuture(e);
      }
      throw new IllegalStateException(e);
    }
  }

  /**
   * The returned future may throw {@link QueryException} (if {@code E} is {@link QueryException})
   * or {@link InterruptedException} on retrieval, but no other exceptions.
   */
  private <E extends Exception & QueryExceptionMarkerInterface>
      ListenableFuture<Void> findTargetsBeneathDirectoryAsyncImpl(
          RepositoryName repository,
          String pattern,
          String directory,
          boolean rulesOnly,
          ImmutableSet<PathFragment> forbiddenSubdirectories,
          ImmutableSet<PathFragment> excludedSubdirectories,
          BatchCallback<Target, E> callback,
          ListeningExecutorService executor)
          throws TargetParsingException, QueryException, InterruptedException,
              ProcessPackageDirectoryException, NoSuchPackageException {
    FilteringPolicy actualPolicy =
        rulesOnly ? FilteringPolicies.and(FilteringPolicies.RULES_ONLY, policy) : policy;

    ArrayList<ListenableFuture<Void>> futures = new ArrayList<>();
    SafeBatchCallback<PackageIdentifier> getPackageTargetsCallback =
        (pkgIdBatch) ->
            futures.add(
                executor.submit(
                    new GetTargetsInPackagesTask<>(pkgIdBatch, pattern, actualPolicy, callback)));

    PathFragment pathFragment = TargetPatternResolverUtil.getPathFragment(directory);
    try (PackageIdentifierBatchingCallback batchingCallback =
        packageIdentifierBatchingCallbackFactory.create(
            getPackageTargetsCallback, MAX_PACKAGES_BULK_GET)) {
      recursivePackageProvider.streamPackagesUnderDirectory(
          batchingCallback,
          eventHandler,
          repository,
          pathFragment,
          forbiddenSubdirectories,
          excludedSubdirectories);
    }
    if (futures.isEmpty()) {
      throw new TargetParsingException(
          "no targets found beneath '" + pathFragment + "'", TargetPatterns.Code.TARGETS_MISSING);
    }
    return Futures.whenAllSucceed(futures).call(() -> null, directExecutor());
  }

  /**
   * Task to get all matching targets in the given packages, filter them, and pass them to the
   * target batch callback.
   */
  private class GetTargetsInPackagesTask<E extends Exception & QueryExceptionMarkerInterface>
      implements Callable<Void> {

    private final Iterable<PackageIdentifier> packageIdentifiers;
    private final String originalPattern;
    private final FilteringPolicy actualPolicy;
    private final BatchCallback<Target, E> callback;

    GetTargetsInPackagesTask(
        Iterable<PackageIdentifier> packageIdentifiers,
        String originalPattern,
        FilteringPolicy actualPolicy,
        BatchCallback<Target, E> callback) {
      this.packageIdentifiers = packageIdentifiers;
      this.originalPattern = originalPattern;
      this.actualPolicy = actualPolicy;
      this.callback = callback;
    }

    @Override
    public Void call() throws E, InterruptedException {
      ImmutableSet<PackageIdentifier> pkgIdBatchSet = ImmutableSet.copyOf(packageIdentifiers);
      packageSemaphore.acquireAll(pkgIdBatchSet);
      try {
        Iterable<Collection<Target>> resolvedTargets =
            RecursivePackageProviderBackedTargetPatternResolver.this
                .bulkGetTargetsInPackage(originalPattern, packageIdentifiers, actualPolicy)
                .values();
        List<Target> filteredTargets = new ArrayList<>(calculateSize(resolvedTargets));
        for (Collection<Target> targets : resolvedTargets) {
          filteredTargets.addAll(targets);
        }
        // TODO(b/121277360): Invoking the callback while holding onto the package
        // semaphore can lead to deadlocks.
        //
        // Also, if the semaphore has a small count, acquireAll can also lead to problems if we
        // don't batch appropriately. Note: We default to an unbounded semaphore for SkyQuery.
        //
        // TODO(b/168142585): Make this code strictly correct in the situation where the semaphore
        // is bounded.
        callback.process(filteredTargets);
      } finally {
        packageSemaphore.releaseAll(pkgIdBatchSet);
      }
      return null;
    }
  }

  private static <T> int calculateSize(Iterable<Collection<T>> resolvedTargets) {
    int size = 0;
    for (Collection<T> targets : resolvedTargets) {
      size += targets.size();
    }
    return size;
  }

  /** Inspired by not-yet-open-source futures code. */
  private static boolean isSuccessful(Future<?> future) {
    if (future.isDone() && !future.isCancelled()) {
      try {
        Uninterruptibles.getUninterruptibly(future);
        return true;
      } catch (ExecutionException | RuntimeException e) {
        // Fall through.
      }
    }
    return false;
  }
}
