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

import static com.google.common.collect.ImmutableSet.toImmutableSet;

import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.actions.ArtifactRoot;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.cmdline.RepositoryName;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.EventHandler;
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.Root;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;

/**
 * Static utilities for managing output directory symlinks.
 */
public class OutputDirectoryLinksUtils {
  static interface SymlinkDefinition {
    String getLinkName(String symlinkPrefix, String productName, String workspaceBaseName);

    Optional<Path> getLinkPath(
        Set<BuildConfiguration> targetConfigs,
        RepositoryName repositoryName,
        Path outputPath,
        Path execRoot);
  }

  private static final class ConfigSymlink implements SymlinkDefinition {
    @FunctionalInterface
    private static interface ConfigPathGetter {
      ArtifactRoot apply(BuildConfiguration configuration, RepositoryName repositoryName);
    }

    private final String suffix;
    private final ConfigPathGetter configToRoot;

    public ConfigSymlink(String suffix, ConfigPathGetter configToRoot) {
      this.suffix = suffix;
      this.configToRoot = configToRoot;
    }

    @Override
    public String getLinkName(String symlinkPrefix, String productName, String workspaceBaseName) {
      return symlinkPrefix + suffix;
    }

    @Override
    public Optional<Path> getLinkPath(
        Set<BuildConfiguration> targetConfigs,
        RepositoryName repositoryName,
        Path outputPath,
        Path execRoot) {
      Set<Path> paths =
          targetConfigs
              .stream()
              .map(config -> configToRoot.apply(config, repositoryName))
              .map(ArtifactRoot::getRoot)
              .map(Root::asPath)
              .distinct()
              .collect(toImmutableSet());
      if (paths.size() == 1) {
        return Optional.of(Iterables.getOnlyElement(paths));
      } else {
        return Optional.empty();
      }
    }
  }

  private static enum ExecRootSymlink implements SymlinkDefinition {
    INSTANCE;

    @Override
    public String getLinkName(String symlinkPrefix, String productName, String workspaceBaseName) {
      return symlinkPrefix + workspaceBaseName;
    }

    @Override
    public Optional<Path> getLinkPath(
        Set<BuildConfiguration> targetConfigs,
        RepositoryName repositoryName,
        Path outputPath,
        Path execRoot) {
      return Optional.of(execRoot);
    }
  }

  private static enum OutputSymlink implements SymlinkDefinition {
    PRODUCT_NAME {
      @Override
      public String getLinkName(
          String symlinkPrefix, String productName, String workspaceBaseName) {
        // TODO(b/35234395): This symlink is created for backwards compatibility, remove it once
        // we're sure it won't cause any other issues.
        return productName + "-out";
      }
    },
    SYMLINK_PREFIX {
      @Override
      public String getLinkName(
          String symlinkPrefix, String productName, String workspaceBaseName) {
        return symlinkPrefix + "out";
      }
    };

    @Override
    public Optional<Path> getLinkPath(
        Set<BuildConfiguration> targetConfigs,
        RepositoryName repositoryName,
        Path outputPath,
        Path execRoot) {
      return Optional.of(outputPath);
    }
  }

  // Links to create, delete, and use for pretty-printing.
  // Note that the order in which items appear in this list controls priority for getPrettyPath.
  // It will try each link as a prefix from first to last.
  private static final ImmutableList<SymlinkDefinition> LINK_DEFINITIONS_WITH_GENFILES =
      ImmutableList.of(
          new ConfigSymlink("bin", BuildConfiguration::getBinDirectory),
          new ConfigSymlink("testlogs", BuildConfiguration::getTestLogsDirectory),
          new ConfigSymlink("genfiles", BuildConfiguration::getGenfilesDirectory),
          OutputSymlink.PRODUCT_NAME,
          OutputSymlink.SYMLINK_PREFIX,
          ExecRootSymlink.INSTANCE);

  // The genfiles symlink will be removed in the future.
  private static final ImmutableList<SymlinkDefinition> LINK_DEFINITIONS_WITHOUT_GENFILES =
      ImmutableList.of(
          new ConfigSymlink("bin", BuildConfiguration::getBinDirectory),
          new ConfigSymlink("testlogs", BuildConfiguration::getTestLogsDirectory),
          OutputSymlink.PRODUCT_NAME,
          OutputSymlink.SYMLINK_PREFIX,
          ExecRootSymlink.INSTANCE);

  private static final String NO_CREATE_SYMLINKS_PREFIX = "/";

  public static Iterable<String> getOutputSymlinkNames(String productName, String symlinkPrefix) {
    ImmutableSet.Builder<String> builder = ImmutableSet.<String>builder();
    for (OutputSymlink definition : OutputSymlink.values()) {
      builder.add(definition.getLinkName(symlinkPrefix, productName, null));
    }
    return builder.build();
  }

