// Copyright 2018 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.includescanning;

import com.google.common.base.Preconditions;
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.util.concurrent.ListenableFuture;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.ArtifactFactory;
import com.google.devtools.build.lib.analysis.BlazeDirectories;
import com.google.devtools.build.lib.includescanning.IncludeParser.Inclusion;
import com.google.devtools.build.lib.rules.cpp.IncludeScanner;
import com.google.devtools.build.lib.rules.cpp.IncludeScanner.IncludeScannerSupplier;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService;

/** IncludeScannerSupplier implementation. */
public class IncludeScannerSupplierImpl implements IncludeScannerSupplier {
  private static class IncludeScannerParams {
    final List<PathFragment> quoteIncludePaths;
    final List<PathFragment> includePaths;
    final List<PathFragment> frameworkIncludePaths;

    IncludeScannerParams(
        List<PathFragment> quoteIncludePaths,
        List<PathFragment> includePaths,
        List<PathFragment> frameworkIncludePaths) {
      this.quoteIncludePaths = quoteIncludePaths;
      this.includePaths = includePaths;
      this.frameworkIncludePaths = frameworkIncludePaths;
    }

    @Override
    public int hashCode() {
      return Objects.hash(quoteIncludePaths, includePaths, frameworkIncludePaths);
    }

    @Override
    public boolean equals(Object other) {
      if (this == other) {
        return true;
      }
      if (!(other instanceof IncludeScannerParams)) {
        return false;
      }
      IncludeScannerParams that = (IncludeScannerParams) other;
      return this.quoteIncludePaths.equals(that.quoteIncludePaths)
          && this.includePaths.equals(that.includePaths)
          && this.frameworkIncludePaths.equals(that.frameworkIncludePaths);
    }
  }

  private final BlazeDirectories directories;
  private final ExecutorService includePool;
  private final ArtifactFactory artifactFactory;

  private IncludeParser includeParser;

  /**
   * Cache of include scan results mapping source paths to sets of scanned inclusions. Shared by all
   * scanner instances.
   */
  private final ConcurrentMap<Artifact, ListenableFuture<Collection<Inclusion>>> includeParseCache =
      new ConcurrentHashMap<>();

  /** Map of grepped include files from input (.cc or .h) to a header-grepped file. */
  private final PathExistenceCache pathCache;

  private final Supplier<SpawnIncludeScanner> spawnIncludeScannerSupplier;
  private final Path execRoot;
  private final boolean useAsyncIncludeScanner;

  /** Cache of include scanner instances mapped by include-path hashes. */
  private final LoadingCache<IncludeScannerParams, IncludeScanner> scanners =
      CacheBuilder.newBuilder()
          .build(
              new CacheLoader<IncludeScannerParams, IncludeScanner>() {
                @Override
                public IncludeScanner load(IncludeScannerParams key) {
                  return new LegacyIncludeScanner(
                      includeParser,
                      includePool,
                      includeParseCache,
                      pathCache,
                      key.quoteIncludePaths,
                      key.includePaths,
                      key.frameworkIncludePaths,
                      directories.getOutputPath(execRoot.getBaseName()),
                      execRoot,
                      artifactFactory,
                      spawnIncludeScannerSupplier,
                      useAsyncIncludeScanner);
                }
              });

  public IncludeScannerSupplierImpl(
      BlazeDirectories directories,
      ExecutorService includePool,
      ArtifactFactory artifactFactory,
      Supplier<SpawnIncludeScanner> spawnIncludeScannerSupplier,
      Path execRoot,
      boolean useAsyncIncludeScanner) {
    this.directories = directories;
    this.includePool = includePool;
    this.artifactFactory = artifactFactory;
    this.spawnIncludeScannerSupplier = spawnIncludeScannerSupplier;
    this.execRoot = execRoot;
    this.pathCache = new PathExistenceCache(execRoot, artifactFactory);
    this.useAsyncIncludeScanner = useAsyncIncludeScanner;
  }

  @Override
  public IncludeScanner scannerFor(
      List<PathFragment> quoteIncludePaths,
      List<PathFragment> includePaths,
      List<PathFragment> frameworkPaths) {
    Preconditions.checkNotNull(includeParser);
    return scanners.getUnchecked(
        new IncludeScannerParams(quoteIncludePaths, includePaths, frameworkPaths));
  }

  public void init(IncludeParser includeParser) {
    Preconditions.checkState(
        this.includeParser == null,
        "Must only be initialized once: %s %s",
        this.includeParser,
        includeParser);
    Preconditions.checkState(includeParseCache.isEmpty(), includeParseCache);
    Preconditions.checkState(scanners.asMap().isEmpty(), scanners);
    this.includeParser = Preconditions.checkNotNull(includeParser);
    if (this.includeParser.getHints() != null) {
      // The Hints object lives across the lifetime of the Blaze server, but its cached hints may
      // be stale.
      this.includeParser.getHints().clearCachedLegacyHints();
    }
  }
}
