// Copyright 2016 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.query2;

import static com.google.common.collect.ImmutableSet.toImmutableSet;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Multimap;
import com.google.devtools.build.lib.actions.FileStateValue;
import com.google.devtools.build.lib.actions.FileValue;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.LabelConstants;
import com.google.devtools.build.lib.cmdline.PackageIdentifier;
import com.google.devtools.build.lib.collect.compacthashset.CompactHashSet;
import com.google.devtools.build.lib.packages.Target;
import com.google.devtools.build.lib.query2.ParallelVisitorUtils.ParallelQueryVisitor;
import com.google.devtools.build.lib.query2.engine.Callback;
import com.google.devtools.build.lib.query2.engine.QueryException;
import com.google.devtools.build.lib.query2.engine.QueryExpressionContext;
import com.google.devtools.build.lib.query2.engine.Uniquifier;
import com.google.devtools.build.lib.rules.repository.WorkspaceFileHelper;
import com.google.devtools.build.lib.skyframe.ContainingPackageLookupFunction;
import com.google.devtools.build.lib.skyframe.DirectoryListingStateValue;
import com.google.devtools.build.lib.skyframe.DirectoryListingValue;
import com.google.devtools.build.lib.skyframe.PackageLookupValue;
import com.google.devtools.build.lib.skyframe.PackageValue;
import com.google.devtools.build.lib.skyframe.SkyFunctions;
import com.google.devtools.build.lib.skyframe.WorkspaceNameValue;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.lib.vfs.RootedPath;
import com.google.devtools.build.skyframe.SkyFunctionName;
import com.google.devtools.build.skyframe.SkyKey;
import com.google.devtools.build.skyframe.SkyValue;
import com.google.devtools.build.skyframe.WalkableGraph;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import javax.annotation.Nullable;

/**
 * A helper class that visits packages of affected files by BFS and is represented by the
 * queryfunction 'rbuildfiles'. Other query functions may also use functionality provided by this
 * visitor.
 */
public class RBuildFilesVisitor extends ParallelQueryVisitor<SkyKey, PackageIdentifier, Target> {

  // Each target in the full output of this visitor corresponds to BUILD file InputFile of a
  // unique package. So the processResultsBatchSize we choose to pass to the ParallelVisitor ctor
  // influences how many packages each leaf task doing processPartialResults will have to
  // deal with at once. A value of 100 was chosen experimentally.
  private static final int PROCESS_RESULTS_BATCH_SIZE = 100;

  // We don't expect to find any additional BUILD files so we skip visitation of the following
  // nodes.
  private static final ImmutableSet<SkyFunctionName> NODES_TO_PRUNE_TRAVERSAL =
      ImmutableSet.of(
          Label.TRANSITIVE_TRAVERSAL,
          SkyFunctions.COLLECT_TARGETS_IN_PACKAGE,
          SkyFunctions.COLLECT_TEST_SUITES_IN_PACKAGE,
          SkyFunctions.PREPARE_DEPS_OF_TARGETS_UNDER_DIRECTORY,
          SkyFunctions.PREPARE_TEST_SUITES_UNDER_DIRECTORY,
          SkyFunctions.PACKAGE_ERROR_MESSAGE,
          SkyFunctions.PREPARE_DEPS_OF_PATTERN,
          SkyFunctions.PREPARE_DEPS_OF_PATTERNS);

  private static final SkyKey EXTERNAL_PACKAGE_KEY =
      PackageValue.key(LabelConstants.EXTERNAL_PACKAGE_IDENTIFIER);
  private final SkyQueryEnvironment env;
  private final QueryExpressionContext<Target> context;
  private final Uniquifier<SkyKey> visitUniquifier;
  protected final Uniquifier<SkyKey> resultUniquifier;

  public RBuildFilesVisitor(
      SkyQueryEnvironment env,
      Uniquifier<SkyKey> visitUniquifier,
      Uniquifier<SkyKey> resultUniquifier,
      QueryExpressionContext<Target> context,
      Callback<Target> callback) {
    super(
        callback,
        env.getVisitBatchSizeForParallelVisitation(),
        PROCESS_RESULTS_BATCH_SIZE,
        env.getVisitTaskStatusCallback());
    this.env = env;
    this.visitUniquifier = visitUniquifier;
    this.resultUniquifier = resultUniquifier;
    this.context = context;
  }

