// Copyright 2014 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.pkgcache;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.base.Verify;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.PackageIdentifier;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.EventHandler;
import com.google.devtools.build.lib.packages.BuildFileNotFoundException;
import com.google.devtools.build.lib.packages.NoSuchPackageException;
import com.google.devtools.build.lib.vfs.FileStatus;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.lib.vfs.Symlinks;
import com.google.devtools.build.lib.vfs.UnixGlob;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;

/**
 * A mapping from the name of a package to the location of its BUILD file.
 * The implementation composes an ordered sequence of directories according to
 * the package-path rules.
 *
 * <p>All methods are thread-safe, and (assuming no change to the underlying
 * filesystem) idempotent.
 */
public class PathPackageLocator implements Serializable {
  private static final PathFragment BUILD_PATH_FRAGMENT = PathFragment.create("BUILD");

  public static final ImmutableSet<String> DEFAULT_TOP_LEVEL_EXCLUDES =
      ImmutableSet.of("experimental");

  private final ImmutableList<Path> pathEntries;
  // Transient because this is an injected value in Skyframe, and as such, its serialized
  // representation is used as a key. We want a change to output base not to invalidate things.
  private final transient Path outputBase;

  public static final PathPackageLocator EMPTY =
      new PathPackageLocator(null, ImmutableList.<Path>of());

  @VisibleForTesting
  public PathPackageLocator(Path outputBase, List<Path> pathEntries) {
    this.outputBase = outputBase;
    this.pathEntries = ImmutableList.copyOf(pathEntries);
  }

  /**
   * Constructs a PathPackageLocator based on the specified list of package root directories.
   */
  @VisibleForTesting
  public PathPackageLocator(Path... pathEntries) {
    this(null, Arrays.asList(pathEntries));
  }

  /**
   * Returns the path to the build file for this package.
   *
   * <p>The package's root directory may be computed by calling getParentFile()
   * on the result of this function.
   *
   * <p>Instances of this interface do not attempt to do any caching, nor
   * implement checks for package-boundary crossing logic; the PackageCache
   * does that.
   *
   * <p>If the same package exists beneath multiple package path entries, the
   * first path that matches always wins.
   */
  public Path getPackageBuildFile(PackageIdentifier packageName) throws NoSuchPackageException {
    Path buildFile  = getPackageBuildFileNullable(packageName, UnixGlob.DEFAULT_SYSCALLS_REF);
    if (buildFile == null) {
      throw new BuildFileNotFoundException(packageName, "BUILD file not found on package path");
    }
    return buildFile;
  }

  /**
   * Like #getPackageBuildFile(), but returns null instead of throwing.
   *  @param packageIdentifier the name of the package.
   * @param cache a filesystem-level cache of stat() calls.
   */
  public Path getPackageBuildFileNullable(PackageIdentifier packageIdentifier,
      AtomicReference<? extends UnixGlob.FilesystemCalls> cache)  {
    Preconditions.checkArgument(!packageIdentifier.getRepository().isDefault());
    if (packageIdentifier.getRepository().isMain()) {
      return getFilePath(
          packageIdentifier.getPackageFragment().getRelative(BUILD_PATH_FRAGMENT), cache);
    } else {
      Verify.verify(outputBase != null, String.format(
          "External package '%s' needs to be loaded but this PathPackageLocator instance does not "
              + "support external packages", packageIdentifier));
      // This works only to some degree, because it relies on the presence of the repository under
      // $OUTPUT_BASE/external, which is created by the appropriate RepositoryDirectoryValue. This
      // is true for the invocation in GlobCache, but not for the locator.getBuildFileForPackage()
      // invocation in Parser#include().
      Path buildFile = outputBase.getRelative(
          packageIdentifier.getSourceRoot()).getRelative(BUILD_PATH_FRAGMENT);
      try {
        FileStatus stat = cache.get().statIfFound(buildFile, Symlinks.FOLLOW);
        if (stat != null && stat.isFile()) {
          return buildFile;
        } else {
          return null;
        }
      } catch (IOException e) {
        return null;
      }
    }
  }


  /**
   * Returns an immutable ordered list of the directories on the package path.
   */
  public ImmutableList<Path> getPathEntries() {
    return pathEntries;
  }

  @Override
  public String toString() {
    return "PathPackageLocator" + pathEntries;
  }

