/*
 * Copyright 2012-present Facebook, 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 com.facebook.buck.parser;

import com.facebook.buck.event.AbstractBuckEvent;
import com.facebook.buck.event.BuckEvent;
import com.facebook.buck.event.BuckEventBus;
import com.facebook.buck.graph.AbstractAcyclicDepthFirstPostOrderTraversal;
import com.facebook.buck.graph.MutableDirectedGraph;
import com.facebook.buck.io.ProjectFilesystem;
import com.facebook.buck.json.BuildFileParseException;
import com.facebook.buck.json.DefaultProjectBuildFileParserFactory;
import com.facebook.buck.json.JsonObjectHashing;
import com.facebook.buck.json.ProjectBuildFileParser;
import com.facebook.buck.json.ProjectBuildFileParserFactory;
import com.facebook.buck.log.Logger;
import com.facebook.buck.model.BuildFileTree;
import com.facebook.buck.model.BuildId;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.BuildTargetException;
import com.facebook.buck.model.BuildTargetPattern;
import com.facebook.buck.model.FilesystemBackedBuildFileTree;
import com.facebook.buck.model.Flavored;
import com.facebook.buck.model.HasBuildTarget;
import com.facebook.buck.model.UnflavoredBuildTarget;
import com.facebook.buck.rules.ActionGraph;
import com.facebook.buck.rules.BuildRuleFactoryParams;
import com.facebook.buck.rules.BuildRuleType;
import com.facebook.buck.rules.ConstructorArgMarshalException;
import com.facebook.buck.rules.ConstructorArgMarshaller;
import com.facebook.buck.rules.Description;
import com.facebook.buck.rules.Repository;
import com.facebook.buck.rules.RepositoryFactory;
import com.facebook.buck.rules.RuleKeyBuilderFactory;
import com.facebook.buck.rules.TargetGraph;
import com.facebook.buck.rules.TargetNode;
import com.facebook.buck.util.Console;
import com.facebook.buck.util.HumanReadableException;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Iterators;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.eventbus.Subscribe;
import com.google.common.hash.HashCode;
import com.google.common.hash.Hasher;
import com.google.common.hash.Hashing;

import java.io.IOException;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;

import javax.annotation.Nullable;

/**
 * High-level build file parsing machinery.  Primarily responsible for producing a
 * {@link ActionGraph} based on a set of targets.  Also exposes some low-level facilities to
 * parse individual build files. Caches build rules to minimise the number of calls to python and
 * processes filesystem WatchEvents to invalidate the cache as files change.
 */
public class Parser {

  private final BuildTargetParser buildTargetParser;

  private final CachedState state;

  private final ImmutableSet<Pattern> tempFilePatterns;

  private final RepositoryFactory repositoryFactory;
  // TODO(jacko): DELETE THESE!!!
  private final Repository repository;
  private final ProjectBuildFileParserFactory buildFileParserFactory;

  private final RuleKeyBuilderFactory ruleKeyBuilderFactory;

  /**
   * Key of the meta-rule that lists the build files executed while reading rules.
   * The value is a list of strings with the root build file as the head and included
   * build files as the tail, for example: {"__includes":["/jimp/BUCK", "/jimp/buck_includes"]}
   */
  private static final String INCLUDES_META_RULE = "__includes";

  /**
   * A map from absolute included files ({@code /jimp/BUILD_DEFS}, for example) to the build files
   * that depend on them (typically {@code /jimp/BUCK} files).
   */
  private final ListMultimap<Path, Path> buildFileDependents;

  private final boolean enforceBuckPackageBoundary;

  /**
   * A BuckEvent used to record the parse start time, which should include the WatchEvent
   * processing that occurs before the BuildTargets required to build a full ParseStart event are
   * known.
   */
  private Optional<BuckEvent> parseStartEvent = Optional.absent();

  private static final Logger LOG = Logger.get(Parser.class);

  private static final ConstructorArgMarshaller marshaller = new ConstructorArgMarshaller();

  /**
   * A cached BuildFileTree which can be invalidated and lazily constructs new BuildFileTrees.
   * TODO(user): refactor this as a generic CachingSupplier<T> when it's needed elsewhere.
   */
  @VisibleForTesting
  static class BuildFileTreeCache implements Supplier<BuildFileTree> {
    private final Supplier<BuildFileTree> supplier;
    @Nullable private BuildFileTree buildFileTree;
    private BuildId currentBuildId = new BuildId();
    private BuildId buildTreeBuildId = new BuildId();

    /**
     * @param buildFileTreeSupplier each call to get() must reconstruct the tree from disk.
     */
    public BuildFileTreeCache(Supplier<BuildFileTree> buildFileTreeSupplier) {
      this.supplier = buildFileTreeSupplier;
    }

    /**
     * Invalidate the current build file tree if it was not created during this build.
     * If the BuildFileTree was created during the current build it is still valid and
     * recreating it would generate an identical tree.
     */
    public synchronized void invalidateIfStale() {
      if (!currentBuildId.equals(buildTreeBuildId)) {
        buildFileTree = null;
      }
    }

    /**
     * @return the cached BuildFileTree, or a new lazily constructed BuildFileTree.
     */
    @Override
    public synchronized BuildFileTree get() {
      if (buildFileTree == null) {
        buildTreeBuildId = currentBuildId;
        buildFileTree = supplier.get();
      }
      return buildFileTree;
    }

    /**
     * Stores the current build id, which is used to determine when the BuildFileTree is invalid.
     */
    public synchronized void onCommandStartedEvent(BuckEvent event) {
      // Ideally, the type of event would be CommandEvent.Started, but that would introduce
      // a dependency on com.facebook.buck.cli.
      Preconditions.checkArgument(event.getEventName().equals("CommandStarted"),
          "event should be of type CommandEvent.Started, but was: %s.",
          event);
      currentBuildId = event.getBuildId();
    }
  }
  private final BuildFileTreeCache buildFileTreeCache;