  @Override
  protected Visit getVisitResult(Iterable<SkyKey> values)
      throws QueryException, InterruptedException {
    Collection<Iterable<SkyKey>> reverseDeps = env.graph.getReverseDeps(values).values();
    Set<PackageIdentifier> keysToUseForResult = CompactHashSet.create();
    Set<SkyKey> keysToVisitNext = CompactHashSet.create();
    for (SkyKey rdep : Iterables.concat(reverseDeps)) {
      // This loop is cpu bound, make sure we bail if asked.
      if (Thread.interrupted()) {
        throw new InterruptedException();
      }

      if (rdep.functionName().equals(SkyFunctions.PACKAGE)) {
        if (resultUniquifier.unique(rdep)) {
          keysToUseForResult.add((PackageIdentifier) rdep.argument());
        }
        // PackageValue(//p) has a transitive dep on the PackageValue(//external), so we need to
        // make sure these dep paths are traversed. These dep paths go through the singleton
        // WorkspaceNameValue(), and that node has a direct dep on PackageValue(//external), so it
        // suffices to ensure we visit PackageValue(//external).
        if (rdep.equals(EXTERNAL_PACKAGE_KEY)) {
          keysToVisitNext.add(rdep);
        }
      } else if (!NODES_TO_PRUNE_TRAVERSAL.contains(rdep.functionName())) {
        processNonPackageRdepAndDetermineVisitations(rdep, keysToVisitNext, keysToUseForResult);
      }
    }
    return new Visit(keysToUseForResult, keysToVisitNext);
  }

  @Override
  protected Iterable<SkyKey> preprocessInitialVisit(Iterable<SkyKey> visitationKeys) {
    return visitationKeys;
  }

  protected void processNonPackageRdepAndDetermineVisitations(
      SkyKey rdep, Set<SkyKey> keysToVisitNext, Set<PackageIdentifier> keysToUseForResult)
      throws QueryException {
    // Packages may depend on the existence of subpackages, but these edges aren't
    // relevant to rbuildfiles. They may also depend on files transitively through
    // globs, but these cannot be included in load statements and so we don't traverse
    // through these either.
    if (!rdep.functionName().equals(SkyFunctions.PACKAGE_LOOKUP)
        && !rdep.functionName().equals(SkyFunctions.GLOB)) {
      keysToVisitNext.add(rdep);
    }
  }

  @Override
  protected Iterable<Target> outputKeysToOutputValues(Iterable<PackageIdentifier> targetKeys)
      throws QueryException, InterruptedException {
    return env.getBuildFileTargetsForPackageKeys(ImmutableSet.copyOf(targetKeys), context);
  }

  @Override
  protected Iterable<SkyKey> noteAndReturnUniqueVisitationKeys(
      Iterable<SkyKey> prospectiveVisitationKeys) throws QueryException {
    return visitUniquifier.unique(prospectiveVisitationKeys);
  }

  /** Initiates the graph visitation algorithm seeded by a set of file paths. */
  public void visitFileIdentifiersAndWaitForCompletion(
      WalkableGraph graph, Iterable<PathFragment> fileKeys)
      throws QueryException, InterruptedException {
    visitAndWaitForCompletion(
        getSkyKeysForFileFragments(graph, fileKeys, /*includeAncestorKeys=*/ false));
  }

  public void visitFileAndDirectoryKeysAndWaitForCompletion(
      WalkableGraph graph, Iterable<PathFragment> fileKeys)
      throws QueryException, InterruptedException {
    visitAndWaitForCompletion(
        getSkyKeysForFileFragments(graph, fileKeys, /*includeAncestorKeys=*/ true));
  }

