// 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.analysis.config;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Predicates.not;
import static java.util.stream.Collectors.joining;

import com.google.common.base.Strings;
import com.google.common.collect.ImmutableSortedMap;
import com.google.devtools.build.lib.actions.ArtifactRoot;
import com.google.devtools.build.lib.actions.ArtifactRoot.RootType;
import com.google.devtools.build.lib.analysis.BlazeDirectories;
import com.google.devtools.build.lib.analysis.PlatformOptions;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.RepositoryName;
import com.google.devtools.build.lib.server.FailureDetails.BuildConfiguration.Code;
import com.google.devtools.build.lib.util.OS;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.lib.vfs.PathFragment.InvalidBaseNameException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;

/**
 * Logic for figuring out what base directories to place outputs generated from a given
 * configuration.
 *
 * <p>In other words, when your output ends up in <code>blaze-out/x86-fastbuild/...</code>, this
 * class is why.
 */
public class OutputDirectories {
  /**
   * Directories in the output tree.
   *
   * <p>The computation of the output directory should be a non-injective mapping from
   * BuildConfigurationValue instances to strings. The result should identify the aspects of the
   * configuration that should be reflected in the output file names. Furthermore the returned
   * string must not contain shell metacharacters.
   *
   * <p>For configuration settings which are NOT part of the output directory name, rebuilding with
   * a different value of such a setting will build in the same output directory. This means that
   * any actions whose keys (see Action.getKey()) have changed will be rerun. That may result in a
   * lot of recompilation.
   *
   * <p>For configuration settings which ARE part of the output directory name, rebuilding with a
   * different value of such a setting will rebuild in a different output directory; this will
   * result in higher disk usage and more work the <i>first</i> time you rebuild with a different
   * setting, but will result in less work if you regularly switch back and forth between different
   * settings.
   *
   * <p>With one important exception, it's sound to choose any subset of the config's components for
   * this string, it just alters the dimensionality of the cache. In other words, it's a trade-off
   * on the "injectiveness" scale: at one extreme (output directory name contains all data in the
   * config, and is thus injective) you get extremely precise caching (no competition for the same
   * output-file locations) but you have to rebuild for even the slightest change in configuration.
   * At the other extreme (the output (directory name is a constant) you have very high competition
   * for output-file locations, but if a slight change in configuration doesn't affect a particular
   * build step, you're guaranteed not to have to rebuild it. The important exception has to do with
   * multiple configurations: every configuration in the build must have a different output
   * directory name so that their artifacts do not conflict.
   *
   * <p>The host configuration is special-cased: in order to guarantee that its output directory is
   * always separate from that of the target configuration, we simply pin it to "host". We do this
   * so that the build works even if the two configurations are too close (which is common) and so
   * that the path of artifacts in the host configuration is a bit more readable.
   */
  public enum OutputDirectory {
    BIN("bin"),
    GENFILES("genfiles"),
    MIDDLEMAN("internal"),
    TESTLOGS("testlogs"),
    COVERAGE("coverage-metadata"),
    INCLUDE(BlazeDirectories.RELATIVE_INCLUDE_DIR),
    OUTPUT("");

    /**
     * Returns the {@link OutputDirectory} matching the given name.
     *
     * <p>Throws {@link IllegalArgumentException} if the given name does not match any directory in
     * the output tree.
     */
    public static OutputDirectory forName(String name) {
      checkNotNull(name);
      for (OutputDirectory directory : values()) {
        if (directory.name.equals(name)) {
          return directory;
        }
      }
      throw new IllegalArgumentException(name);
    }

    private final String name;

    OutputDirectory(String name) {
      // Must be a legal basename for root - multiple segments not allowed.
      if (!name.isEmpty()) {
        FileSystemUtils.checkBaseName(name);
      }
      this.name = name;
    }

    public ArtifactRoot getRoot(
        String outputDirName, BlazeDirectories directories, RepositoryName mainRepositoryName) {
      // e.g., execroot/repo1
      Path execRoot = directories.getExecRoot(mainRepositoryName.strippedName());
      // e.g., [[execroot/repo1]/bazel-out/config/bin]
      return ArtifactRoot.asDerivedRoot(
          execRoot,
          this == MIDDLEMAN ? RootType.Middleman : RootType.Output,
          directories.getRelativeOutputPath(),
          outputDirName,
          name);
    }
  }

  private final BlazeDirectories directories;
  private final String mnemonic;
  private final String outputDirName;

  private final ArtifactRoot outputDirectory;
  private final ArtifactRoot binDirectory;
  private final ArtifactRoot includeDirectory;
  private final ArtifactRoot genfilesDirectory;
  private final ArtifactRoot coverageDirectory;
  private final ArtifactRoot testlogsDirectory;
  private final ArtifactRoot middlemanDirectory;