  public static Parser createParser(
      final RepositoryFactory repositoryFactory,
      final ParserConfig parserConfig,
      RuleKeyBuilderFactory ruleKeyBuilderFactory)
      throws IOException, InterruptedException {
    final Repository rootRepository = repositoryFactory.getRootRepository();
    return new Parser(
        repositoryFactory,
        parserConfig,
        /* Calls to get() will reconstruct the build file tree by calling constructBuildFileTree. */
        // TODO(simons): Consider momoizing the suppler.
        new Supplier<BuildFileTree>() {
          @Override
          public BuildFileTree get() {
            return new FilesystemBackedBuildFileTree(
                rootRepository.getFilesystem(),
                parserConfig.getBuildFileName());
          }
        },
        // TODO(jacko): Get rid of this global BuildTargetParser completely.
        rootRepository.getBuildTargetParser(),
        new DefaultProjectBuildFileParserFactory(
            rootRepository.getFilesystem(),
            parserConfig,
            rootRepository.getAllDescriptions()),
        ruleKeyBuilderFactory);
  }

  /**
   * @param buildFileTreeSupplier each call to getInput() must reconstruct the build file tree from
   */
  @VisibleForTesting
  Parser(
      RepositoryFactory repositoryFactory,
      ParserConfig parserConfig,
      Supplier<BuildFileTree> buildFileTreeSupplier,
      BuildTargetParser buildTargetParser,
      ProjectBuildFileParserFactory buildFileParserFactory,
      RuleKeyBuilderFactory ruleKeyBuilderFactory)
      throws IOException, InterruptedException {
    this.repositoryFactory = repositoryFactory;
    this.repository = repositoryFactory.getRootRepository();
    this.buildFileTreeCache = new BuildFileTreeCache(buildFileTreeSupplier);
    this.buildTargetParser = buildTargetParser;
    this.buildFileParserFactory = buildFileParserFactory;
    this.ruleKeyBuilderFactory = ruleKeyBuilderFactory;
    this.enforceBuckPackageBoundary = parserConfig.getEnforceBuckPackageBoundary();
    this.buildFileDependents = ArrayListMultimap.create();
    this.tempFilePatterns = parserConfig.getTempFilePatterns();
    this.state = new CachedState(parserConfig.getBuildFileName());
  }

  public BuildTargetParser getBuildTargetParser() {
    return buildTargetParser;
  }

  public Path getProjectRoot() {
    return repository.getFilesystem().getRootPath();
  }

  /**
   * The rules in a build file are cached if that specific build file was parsed or all build
   * files in the project were parsed and the includes and environment haven't changed since the
   * rules were cached.
   *
   * @param buildFile the build file to look up in the {@link CachedState}.
   * @param includes the files to include before executing the build file.
   * @param env the environment to execute the build file in.
   * @return true if the build file has already been parsed and its rules are cached.
   */
  private synchronized boolean isCached(
      Path buildFile,
      Iterable<String> includes,
      ImmutableMap<String, String> env) {
    boolean includesChanged = state.invalidateCacheOnIncludeChange(includes);
    boolean environmentChanged = state.invalidateCacheOnEnvironmentChange(env);
    boolean fileParsed = state.isParsed(buildFile);
    return !includesChanged && !environmentChanged && fileParsed;
  }

  private synchronized void invalidateCache() {
    state.invalidateAll();
  }

  /**
   * Invoke this after each command to clean any parts of the cache
   * that must not be retained between commands.
   */
  public synchronized void cleanCache() {
    state.cleanCache();
  }

  public LoadingCache<BuildTarget, HashCode> getBuildTargetHashCodeCache() {
    return state.getBuildTargetHashCodeCache();
  }

  /**
   * @return a set of {@link BuildTarget} objects that this {@link TargetNodeSpec} refers to.
   */
  private ImmutableSet<BuildTarget> resolveTargetSpec(
      TargetNodeSpec spec,
      ParserConfig parserConfig,
      ProjectBuildFileParser buildFileParser,
      ImmutableMap<String, String> environment)
      throws BuildFileParseException, BuildTargetException, IOException, InterruptedException {

    ImmutableSet.Builder<BuildTarget> targets = ImmutableSet.builder();

    // Iterate over the build files the given target node spec returns.
    for (Path buildFile : spec.getBuildFileSpec().findBuildFiles(
        repository.getFilesystem(),
        parserConfig.getBuildFileName())) {

      // Format a proper error message for non-existent build files.
      if (!repository.getFilesystem().isFile(buildFile)) {
        throw new MissingBuildFileException(spec, buildFile);
      }

      // Build up a list of all target nodes from the build file.
      List<Map<String, Object>> parsed = parseBuildFile(
          repository.getFilesystem().resolve(buildFile),
          parserConfig,
          buildFileParser,
          environment);
      List<TargetNode<?>> nodes = Lists.newArrayListWithCapacity(parsed.size());
      for (Map<String, Object> map : parsed) {
        BuildTarget target = parseBuildTargetFromRawRule(map);
        TargetNode<?> node = getTargetNode(target);
        nodes.add(node);
      }

      // Call back into the target node spec to filter the relevant build targets.
      targets.addAll(spec.filter(nodes));
    }

    return targets.build();
  }