  /**
   * The passed in {@link PathFragment}s can be associated uniquely to a {@link FileStateValue} with
   * the following logic (the same logic that's in {@link ContainingPackageLookupFunction}): For
   * each given file path, we look for the nearest ancestor directory (starting with its parent
   * directory), if any, that has a package. The {@link PackageLookupValue} for this package tells
   * us the package root that we should use for the {@link RootedPath} for the {@link
   * FileStateValue} key.
   *
   * <p>For the reverse graph traversal, we are looking for all packages that are transitively
   * reverse dependencies of those {@link FileStateValue} keys. This function returns a collection
   * of SkyKeys whose transitive reverse dependencies must contain the exact same set of packages.
   *
   * <p>Note that there may not be nodes in the graph corresponding to the returned SkyKeys.
   *
   * <p>Note also that we assume there'll be a PackageLookupValue node for some ancestor directory
   * of every file to which a symlink could possibly point otherwise the file will not be included.
   *
   * <p>If includeAncestorKeys is true, we will include a directory listing state of the first
   * ancestor directory that exists and file states for non-existent ancestors.
   */
  @VisibleForTesting
  static Set<SkyKey> getSkyKeysForFileFragments(
      WalkableGraph graph, Iterable<PathFragment> pathFragments, boolean includeAncestorKeys)
      throws InterruptedException {
    if (Iterables.isEmpty(pathFragments)) {
      return ImmutableSet.of();
    }

    Set<SkyKey> result = new HashSet<>();
    ListMultimap<PathFragment, PathFragment> currentAncestorToOriginalPath =
        ArrayListMultimap.create();
    for (PathFragment pathFragment : pathFragments) {
      checkWorkspaceFile(result, pathFragment);
      PathFragment parentPathFragment = pathFragment.getParentDirectory();
      if (parentPathFragment != null) {
        currentAncestorToOriginalPath.put(parentPathFragment, pathFragment);
      }
    }

    // Used to find directories that have been added in the diff.
    Set<RootedPath> pathsToCheckForNewlyAddedDirectories = new HashSet<>();

    // We look at each ancestor directory of every file, and use the currentAncestorToOriginalPath
    // map to avoid doing unnecessary work with common ancestors. If we don't find a package
    // with the first level of ancestors, we go up a level, until we find the first package
    // for every file. If a file doesn't have a parent package, the file is ignored.
    while (!currentAncestorToOriginalPath.isEmpty()) {
      ImmutableSet<SkyKey> pkgLookupKeys =
          currentAncestorToOriginalPath.keySet().stream()
              .map(RBuildFilesVisitor::getPkgLookupKeyForDirectory)
              .collect(toImmutableSet());
      Map<SkyKey, SkyValue> lookupValues = graph.getSuccessfulValues(pkgLookupKeys);
      for (Map.Entry<SkyKey, SkyValue> entry : lookupValues.entrySet()) {
        PackageLookupValue packageLookupValue = (PackageLookupValue) entry.getValue();
        if (packageLookupValue.packageExists()) {
          SkyKey packageLookupKey = entry.getKey();
          PathFragment currentFragment =
              ((PackageIdentifier) packageLookupKey.argument()).getPackageFragment();
          List<PathFragment> originalFiles = currentAncestorToOriginalPath.get(currentFragment);
          Preconditions.checkState(!originalFiles.isEmpty(), entry);
          for (PathFragment fileName : originalFiles) {
            RootedPath rootedPath = RootedPath.toRootedPath(packageLookupValue.getRoot(), fileName);
            result.add(FileStateValue.key(rootedPath));
            // Include the File key too in case the FileState is never considered due to a
            // missing parent directory.
            result.add(FileValue.key(rootedPath));

            if (includeAncestorKeys) {
              RootedPath parentPath = rootedPath.getParentDirectory();
              result.add(DirectoryListingStateValue.key(parentPath));
              // Include the DirectoryListing key too in case the DirectoryListingState is never
              // considered due to a missing parent directory.
              result.add(DirectoryListingValue.key(parentPath));
              for (PathFragment pathToCheckIfNewlyAdded = fileName;
                  pathToCheckIfNewlyAdded.getPathString().length()
                      > currentFragment.getPathString().length();
                  pathToCheckIfNewlyAdded = pathToCheckIfNewlyAdded.getParentDirectory()) {
                pathsToCheckForNewlyAddedDirectories.add(
                    RootedPath.toRootedPath(packageLookupValue.getRoot(), pathToCheckIfNewlyAdded));
              }
            }
          }
          currentAncestorToOriginalPath.removeAll(currentFragment);
        }
      }
      currentAncestorToOriginalPath = goUpOneDirectory(currentAncestorToOriginalPath);
    }
    if (includeAncestorKeys) {
      includeAncestorKeysInResult(graph, result, pathsToCheckForNewlyAddedDirectories);
    }
    return result;
  }

