// 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.devtools.build.lib.cmdline.LabelConstants;
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.BuildFileName;
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.Root;
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.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 String WORKSPACE_WILDCARD = "%workspace%";

  private final ImmutableList<Root> 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;

  private final ImmutableList<BuildFileName> buildFilesByPriority;

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

  /**
   * 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.
   * @return the {@link Path} to the correct build file, or {@code null} if none was found
   */
  public Path getPackageBuildFileNullable(
      PackageIdentifier packageIdentifier,
      AtomicReference<? extends UnixGlob.FilesystemCalls> cache) {
    Preconditions.checkArgument(!packageIdentifier.getRepository().isDefault());
    if (packageIdentifier.getRepository().isMain()) {
      for (BuildFileName buildFileName : buildFilesByPriority) {
        Path buildFilePath =
            getFilePath(
                packageIdentifier
                    .getPackageFragment()
                    .getRelative(buildFileName.getFilenameFragment()),
                cache);
        if (buildFilePath != null) {
          return buildFilePath;
        }
      }
    } 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().
      for (BuildFileName buildFileName : buildFilesByPriority) {
        Path buildFile =
            outputBase
                .getRelative(packageIdentifier.getSourceRoot())
                .getRelative(buildFileName.getFilenameFragment());
        try {
          FileStatus stat = cache.get().statIfFound(buildFile, Symlinks.FOLLOW);
          if (stat != null && stat.isFile()) {
            return buildFile;
          }
        } catch (IOException e) {
          return null;
        }
      }
    }

    return null;
  }

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

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

  public static String maybeReplaceWorkspaceInString(String pathElement, Path workspace) {
    return pathElement.replace(WORKSPACE_WILDCARD, workspace.getPathString());
  }
  /**
   * A factory of PathPackageLocators from a list of path elements. Elements may contain
   * "%workspace%", indicating the workspace.
   *
   * <p>If any of the paths given do not exist, an exception will be thrown.
   *
   * @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 buildFilesByPriority The ordered collection of {@link BuildFileName}s to check in each
   *     potential package directory.
   * @return a {@link PathPackageLocator} that uses the {@code outputBase} and {@code pathElements}
   *     provided.
   */
  public static PathPackageLocator create(
      Path outputBase,
      List<String> pathElements,
      EventHandler eventHandler,
      Path workspace,
      Path clientWorkingDirectory,
      List<BuildFileName> buildFilesByPriority) {
    return createInternal(
        outputBase,
        pathElements,
        eventHandler,
        workspace,
        clientWorkingDirectory,
        buildFilesByPriority,
        true);
  }

  /**
   * A factory of PathPackageLocators from a list of path elements.
   *
   * @param outputBase the output base. Can be null if remote repositories are not in use.
   * @param pathElements Each element must be a {@link Root} object.
   * @param buildFilesByPriority The ordered collection of {@link BuildFileName}s to check in each
   *     potential package directory.
   * @return a {@link PathPackageLocator} that uses the {@code outputBase} and {@code pathElements}
   *     provided.
   */
  public static PathPackageLocator createWithoutExistenceCheck(
      Path outputBase, List<Root> pathElements, List<BuildFileName> buildFilesByPriority) {
    return new PathPackageLocator(outputBase, pathElements, buildFilesByPriority);
  }

  private static PathPackageLocator createInternal(
      Path outputBase,
      List<String> pathElements,
      EventHandler eventHandler,
      Path workspace,
      Path clientWorkingDirectory,
      List<BuildFileName> buildFilesByPriority,
      boolean checkExistence) {
    List<Root> resolvedPaths = new ArrayList<>();

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

      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 '"
                    + WORKSPACE_WILDCARD
                    + "' wildcard."));
      }

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

    return new PathPackageLocator(outputBase, resolvedPaths, buildFilesByPriority);
  }

  /**
   * 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(LabelConstants.WORKSPACE_FILE_NAME, cache);
  }

  private Path getFilePath(PathFragment suffix,
      AtomicReference<? extends UnixGlob.FilesystemCalls> cache) {
    for (Root 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;
  }
}