  private ImmutableSet<BuildTarget> resolveTargetSpecs(
      Iterable<? extends TargetNodeSpec> specs,
      ParserConfig parserConfig,
      ProjectBuildFileParser buildFileParser,
      ImmutableMap<String, String> environment)
      throws BuildFileParseException, BuildTargetException, IOException, InterruptedException {

    ImmutableSet.Builder<BuildTarget> targets = ImmutableSet.builder();

    for (TargetNodeSpec spec : specs) {
      targets.addAll(
          resolveTargetSpec(
              spec,
              parserConfig,
              buildFileParser,
              environment));
    }

    return targets.build();
  }

  /**
   * @param targetNodeSpecs the specs representing the build targets to generate a target graph for.
   * @param eventBus used to log events while parsing.
   * @return the target graph containing the build targets and their related targets.
   */
  public synchronized TargetGraph buildTargetGraphForTargetNodeSpecs(
      Iterable<? extends TargetNodeSpec> targetNodeSpecs,
      ParserConfig parserConfig,
      BuckEventBus eventBus,
      Console console,
      ImmutableMap<String, String> environment,
      boolean enableProfiling)
      throws BuildFileParseException, BuildTargetException, IOException, InterruptedException {

    TargetGraph graph = null;
    // TODO(jacko): Instantiating one ProjectBuildFileParser here isn't enough. We a collection of
    //              repo-specific parsers.
    try (ProjectBuildFileParser buildFileParser = buildFileParserFactory.createParser(
        console,
        environment,
        eventBus)) {
      buildFileParser.setEnableProfiling(enableProfiling);

      // Resolve the target node specs to the build targets the represent.
      ImmutableSet<BuildTarget> buildTargets = resolveTargetSpecs(
          targetNodeSpecs,
          parserConfig,
          buildFileParser,
          environment);

      postParseStartEvent(buildTargets, eventBus);

      try {
        graph = buildTargetGraph(
            buildTargets,
            parserConfig,
            buildFileParser,
            environment);
        return graph;
      } finally {
        eventBus.post(ParseEvent.finished(buildTargets, Optional.fromNullable(graph)));
      }
    }
  }

  /**
   * @param buildTargets the build targets to generate a target graph for.
   * @param eventBus used to log events while parsing.
   * @return the target graph containing the build targets and their related targets.
   */
  public TargetGraph buildTargetGraphForBuildTargets(
      Iterable<BuildTarget> buildTargets,
      ParserConfig parserConfig,
      BuckEventBus eventBus,
      Console console,
      ImmutableMap<String, String> environment,
      boolean enableProfiling)
      throws BuildFileParseException, BuildTargetException, IOException, InterruptedException {
    return buildTargetGraphForTargetNodeSpecs(
        Iterables.transform(
            buildTargets,
            BuildTargetSpec.TO_BUILD_TARGET_SPEC),
        parserConfig,
        eventBus,
        console,
        environment,
        enableProfiling);
  }

  @Nullable
  public synchronized TargetNode<?> getTargetNode(BuildTarget buildTarget)
      throws IOException, InterruptedException {
    return state.get(buildTarget);
  }

  /**
   * Build a {@link TargetGraph} from the {@code toExplore} targets. Note that this graph isn't
   * pruned in any way and needs to be transformed into an {@link ActionGraph} before being useful
   * in a build. The TargetGraph is useful for commands such as
   * {@link com.facebook.buck.cli.AuditOwnerCommand} which only need to understand the relationship
   * between modules.
   *
   * @param toExplore the {@link BuildTarget}s that {@link TargetGraph} is calculated for.
   * @param buildFileParser the parser for build files.
   * @return a {@link TargetGraph} containing all the nodes from {@code toExplore}.
   */
  private synchronized TargetGraph buildTargetGraph(
      Iterable<BuildTarget> toExplore,
      final ParserConfig parserConfig,
      final ProjectBuildFileParser buildFileParser,
      final ImmutableMap<String, String> environment) throws IOException, InterruptedException {

    final MutableDirectedGraph<TargetNode<?>> graph = new MutableDirectedGraph<>();

    AbstractAcyclicDepthFirstPostOrderTraversal<BuildTarget> traversal =
        new AbstractAcyclicDepthFirstPostOrderTraversal<BuildTarget>() {
          @Override
          protected Iterator<BuildTarget> findChildren(BuildTarget buildTarget)
              throws IOException, InterruptedException {
            BuildTargetPatternParser buildTargetPatternParser =
                BuildTargetPatternParser.forBaseName(buildTargetParser, buildTarget.getBaseName());

            // Verify that the BuildTarget actually exists in the map of known BuildTargets
            // before trying to recurse through its children.
            TargetNode<?> targetNode = getTargetNode(buildTarget);
            if (targetNode == null) {
              throw new HumanReadableException(
                  NoSuchBuildTargetException.createForMissingBuildRule(
                      buildTarget,
                      buildTargetPatternParser,
                      parserConfig.getBuildFileName()));
            }

            Set<BuildTarget> deps = Sets.newHashSet();
            for (BuildTarget buildTargetForDep : targetNode.getDeps()) {
              try {
                TargetNode<?> depTargetNode = getTargetNode(buildTargetForDep);
                if (depTargetNode == null) {
                  parseBuildFileContainingTarget(
                      buildTargetForDep,
                      parserConfig,
                      buildFileParser,
                      environment);
                  depTargetNode = getTargetNode(buildTargetForDep);
                  if (depTargetNode == null) {
                    throw new HumanReadableException(
                        NoSuchBuildTargetException.createForMissingBuildRule(
                            buildTargetForDep,
                            BuildTargetPatternParser.forBaseName(
                                buildTargetParser,
                                buildTargetForDep.getBaseName()),
                            parserConfig.getBuildFileName()));
                  }
                }
                depTargetNode.checkVisibility(buildTarget);
                deps.add(buildTargetForDep);
              } catch (HumanReadableException | BuildTargetException | BuildFileParseException e) {
                throw new HumanReadableException(
                    e,
                    "Couldn't get dependency '%s' of target '%s':\n%s",
                    buildTargetForDep,
                    buildTarget,
                    e.getHumanReadableErrorMessage());
              }
            }

            return deps.iterator();
          }

          @Override
          protected void onNodeExplored(BuildTarget buildTarget)
              throws IOException, InterruptedException {
            TargetNode<?> targetNode = getTargetNode(buildTarget);
            Preconditions.checkNotNull(targetNode, "No target node found for %s", buildTarget);
            graph.addNode(targetNode);
            for (BuildTarget target : targetNode.getDeps()) {
              graph.addEdge(targetNode, getTargetNode(target));
            }
          }

          @Override
          protected void onTraversalComplete(Iterable<BuildTarget> nodesInExplorationOrder) {
          }
        };

    try {
      traversal.traverse(toExplore);
    } catch (AbstractAcyclicDepthFirstPostOrderTraversal.CycleException e) {
      throw new HumanReadableException(e.getMessage());
    }

    return new TargetGraph(graph);
  }