  private static ListMultimap<PathFragment, PathFragment> goUpOneDirectory(
      Multimap<PathFragment, PathFragment> currentToOriginal) {
    ListMultimap<PathFragment, PathFragment> newCurrentToOriginal = ArrayListMultimap.create();
    for (PathFragment pathFragment : currentToOriginal.keySet()) {
      PathFragment parent = pathFragment.getParentDirectory();
      if (parent != null) {
        newCurrentToOriginal.putAll(parent, currentToOriginal.get(pathFragment));
      }
    }
    return newCurrentToOriginal;
  }

  private static void checkWorkspaceFile(Set<SkyKey> result, PathFragment file) {
    // The WORKSPACE file is a transitive dependency of every package. Unfortunately, there is
    // no specific SkyValue that we can use to figure out under which package path entries it
    // lives so we add a dependency on the WorkspaceNameValue key.
    if (WorkspaceFileHelper.matchWorkspaceFileName(file)) {
      // TODO(mschaller): this should not be checked at runtime. These are constants!
      Preconditions.checkState(
          LabelConstants.WORKSPACE_FILE_NAME
              .getParentDirectory()
              .equals(PathFragment.EMPTY_FRAGMENT),
          LabelConstants.WORKSPACE_FILE_NAME);
      result.add(WorkspaceNameValue.key());
    }
  }

  private static void includeAncestorKeysInResult(
      WalkableGraph graph, Set<SkyKey> result, Set<RootedPath> pathsToCheckForNewlyAddedDirectories)
      throws InterruptedException {
    // Do a single batch fetch of all FileState's corresponding to directories with
    // failed package lookups.
    Set<SkyKey> fileStateKeysToFetch =
        pathsToCheckForNewlyAddedDirectories.stream()
            .map(FileStateValue::key)
            .collect(Collectors.toSet());
    Map<SkyKey, SkyValue> fileStateValues = graph.getSuccessfulValues(fileStateKeysToFetch);

    for (SkyKey fileStateKey : fileStateKeysToFetch) {
      if (fileStateValues.containsKey(fileStateKey)) {
        FileStateValue fsv = (FileStateValue) fileStateValues.get(fileStateKey);
        if (!fsv.getType().exists() && !fsv.getType().isDirectory()) {
          processFileStateKeyForMissingDirectory(result, (FileStateValue.Key) fileStateKey);
        }
      } else {
        processFileStateKeyForMissingDirectory(result, (FileStateValue.Key) fileStateKey);
      }
    }
  }

  private static void processFileStateKeyForMissingDirectory(
      Set<SkyKey> result, FileStateValue.Key key) {
    RootedPath rootedPath = key.argument();
    result.add(key);
    result.add(FileValue.key(rootedPath));
    // Add a DirectoryListingState node to our traversal even if the ancestor path too didn't exist
    // prior to the diff. This will have no effect on the results if the ancestor directory was also
    // newly created doesn't exist but has the consequence that the first ancestor path that did
    // exist prior to the diff will be correctly marked as having a changed directory listing state.
    RootedPath parentPath = rootedPath.getParentDirectory();
    if (parentPath != null) {
      result.add(DirectoryListingStateValue.key(parentPath));
      result.add(DirectoryListingValue.key(parentPath));
    }
  }

  /**
   * Returns package lookup key for looking up the package root for which there may be a relevant
   * {@link FileStateValue} node in the graph for {@code originalFileFragment}, which is assumed to
   * be a file path.
   *
   * <p>This is a helper function for {@link #getSkyKeysForFileFragments}.
   */
  @Nullable
  private static SkyKey getPkgLookupKeyForDirectory(PathFragment pathFragment) {
    return PackageLookupValue.key(
        PackageIdentifier.createInMainRepo(Preconditions.checkNotNull(pathFragment)));
  }
}
