// 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;

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

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

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

  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,
                      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) {
    Preconditions.checkNotNull(includeParser);
    return scanners.getUnchecked(new IncludeScannerParams(quoteIncludePaths, includePaths));
  }

  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();
    }
  }
}