  /**
   * Note that if this Parser is populated via
   * {@link #filterAllTargetsInProject}, then this method should not be called.
   */
  private synchronized void parseBuildFileContainingTarget(
      BuildTarget buildTarget,
      ParserConfig parserConfig,
      ProjectBuildFileParser buildFileParser,
      ImmutableMap<String, String> environment)
      throws BuildFileParseException, BuildTargetException, IOException, InterruptedException {

    Repository targetRepo =
        repositoryFactory.getRepositoryByCanonicalName(buildTarget.getRepository());
    Path buildFile = targetRepo.getAbsolutePathToBuildFile(buildTarget);
    if (isCached(buildFile, parserConfig.getDefaultIncludes(), environment)) {
      throw new HumanReadableException(
          "The build file that should contain %s has already been parsed (%s), " +
              "but %s was not found. Please make sure that %s is defined in %s.",
          buildTarget,
          buildFile,
          buildTarget,
          buildTarget,
          buildFile);
    }

    parseBuildFile(buildFile, parserConfig, buildFileParser, environment);
  }

  public synchronized List<Map<String, Object>> parseBuildFile(
      Path buildFile,
      ParserConfig parserConfig,
      ImmutableMap<String, String> environment,
      Console console,
      BuckEventBus buckEventBus)
      throws BuildFileParseException, BuildTargetException, IOException, InterruptedException {
    try (ProjectBuildFileParser projectBuildFileParser = buildFileParserFactory.createParser(
        console,
        environment,
        buckEventBus)) {
      return parseBuildFile(buildFile, parserConfig, projectBuildFileParser, environment);
    }
  }

  /**
   * @param buildFile the build file to execute to generate build rules if they are not cached.
   * @param environment the environment to execute the build file in.
   * @return a list of raw build rules generated by executing the build file.
   */
  public synchronized List<Map<String, Object>> parseBuildFile(
      Path buildFile,
      ParserConfig parserConfig,
      ProjectBuildFileParser buildFileParser,
      ImmutableMap<String, String> environment)
      throws BuildFileParseException, BuildTargetException, IOException, InterruptedException {

    if (!isCached(buildFile, parserConfig.getDefaultIncludes(), environment)) {
      LOG.debug("Parsing %s file: %s", parserConfig.getBuildFileName(), buildFile);
      parseRawRulesInternal(buildFileParser.getAllRulesAndMetaRules(buildFile));
    } else {
      LOG.debug("Not parsing %s file (already in cache)", parserConfig.getBuildFileName());
    }
    return state.getRawRules(buildFile);
  }

  /**
   * @param rules the raw rule objects to parse.
   */
  @VisibleForTesting
  synchronized void parseRawRulesInternal(Iterable<Map<String, Object>> rules)
      throws BuildTargetException, IOException {
    LOG.verbose("Parsing raw rules, state before parse %s", state);
    for (Map<String, Object> map : rules) {

      if (isMetaRule(map)) {
        parseMetaRule(map);
        continue;
      }

      BuildTarget target = parseBuildTargetFromRawRule(map);
      BuildRuleType buildRuleType = parseBuildRuleTypeFromRawRule(map);
      Description<?> description = repository.getDescription(buildRuleType);
      if (description == null) {
        throw new HumanReadableException("Unrecognized rule %s while parsing %s.",
            buildRuleType,
            repository.getAbsolutePathToBuildFile(target));
      }

      state.put(target, map);
    }
    LOG.verbose("Finished parsing raw rules, state after parse %s", state);
  }

  /**
   * @param map a build rule read from a build file.
   * @return true if map represents a meta rule.
   */
  private boolean isMetaRule(Map<String, Object> map) {
    return map.containsKey(INCLUDES_META_RULE);
  }

  /**
   * Processes build file meta rules and returns true if map represents a meta rule.
   * @param map a meta rule read from a build file.
   */
  @SuppressWarnings("unchecked") // Needed for downcast from Object to List<String>.
  private synchronized boolean parseMetaRule(Map<String, Object> map) {
    Preconditions.checkState(isMetaRule(map));

    // INCLUDES_META_RULE maps to a list of file paths: the head is a
    // dependent build file and the tail is a list of the files it includes.
    List<String> fileNames = ((List<String>) map.get(INCLUDES_META_RULE));
    Preconditions.checkNotNull(fileNames);
    Path dependent = normalize(Paths.get(fileNames.get(0)));
    for (String fileName : fileNames) {
      buildFileDependents.put(normalize(Paths.get(fileName)), dependent);
    }
    return true;
  }