  private final boolean mergeGenfilesDirectory;

  private final boolean siblingRepositoryLayout;

  private final Path execRoot;

  OutputDirectories(
      BlazeDirectories directories,
      CoreOptions options,
      @Nullable PlatformOptions platformOptions,
      ImmutableSortedMap<Class<? extends Fragment>, Fragment> fragments,
      RepositoryName mainRepositoryName,
      boolean siblingRepositoryLayout)
      throws InvalidMnemonicException {
    this.directories = directories;
    this.mnemonic = buildMnemonic(options, platformOptions, fragments);
    this.outputDirName = options.isHost ? "host" : mnemonic;

    this.outputDirectory =
        OutputDirectory.OUTPUT.getRoot(outputDirName, directories, mainRepositoryName);
    this.binDirectory = OutputDirectory.BIN.getRoot(outputDirName, directories, mainRepositoryName);
    this.includeDirectory =
        OutputDirectory.INCLUDE.getRoot(outputDirName, directories, mainRepositoryName);
    this.genfilesDirectory =
        OutputDirectory.GENFILES.getRoot(outputDirName, directories, mainRepositoryName);
    this.coverageDirectory =
        OutputDirectory.COVERAGE.getRoot(outputDirName, directories, mainRepositoryName);
    this.testlogsDirectory =
        OutputDirectory.TESTLOGS.getRoot(outputDirName, directories, mainRepositoryName);
    this.middlemanDirectory =
        OutputDirectory.MIDDLEMAN.getRoot(outputDirName, directories, mainRepositoryName);

    this.mergeGenfilesDirectory = options.mergeGenfilesDirectory;
    this.siblingRepositoryLayout = siblingRepositoryLayout;
    this.execRoot = directories.getExecRoot(mainRepositoryName.strippedName());
  }

  private static void addMnemonicPart(
      List<String> nameParts, String part, String errorTemplate, Object... spec)
      throws InvalidMnemonicException {
    if (Strings.isNullOrEmpty(part)) {
      return;
    }

    validateMnemonicPart(part, errorTemplate, spec);

    nameParts.add(part);
  }

  /**
   * Validate that part is valid for use in the mnemonic, emitting an error message based on the
   * template if not.
   *
   * <p>The error template is expanded with the part itself as the first argument, and any remaining
   * elements of errorArgs following.
   */
  private static void validateMnemonicPart(String part, String errorTemplate, Object... errorArgs)
      throws InvalidMnemonicException {
    try {
      PathFragment.checkSeparators(part);
    } catch (InvalidBaseNameException e) {
      Object[] args = new Object[errorArgs.length + 1];
      args[0] = part;
      System.arraycopy(errorArgs, 0, args, 1, errorArgs.length);
      String message = String.format(errorTemplate, args);
      throw new InvalidMnemonicException(message, e);
    }
  }

  private static String buildMnemonic(
      CoreOptions options,
      @Nullable PlatformOptions platformOptions,
      ImmutableSortedMap<Class<? extends Fragment>, Fragment> fragments)
      throws InvalidMnemonicException {
    // See explanation at declaration for outputRoots.
    List<String> nameParts = new ArrayList<>();

    // Add the fragment-specific sections.
    for (Map.Entry<Class<? extends Fragment>, Fragment> entry : fragments.entrySet()) {
      String outputDirectoryName = entry.getValue().getOutputDirectoryName();
      addMnemonicPart(
          nameParts,
          outputDirectoryName,
          "Output directory name '%s' specified by %s",
          entry.getKey().getSimpleName());
    }

    // Add the compilation mode.
    addMnemonicPart(nameParts, options.compilationMode.toString(), "Compilation mode '%s'");

    // Add the platform suffix, if any.
    addMnemonicPart(nameParts, options.platformSuffix, "Platform suffix '%s'");

    // Add the transition suffix.
    addMnemonicPart(
        nameParts,
        options.transitionDirectoryNameFragment,
        "Transition directory name fragment '%s'");

    // Join all the parts.
    String mnemonic = nameParts.stream().filter(not(Strings::isNullOrEmpty)).collect(joining("-"));

    // Replace the CPU idenfitier.
    String cpuIdentifier = buildCpuIdentifier(options, platformOptions);
    validateMnemonicPart(cpuIdentifier, "CPU name '%s'");
    mnemonic = mnemonic.replace("{CPU}", cpuIdentifier);

    return mnemonic;
  }

  private static String buildCpuIdentifier(
      CoreOptions options, @Nullable PlatformOptions platformOptions) {
    if (options.platformInOutputDir && platformOptions != null) {
      Label targetPlatform = platformOptions.computeTargetPlatform();
      // Only use non-default platforms.
      if (!PlatformOptions.platformIsDefault(targetPlatform)) {
        return targetPlatform.getName();
      }
    }

    // Fall back to using the CPU.
    return options.cpu;
  }