  /**
   * A factory of PathPackageLocators from a list of path elements.  Elements
   * may contain "%workspace%", indicating the workspace.
   *
   * @param outputBase the output base. Can be null if remote repositories are not in use.
   * @param pathElements Each element must be an absolute path, relative path,
   *                     or some string "%workspace%" + relative, where relative is itself a
   *                     relative path.  The special symbol "%workspace%" means to interpret
   *                     the path relative to the nearest enclosing workspace.  Relative
   *                     paths are interpreted relative to the client's working directory,
   *                     which may be below the workspace.
   * @param eventHandler The eventHandler.
   * @param workspace The nearest enclosing package root directory.
   * @param clientWorkingDirectory The client's working directory.
   * @param checkExistence If true, verify that the element exists before adding it to the locator.
   * @return a list of {@link Path}s.
   */
  public static PathPackageLocator create(Path outputBase,
                                          List<String> pathElements,
                                          EventHandler eventHandler,
                                          Path workspace,
                                          Path clientWorkingDirectory,
                                          boolean checkExistence) {
    List<Path> resolvedPaths = new ArrayList<>();
    final String workspaceWildcard = "%workspace%";

    for (String pathElement : pathElements) {
      // Replace "%workspace%" with the path of the enclosing workspace directory.
      pathElement = pathElement.replace(workspaceWildcard, workspace.getPathString());

      PathFragment pathElementFragment = PathFragment.create(pathElement);

      // If the path string started with "%workspace%" or "/", it is already absolute,
      // so the following line is a no-op.
      Path rootPath = clientWorkingDirectory.getRelative(pathElementFragment);

      if (!pathElementFragment.isAbsolute() && !clientWorkingDirectory.equals(workspace)) {
        eventHandler.handle(
            Event.warn("The package path element '" + pathElementFragment + "' will be "
                + "taken relative to your working directory. You may have intended "
                + "to have the path taken relative to your workspace directory. "
                + "If so, please use the '" + workspaceWildcard + "' wildcard."));
      }

      if (!checkExistence || rootPath.exists()) {
        resolvedPaths.add(rootPath);
      }
    }

    return new PathPackageLocator(outputBase, resolvedPaths);
  }

    /**
     * A factory of PathPackageLocators from a list of path elements.  Elements
     * may contain "%workspace%", indicating the workspace.
     *
     * @param outputBase the output base. Can be null if remote repositories are not in use.
     * @param pathElements Each element must be an absolute path, relative path,
     *                     or some string "%workspace%" + relative, where relative is itself a
     *                     relative path.  The special symbol "%workspace%" means to interpret
     *                     the path relative to the nearest enclosing workspace.  Relative
     *                     paths are interpreted relative to the client's working directory,
     *                     which may be below the workspace.
     * @param eventHandler The eventHandler.
     * @param workspace The nearest enclosing package root directory.
     * @param clientWorkingDirectory The client's working directory.
     * @return a list of {@link Path}s.
     */
    public static PathPackageLocator create(Path outputBase,
            List<String> pathElements, EventHandler eventHandler, Path workspace,
            Path clientWorkingDirectory) {
        return create(outputBase, pathElements, eventHandler, workspace, clientWorkingDirectory,
                /*checkExistence=*/true);
    }

  /**
   * Returns the path to the WORKSPACE file for this build.
   *
   * <p>If there are WORKSPACE files beneath multiple package path entries, the first one always
   * wins.
   */
  public Path getWorkspaceFile() {
    AtomicReference<? extends UnixGlob.FilesystemCalls> cache = UnixGlob.DEFAULT_SYSCALLS_REF;
    // TODO(bazel-team): correctness in the presence of changes to the location of the WORKSPACE
    // file.
    return getFilePath(Label.WORKSPACE_FILE_NAME, cache);
  }

  private Path getFilePath(PathFragment suffix,
      AtomicReference<? extends UnixGlob.FilesystemCalls> cache) {
    for (Path pathEntry : pathEntries) {
      Path buildFile = pathEntry.getRelative(suffix);
      try {
        FileStatus stat = cache.get().statIfFound(buildFile, Symlinks.FOLLOW);
        if (stat != null && stat.isFile()) {
          return buildFile;
        }
      } catch (IOException ignored) {
        // Treat IOException as a missing file.
      }
    }
    return null;
  }

  @Override
  public int hashCode() {
    return Objects.hash(pathEntries, outputBase);
  }

  @Override
  public boolean equals(Object other) {
    if (this == other) {
      return true;
    }
    if (!(other instanceof PathPackageLocator)) {
      return false;
    }
    PathPackageLocator pathPackageLocator = (PathPackageLocator) other;
    return Objects.equals(getPathEntries(), pathPackageLocator.getPathEntries())
        && Objects.equals(outputBase, pathPackageLocator.outputBase);
  }

  public Path getOutputBase() {
    return outputBase;
  }
}