  /**
   * @param map the map of values that define the rule.
   * @return the type of rule defined by the map.
   */
  private BuildRuleType parseBuildRuleTypeFromRawRule(Map<String, Object> map) {
    String type = (String) map.get("type");
    return repository.getBuildRuleType(type);
  }

  /**
   * @param map the map of values that define the rule.
   * @return the build target defined by the rule.
   */
  private BuildTarget parseBuildTargetFromRawRule(Map<String, Object> map) {
    String basePath = (String) map.get("buck.base_path");
    String name = (String) map.get("name");
    return BuildTarget.builder(UnflavoredBuildTarget.BUILD_TARGET_PREFIX + basePath, name).build();
  }

  /**
   * Populates the collection of known build targets that this Parser will use to construct an
   * action graph using all build files inside the given project root and returns an optionally
   * filtered set of build targets.
   *
   * @param filesystem The project filesystem.
   * @param filter if specified, applied to each rule in rules. All matching rules will be included
   *     in the List returned by this method. If filter is null, then this method returns null.
   * @return The build targets in the project filtered by the given filter.
   */
  public synchronized ImmutableSet<BuildTarget> filterAllTargetsInProject(
      ProjectFilesystem filesystem,
      ParserConfig parserConfig,
      Predicate<TargetNode<?>> filter,
      Console console,
      ImmutableMap<String, String> environment,
      BuckEventBus buckEventBus,
      boolean enableProfiling)
      throws BuildFileParseException, BuildTargetException, IOException, InterruptedException {
    ProjectFilesystem projectFilesystem = repository.getFilesystem();
    if (!projectFilesystem.getRootPath().equals(filesystem.getRootPath())) {
      throw new HumanReadableException(String.format("Unsupported root path change from %s to %s",
          projectFilesystem.getRootPath(), filesystem.getRootPath()));
    }
    return FluentIterable
        .from(
            buildTargetGraphForTargetNodeSpecs(
                ImmutableList.of(
                    new TargetNodePredicateSpec(
                        filter,
                        filesystem.getIgnorePaths())),
                parserConfig,
                buckEventBus,
                console,
                environment,
                enableProfiling).getNodes())
        .filter(filter)
        .transform(HasBuildTarget.TO_TARGET)
        .toSet();
  }


  /**
   * Called when a new command is executed and used to signal to the BuildFileTreeCache
   * that reconstructing the build file tree may result in a different BuildFileTree.
   */
  @Subscribe
  public synchronized void onCommandStartedEvent(BuckEvent event) {
    // Ideally, the type of event would be CommandEvent.Started, but that would introduce
    // a dependency on com.facebook.buck.cli.
    Preconditions.checkArgument(
        event.getEventName().equals("CommandStarted"),
        "event should be of type CommandEvent.Started, but was: %s.",
        event);
    buildFileTreeCache.onCommandStartedEvent(event);
  }

  /**
   * Called when file change events are posted to the file change EventBus to invalidate cached
   * build rules if required. {@link Path}s contained within events must all be relative to the
   * {@link ProjectFilesystem} root.
   */
  @Subscribe
  public synchronized void onFileSystemChange(WatchEvent<?> event) throws IOException {
    if (LOG.isVerboseEnabled()) {
      LOG.verbose(
          "Parser watched event %s %s",
          event.kind(),
          repository.getFilesystem().createContextString(event));
    }

    if (repository.getFilesystem().isPathChangeEvent(event)) {
      Path path = (Path) event.context();

      if (isPathCreateOrDeleteEvent(event)) {

        if (path.endsWith(new ParserConfig(repository.getBuckConfig()).getBuildFileName())) {

          // If a build file has been added or removed, reconstruct the build file tree.
          buildFileTreeCache.invalidateIfStale();
        }

        // Added or removed files can affect globs, so invalidate the package build file
        // "containing" {@code path} unless its filename matches a temp file pattern.
        if (!isTempFile(path)) {
          invalidateContainingBuildFile(path);
        }
      }

      LOG.verbose("Invalidating dependents for path %s, cache state %s", path, state);

      // Invalidate the raw rules and targets dependent on this file.
      state.invalidateDependents(path);

    } else {
      // Non-path change event, likely an overflow due to many change events: invalidate everything.
      LOG.debug("Parser invalidating entire cache on overflow.");
      buildFileTreeCache.invalidateIfStale();
      invalidateCache();
    }
  }

  /**
   * @param path The {@link Path} to test.
   * @return true if {@code path} is a temporary or backup file.
   */
  private boolean isTempFile(Path path) {
    final String fileName = path.getFileName().toString();
    Predicate<Pattern> patternMatches = new Predicate<Pattern>() {
      @Override
      public boolean apply(Pattern pattern) {
        return pattern.matcher(fileName).matches();
      }
    };
    return Iterators.any(tempFilePatterns.iterator(), patternMatches);
  }

  /**
   * Finds the build file responsible for the given {@link Path} and invalidates
   * all of the cached rules dependent on it.
   * @param path A {@link Path}, relative to the project root and "contained"
   *             within the build file to find and invalidate.
   */
  private synchronized void invalidateContainingBuildFile(Path path) throws IOException {
    Optional<Path> packageBuildFile = buildFileTreeCache.get().getBasePathOfAncestorTarget(path);
    if (!packageBuildFile.isPresent()) {
      return;
    }
    state.invalidateDependents(
        repository.getFilesystem().getPathForRelativePath(
            packageBuildFile.get().resolve(
                new ParserConfig(repository.getBuckConfig()).getBuildFileName())));
  }

  private boolean isPathCreateOrDeleteEvent(WatchEvent<?> event) {
    return event.kind() == StandardWatchEventKinds.ENTRY_CREATE ||
        event.kind() == StandardWatchEventKinds.ENTRY_DELETE;
  }