  private ArtifactRoot buildDerivedRoot(
      String nameFragment, RepositoryName repository, boolean isMiddleman) {
    // e.g., execroot/mainRepoName/bazel-out/[repoName/]config/bin
    // TODO(jungjw): Ideally, we would like to do execroot_base/repoName/bazel-out/config/bin
    // instead. However, it requires individually symlinking the top-level elements of external
    // repositories, which is blocked by a Windows symlink issue #8704.
    RootType rootType;
    if (repository.isMain() || repository.isDefault()) {
      rootType = isMiddleman ? RootType.SiblingMainMiddleman : RootType.SiblingMainOutput;
    } else {
      rootType = isMiddleman ? RootType.SiblingExternalMiddleman : RootType.SiblingExternalOutput;
    }
    return ArtifactRoot.asDerivedRoot(
        execRoot,
        rootType,
        directories.getRelativeOutputPath(),
        repository.strippedName(),
        outputDirName,
        nameFragment);
  }

  /** Returns the output directory for this build configuration. */
  ArtifactRoot getOutputDirectory(RepositoryName repositoryName) {
    return siblingRepositoryLayout ? buildDerivedRoot("", repositoryName, false) : outputDirectory;
  }

  /** Returns the bin directory for this build configuration. */
  ArtifactRoot getBinDirectory(RepositoryName repositoryName) {
    return siblingRepositoryLayout ? buildDerivedRoot("bin", repositoryName, false) : binDirectory;
  }

  /** Returns the include directory for this build configuration. */
  ArtifactRoot getIncludeDirectory(RepositoryName repositoryName) {
    return siblingRepositoryLayout
        ? buildDerivedRoot(BlazeDirectories.RELATIVE_INCLUDE_DIR, repositoryName, false)
        : includeDirectory;
  }

  /** Returns the genfiles directory for this build configuration. */
  ArtifactRoot getGenfilesDirectory(RepositoryName repositoryName) {
    return mergeGenfilesDirectory
        ? getBinDirectory(repositoryName)
        : siblingRepositoryLayout
            ? buildDerivedRoot("genfiles", repositoryName, false)
            : genfilesDirectory;
  }

  /**
   * Returns the directory where coverage-related artifacts and metadata files should be stored.
   * This includes for example uninstrumented class files needed for Jacoco's coverage reporting
   * tools.
   */
  ArtifactRoot getCoverageMetadataDirectory(RepositoryName repositoryName) {
    return siblingRepositoryLayout
        ? buildDerivedRoot("coverage-metadata", repositoryName, false)
        : coverageDirectory;
  }

  /** Returns the testlogs directory for this build configuration. */
  ArtifactRoot getTestLogsDirectory(RepositoryName repositoryName) {
    return siblingRepositoryLayout
        ? buildDerivedRoot("testlogs", repositoryName, false)
        : testlogsDirectory;
  }

  /** Returns a relative path to the genfiles directory at execution time. */
  PathFragment getGenfilesFragment(RepositoryName repositoryName) {
    return getGenfilesDirectory(repositoryName).getExecPath();
  }

  /**
   * Returns the path separator for the host platform. This is basically the same as {@link
   * java.io.File#pathSeparator}, except that that returns the value for this JVM, which may or may
   * not match the host platform. You should only use this when invoking tools that are known to use
   * the native path separator, i.e., the path separator for the machine that they run on.
   */
  String getHostPathSeparator() {
    // TODO(bazel-team): Maybe do this in the constructor instead? This isn't serialization-safe.
    return OS.getCurrent() == OS.WINDOWS ? ";" : ":";
  }

  /** Returns the internal directory (used for middlemen) for this build configuration. */
  ArtifactRoot getMiddlemanDirectory(RepositoryName repositoryName) {
    return siblingRepositoryLayout
        ? buildDerivedRoot("internal", repositoryName, true)
        : middlemanDirectory;
  }

  String getMnemonic() {
    return mnemonic;
  }

  boolean mergeGenfilesDirectory() {
    return mergeGenfilesDirectory;
  }

  BlazeDirectories getDirectories() {
    return directories;
  }

  /** Indicates a failure to construct the mnemonic for an output directory. */
  public static class InvalidMnemonicException extends InvalidConfigurationException {
    InvalidMnemonicException(String message, InvalidBaseNameException e) {
      super(
          message + " is invalid as part of a path: " + e.getMessage(),
          Code.INVALID_OUTPUT_DIRECTORY_MNEMONIC);
    }
  }
}