  /**
   * Attempts to create convenience symlinks in the workspaceDirectory and in execRoot to the output
   * area and to the configuration-specific output directories. Issues a warning if it fails, e.g.
   * because workspaceDirectory is readonly.
   *
   * <p>Configuration-specific output symlinks will be created or updated if and only if the set of
   * {@code targetConfigs} contains only configurations whose output directories match. Otherwise -
   * i.e., if there are multiple configurations with distinct output directories or there were no
   * targets with non-null configurations in the build - any stale symlinks left over from previous
   * invocations will be removed.
   */
  static void createOutputDirectoryLinks(
      String workspaceName,
      Path workspace,
      Path execRoot,
      Path outputPath,
      EventHandler eventHandler,
      Set<BuildConfiguration> targetConfigs,
      String symlinkPrefix,
      String productName,
      boolean createGenfilesSymlink) {
    if (NO_CREATE_SYMLINKS_PREFIX.equals(symlinkPrefix)) {
      return;
    }

    List<String> failures = new ArrayList<>();
    List<String> missingLinks = new ArrayList<>();
    Set<String> createdLinks = new LinkedHashSet<>();
    String workspaceBaseName = workspace.getBaseName();
    RepositoryName repositoryName = RepositoryName.createFromValidStrippedName(workspaceName);

    List<SymlinkDefinition> defs =
        createGenfilesSymlink ? LINK_DEFINITIONS_WITH_GENFILES : LINK_DEFINITIONS_WITHOUT_GENFILES;
    for (SymlinkDefinition definition : defs) {
      String symlinkName = definition.getLinkName(symlinkPrefix, productName, workspaceBaseName);
      if (!createdLinks.add(symlinkName)) {
        // already created a link by this name
        continue;
      }
      Optional<Path> result =
          definition.getLinkPath(targetConfigs, repositoryName, outputPath, execRoot);
      if (result.isPresent()) {
        createLink(workspace, symlinkName, result.get(), failures);
      } else {
        removeLink(workspace, symlinkName, failures);
        missingLinks.add(symlinkName);
      }
    }

    if (!failures.isEmpty()) {
      eventHandler.handle(Event.warn(String.format(
          "failed to create one or more convenience symlinks for prefix '%s':\n  %s",
          symlinkPrefix, Joiner.on("\n  ").join(failures))));
    }
    if (!missingLinks.isEmpty()) {
      eventHandler.handle(
          Event.warn(
              String.format(
                  "cleared convenience symlink(s) %s because their destinations would be ambiguous",
                  Joiner.on(", ").join(missingLinks))));
    }
  }

  public static PathPrettyPrinter getPathPrettyPrinter(
      String symlinkPrefix, String productName, Path workspaceDirectory, Path workingDirectory) {
    return new PathPrettyPrinter(
        LINK_DEFINITIONS_WITH_GENFILES,
        symlinkPrefix,
        productName,
        workspaceDirectory,
        workingDirectory);
  }

  /**
   * Attempts to remove the convenience symlinks in the workspace directory.
   *
   * <p>Issues a warning if it fails, e.g. because workspaceDirectory is readonly.
   * Also cleans up any child directories created by a custom prefix.
   *
   * @param workspace the runtime's workspace
   * @param eventHandler the error eventHandler
   * @param symlinkPrefix the symlink prefix which should be removed
   * @param productName the product name
   */
  public static void removeOutputDirectoryLinks(String workspaceName, Path workspace,
      EventHandler eventHandler, String symlinkPrefix, String productName) {
    if (NO_CREATE_SYMLINKS_PREFIX.equals(symlinkPrefix)) {
      return;
    }
    List<String> failures = new ArrayList<>();

    String workspaceBaseName = workspace.getBaseName();
    for (SymlinkDefinition link : LINK_DEFINITIONS_WITH_GENFILES) {
      removeLink(
          workspace, link.getLinkName(symlinkPrefix, productName, workspaceBaseName), failures);
    }

    FileSystemUtils.removeDirectoryAndParents(workspace, PathFragment.create(symlinkPrefix));
    if (!failures.isEmpty()) {
      eventHandler.handle(Event.warn(String.format(
          "failed to remove one or more convenience symlinks for prefix '%s':\n  %s", symlinkPrefix,
          Joiner.on("\n  ").join(failures))));
    }
  }

  /**
   * Helper to createOutputDirectoryLinks that creates a symlink from base + name to target.
   */
  private static boolean createLink(Path base, String name, Path target, List<String> failures) {
    try {
      FileSystemUtils.createDirectoryAndParents(target);
    } catch (IOException e) {
      failures.add(String.format("cannot create directory %s: %s",
          target.getPathString(), e.getMessage()));
      return false;
    }
    try {
      FileSystemUtils.ensureSymbolicLink(base.getRelative(name), target);
    } catch (IOException e) {
      failures.add(String.format("cannot create symbolic link %s -> %s:  %s",
          name, target.getPathString(), e.getMessage()));
      return false;
    }

    return true;
  }

  /**
   * Helper to removeOutputDirectoryLinks that removes one of the Blaze convenience symbolic links.
   */
  private static boolean removeLink(Path base, String name, List<String> failures) {
    Path link = base.getRelative(name);
    try {
      if (link.isSymbolicLink()) {
        ExecutionTool.logger.finest("Removing " + link);
        link.delete();
      }
      return true;
    } catch (IOException e) {
      failures.add(String.format("%s: %s", name, e.getMessage()));
      return false;
    }
  }
}