  /**
   * Always use Files created from absolute paths as they are returned from buck.py and must be
   * created from consistent paths to be looked up correctly in maps.
   * @param path A File to normalize.
   * @return An equivalent file constructed from a normalized, absolute path to the given File.
   */
  private Path normalize(Path path) {
    return repository.getFilesystem().resolve(path);
  }

  /**
   * Record the parse start time, which should include the WatchEvent processing that occurs
   * before the BuildTargets required to build a full ParseStart event are known.
   */
  public void recordParseStartTime(BuckEventBus eventBus) {
    class ParseStartTime extends AbstractBuckEvent {

      @Override
      protected String getValueString() {
        return "Timestamp.";
      }

      @Override
      public boolean isRelatedTo(BuckEvent event) {
        return false;
      }

      @Override
      public String getEventName() {
        return "ParseStartTime";
      }
    }
    parseStartEvent = Optional.<BuckEvent>of(new ParseStartTime());
    eventBus.timestamp(parseStartEvent.get());
  }

  /**
   * @return an Optional BuckEvent timestamped with the parse start time.
   */
  public Optional<BuckEvent> getParseStartTime() {
    return parseStartEvent;
  }

  /**
   * Post a ParseStart event to eventBus, using the start of WatchEvent processing as the start
   * time if applicable.
   */
  private void postParseStartEvent(Iterable<BuildTarget> buildTargets, BuckEventBus eventBus) {
    if (parseStartEvent.isPresent()) {
      eventBus.post(ParseEvent.started(buildTargets), parseStartEvent.get());
    } else {
      eventBus.post(ParseEvent.started(buildTargets));
    }
  }

  private class CachedState {

    /**
     * The build files that have been parsed and whose build rules are in
     * {@link #memoizedTargetNodes}.
     */
    private final ListMultimap<Path, Map<String, Object>> parsedBuildFiles;

    /**
     * Cache of (symlink path: symlink target) pairs used to avoid repeatedly
     * checking for the existence of symlinks in the source tree.
     */
    private final Map<Path, Path> symlinkExistenceCache;

    /**
     * Build rule input files (e.g., paths in {@code srcs}) whose
     * paths contain an element which exists in {@code symlinkExistenceCache}.
     *
     * Used to invalidate build rules in {@code cleanCache} if their
     * inputs contain any files in this set.
     */
    private final Set<Path> buildInputPathsUnderSymlink;

    /**
     * Map from build file path to targets generated by that file.
     */
    private final ListMultimap<Path, BuildTarget> pathsToBuildTargets;

    /**
     * We parse a build file in search for one particular rule; however, we also keep track of the
     * other rules that were also parsed from it.
     */
    private final Map<BuildTarget, TargetNode<?>> memoizedTargetNodes;

    /**
     * Environment used by build files. If the environment is changed, then build files need to be
     * reevaluated with the new environment, so the environment used when populating the rule cache
     * is stored between requests to parse build files and the cache is invalidated and build files
     * reevaluated if the environment changes.
     */
    @Nullable
    private ImmutableMap<String, String> cacheEnvironment;

    /**
     * Files included by build files. If the default includes are changed, then build files need to
     * be reevaluated with the new includes, so the includes used when populating the rule cache are
     * stored between requests to parse build files and the cache is invalidated and build files
     * reevaluated if the includes change.
     */
    @Nullable
    private List<String> cacheDefaultIncludes;

    private final Map<BuildTarget, Path> targetsToFile;

    private final LoadingCache<BuildTarget, HashCode> buildTargetHashCodeCache;

    private final String buildFileName;

    public CachedState(String buildFileName) {
      this.memoizedTargetNodes = Maps.newHashMap();
      this.symlinkExistenceCache = Maps.newHashMap();
      this.buildInputPathsUnderSymlink = Sets.newHashSet();
      this.parsedBuildFiles = ArrayListMultimap.create();
      this.targetsToFile = Maps.newHashMap();
      this.pathsToBuildTargets = ArrayListMultimap.create();
      this.buildTargetHashCodeCache = CacheBuilder.newBuilder().build(
          new CacheLoader<BuildTarget, HashCode>() {
            @Override
            public HashCode load(BuildTarget buildTarget) throws IOException, InterruptedException {
              return loadHashCodeForBuildTarget(buildTarget);
            }
          });
      this.buildFileName = buildFileName;
    }

    public void invalidateAll() {
      LOG.debug("Invalidating all cached data.");
      parsedBuildFiles.clear();
      symlinkExistenceCache.clear();
      buildInputPathsUnderSymlink.clear();
      memoizedTargetNodes.clear();
      targetsToFile.clear();
      pathsToBuildTargets.clear();
      buildTargetHashCodeCache.invalidateAll();
    }

    @Override
    public String toString() {
      return String.format(
          "%s memoized=%s symlinks=%s build files under symlink=%s parsed=%s targets-to-files=%s " +
          "paths-to-targets=%s build-target-hash-code-cache=%s",
          super.toString(),
          memoizedTargetNodes,
          symlinkExistenceCache,
          buildInputPathsUnderSymlink,
          parsedBuildFiles,
          targetsToFile,
          pathsToBuildTargets,
          buildTargetHashCodeCache);
    }

    /**
     * Invalidates the cached build rules if {@code environment} has changed since the last call.
     * If the cache is invalidated the new {@code environment} used to build the new cache is
     * stored.
     *
     * @param environment the environment to execute the build file in.
     * @return true if the cache was invalidated, false if the cache is still valid.
     */
    private synchronized boolean invalidateCacheOnEnvironmentChange(
        ImmutableMap<String, String> environment) {
      if (!environment.equals(cacheEnvironment)) {
        if (cacheEnvironment != null) {
          LOG.warn(
              "Environment variables changed (%s). Discarding cache to avoid effects on build. " +
              "This will make builds very slow.",
              Maps.difference(cacheEnvironment, environment));
        }
        invalidateCache();
        this.cacheEnvironment = environment;
        return true;
      }
      return false;
    }

    /**
     * Invalidates the cached build rules if {@code includes} have changed since the last call.
     * If the cache is invalidated the new {@code includes} used to build the new cache are stored.
     *
     * @param includes the files to include before executing the build file.
     * @return true if the cache was invalidated, false if the cache is still valid.
     */
    private synchronized boolean invalidateCacheOnIncludeChange(Iterable<String> includes) {
      List<String> includesList = Lists.newArrayList(includes);
      if (!includesList.equals(this.cacheDefaultIncludes)) {
        LOG.debug("Parser invalidating entire cache on default include change.");
        invalidateCache();
        this.cacheDefaultIncludes = includesList;
        return true;
      }
      return false;
    }

    /**
     * Remove the targets and rules defined by {@code path} from the cache and recursively remove
     * the targets and rules defined by files that transitively include {@code path} from the cache.
     * @param path The File that has changed.
     */
    synchronized void invalidateDependents(Path path) {
      // Normalize path to ensure it hashes equally with map keys.
      path = normalize(path);

      // The path may have changed from being a symlink to not being a symlink.
      symlinkExistenceCache.remove(path);

      if (parsedBuildFiles.containsKey(path)) {
        LOG.debug("Parser invalidating %s cache", path);

        // Remove all rules defined in path from cache.
        List<?> removed = parsedBuildFiles.removeAll(path);
        LOG.verbose("Removed parsed build files %s defined by %s", removed, path);

        // If this build file contained inputs under a symlink, we'll be reparsing
        // it, so forget that.
        buildInputPathsUnderSymlink.remove(path);
      } else {
        LOG.debug("Parsed build files does not contain %s, not invalidating", path);
      }

      List<BuildTarget> targetsToRemove = pathsToBuildTargets.get(path);
      LOG.debug("Removing targets %s for path %s", targetsToRemove, path);
      for (BuildTarget target : targetsToRemove) {
        memoizedTargetNodes.remove(target);
      }
      buildTargetHashCodeCache.invalidateAll(targetsToRemove);
      pathsToBuildTargets.removeAll(path);

      List<Path> dependents = buildFileDependents.get(path);
      LOG.verbose("Invalidating dependents %s of path %s", dependents, path);
      // Recursively invalidate dependents.
      for (Path dependent : dependents) {

        if (!dependent.equals(path)) {
          invalidateDependents(dependent);
        }
      }

      // Dependencies will be repopulated when files are re-parsed.
      List<?> removedDependents = buildFileDependents.removeAll(path);
      LOG.verbose("Removed build file dependents %s defined by %s", removedDependents, path);
    }

    public boolean isParsed(Path buildFile) {
      return parsedBuildFiles.containsKey(normalize(buildFile));
    }

    public List<Map<String, Object>> getRawRules(Path buildFile) {
      return Preconditions.checkNotNull(parsedBuildFiles.get(normalize(buildFile)));
    }

    public void put(BuildTarget target, Map<String, Object> rawRules) {
      Path normalized = normalize(target.getBasePath().resolve(buildFileName));
      LOG.verbose("Adding rules for parsed build file %s", normalized);
      parsedBuildFiles.put(normalized, rawRules);

      targetsToFile.put(
          target,
          normalize(Paths.get((String) rawRules.get("buck.base_path")))
              .resolve(buildFileName).toAbsolutePath());
    }

    @Nullable
    @SuppressWarnings({"rawtypes", "unchecked"})
    public TargetNode<?> get(BuildTarget buildTarget) throws IOException, InterruptedException {
      // Fast path.
      TargetNode<?> toReturn = memoizedTargetNodes.get(buildTarget);
      if (toReturn != null) {
        return toReturn;
      }

      Repository targetRepo =
          repositoryFactory.getRepositoryByCanonicalName(buildTarget.getRepository());
      Path buildFilePath;
      try {
        buildFilePath = targetRepo.getAbsolutePathToBuildFile(buildTarget);
      } catch (Repository.MissingBuildFileException e) {
        throw new HumanReadableException(e);
      }
      UnflavoredBuildTarget unflavored = buildTarget.getUnflavoredBuildTarget();
      List<Map<String, Object>> rules = state.getRawRules(buildFilePath);
      for (Map<String, Object> map : rules) {

        if (!buildTarget.getShortName().equals(map.get("name"))) {
          continue;
        }

        BuildRuleType buildRuleType = parseBuildRuleTypeFromRawRule(map);
        targetsToFile.put(
            BuildTarget.of(unflavored),
            normalize(Paths.get((String) map.get("buck.base_path")))
                .resolve(buildFileName).toAbsolutePath());

        Description<?> description = repository.getDescription(buildRuleType);
        if (description == null) {
          throw new HumanReadableException("Unrecognized rule %s while parsing %s%s.",
              buildRuleType,
              UnflavoredBuildTarget.BUILD_TARGET_PREFIX,
              unflavored.getBasePath().resolve(buildFileName));
        }

        if (buildTarget.isFlavored()) {
          if (description instanceof Flavored) {
            if (!((Flavored) description).hasFlavors(
                    ImmutableSet.copyOf(buildTarget.getFlavors()))) {
              throw new HumanReadableException(
                  "Unrecognized flavor in target %s while parsing %s%s.",
                  buildTarget,
                  UnflavoredBuildTarget.BUILD_TARGET_PREFIX,
                  buildTarget.getBasePath().resolve(buildFileName));
            }
          } else {
            LOG.warn(
                "Target %s (type %s) must implement the Flavored interface " +
                "before we can check if it supports flavors: %s",
                buildTarget.getUnflavoredBuildTarget(),
                buildRuleType,
                buildTarget.getFlavors());
            throw new HumanReadableException(
                "Target %s (type %s) does not currently support flavors (tried %s)",
                buildTarget.getUnflavoredBuildTarget(),
                buildRuleType,
                buildTarget.getFlavors());
          }
        }

        this.pathsToBuildTargets.put(buildFilePath, buildTarget);

        BuildRuleFactoryParams factoryParams = new BuildRuleFactoryParams(
            targetRepo.getFilesystem(),
            targetRepo.getBuildTargetParser(),
            // Although we store the rule by its unflavoured name, when we construct it, we need the
            // flavour.
            buildTarget,
            ruleKeyBuilderFactory,
            buildFileTreeCache.get(),
            enforceBuckPackageBoundary);
        Object constructorArg = description.createUnpopulatedConstructorArg();
        TargetNode<?> targetNode;
        try {
          ImmutableSet.Builder<BuildTarget> declaredDeps = ImmutableSet.builder();
          ImmutableSet.Builder<BuildTargetPattern> visibilityPatterns = ImmutableSet.builder();
          marshaller.populate(
              targetRepo.getFilesystem(),
              factoryParams,
              constructorArg,
              declaredDeps,
              visibilityPatterns,
              map);
          targetNode = new TargetNode(
              description,
              constructorArg,
              factoryParams,
              declaredDeps.build(),
              visibilityPatterns.build());
        } catch (NoSuchBuildTargetException | TargetNode.InvalidSourcePathInputException e) {
          throw new HumanReadableException(e);
        } catch (ConstructorArgMarshalException e) {
          throw new HumanReadableException("%s: %s", buildTarget, e.getMessage());
        }

        Map<Path, Path> newSymlinksEncountered = Maps.newHashMap();
        if (inputFilesUnderSymlink(
                targetNode.getInputs(),
                targetRepo.getFilesystem(),
                symlinkExistenceCache,
                newSymlinksEncountered)) {
          LOG.warn(
              "Disabling caching for target %s, because one or more input files are under a " +
              "symbolic link (%s). This will severely impact performance! To resolve this, use " +
              "separate rules and declare dependencies instead of using symbolic links.",
              targetNode.getBuildTarget(),
              newSymlinksEncountered);
          buildInputPathsUnderSymlink.add(buildFilePath);
        }
        TargetNode<?> existingTargetNode = memoizedTargetNodes.put(buildTarget, targetNode);
        if (existingTargetNode != null) {
          throw new HumanReadableException("Duplicate definition for " + unflavored);
        }

        // PMD considers it bad form to return while in a loop.
      }

      return memoizedTargetNodes.get(buildTarget);
    }

    public synchronized void cleanCache() {
      LOG.debug(
          "Cleaning cache of build files with inputs under symlink %s",
          buildInputPathsUnderSymlink);
      Set<Path> buildInputPathsUnderSymlinkCopy = new HashSet<>(buildInputPathsUnderSymlink);
      buildInputPathsUnderSymlink.clear();
      for (Path buildFilePath : buildInputPathsUnderSymlinkCopy) {
        invalidateDependents(buildFilePath);
      }
    }

    private synchronized HashCode loadHashCodeForBuildTarget(BuildTarget buildTarget)
        throws IOException, InterruptedException{
      // Warm up the cache.
      get(buildTarget);

      Path buildTargetPath = targetsToFile.get(
          BuildTarget.of(buildTarget.getUnflavoredBuildTarget()));
      if (buildTargetPath == null) {
        throw new HumanReadableException("Couldn't find build target %s", buildTarget);
      }
      List<Map<String, Object>> rules = getRawRules(buildTargetPath);
      Hasher hasher = Hashing.sha1().newHasher();
      for (Map<String, Object> map : rules) {
        if (!buildTarget.getShortName().equals(map.get("name"))) {
          continue;
        }

        JsonObjectHashing.hashJsonObject(hasher, map);
      }
      return hasher.hash();
    }

    public LoadingCache<BuildTarget, HashCode> getBuildTargetHashCodeCache() {
      return buildTargetHashCodeCache;
    }
  }

  private static boolean inputFilesUnderSymlink(
      // We use Collection<Path> instead of Iterable<Path> to prevent
      // accidentally passing in Path, since Path itself is Iterable<Path>.
      Collection<Path> inputs,
      ProjectFilesystem projectFilesystem,
      Map<Path, Path> symlinkExistenceCache,
      Map<Path, Path> newSymlinksEncountered) throws IOException {
    boolean result = false;
    for (Path input : inputs) {
      for (int i = 1; i < input.getNameCount(); i++) {
        Path subpath = input.subpath(0, i);
        Path resolvedSymlink = symlinkExistenceCache.get(subpath);
        if (resolvedSymlink != null) {
          newSymlinksEncountered.put(subpath, resolvedSymlink);
          result = true;
        } else if (projectFilesystem.isSymLink(subpath)) {
          try {
            resolvedSymlink = projectFilesystem.getRootPath().relativize(subpath.toRealPath());
            LOG.debug("Detected symbolic link %s -> %s", subpath, resolvedSymlink);
            newSymlinksEncountered.put(subpath, resolvedSymlink);
            symlinkExistenceCache.put(subpath, resolvedSymlink);
          } catch (NoSuchFileException e) {
            LOG.verbose(e, "No such file detecting symlink at %s", subpath);
          } catch (IOException e) {
            LOG.error(e, "Couldn't detect symbolic link at %s", subpath);
          }
          result = true;
        }
      }
    }
    return result;
  }

}
