// 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.base.Preconditions.checkArgument;
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.Iterables;
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.List;
import java.util.Set;

/**
 * Static utilities for managing output directory symlinks.
 */
public class OutputDirectoryLinksUtils {
  // Used in getPrettyPath() method below.
  private static final String[] LINKS = { "bin", "genfiles", "includes" };

  private static final String NO_CREATE_SYMLINKS_PREFIX = "/";

  public static ImmutableList<String> getOutputSymlinkNames(String productName,
      String symlinkPrefix) {
    ImmutableList.Builder<String> builder = ImmutableList.<String>builder();
    // TODO(b/35234395): This symlink is created for backwards compatiblity, remove it once
    // we're sure it won't cause any other issues.
    builder.add(productName + "-out");
    if (!productName.equals(symlinkPrefix)) {
      builder.add(symlinkPrefix + "out");
    }
    return builder.build();
  }

  private static String execRootSymlink(String symlinkPrefix, String workspaceName) {
    return symlinkPrefix + workspaceName;
  }

  /**
   * 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) {
    if (NO_CREATE_SYMLINKS_PREFIX.equals(symlinkPrefix)) {
      return;
    }
    List<String> failures = new ArrayList<>();

    // Make the two non-specific links from the workspace to the output area,
    // and the configuration-specific links in both the workspace and the execution root dirs.
    // IMPORTANT: Keep in sync with removeOutputDirectoryLinks below.
    for (String outputSymlinkName : getOutputSymlinkNames(productName, symlinkPrefix)) {
      createLink(workspace, outputSymlinkName, outputPath, failures);
    }

    // Points to execroot
    createLink(workspace, execRootSymlink(
        symlinkPrefix, workspace.getBaseName()), execRoot, failures);
    RepositoryName repositoryName = RepositoryName.createFromValidStrippedName(workspaceName);

    // Set up convenience symlinks iff there's only one useful target for them to point to;
    // otherwise, remove stale symlinks from previous invocations at that path to avoid confusion
    Set<Path> binPaths =
        targetConfigs
            .stream()
            .map(targetConfig -> targetConfig.getBinDirectory(repositoryName).getRoot())
            .map(Root::asPath)
            .distinct()
            .collect(toImmutableSet());
    if (binPaths.size() == 1) {
      createLink(workspace, symlinkPrefix + "bin", Iterables.getOnlyElement(binPaths), failures);
    } else {
      removeLink(workspace, symlinkPrefix + "bin", failures);
    }
    Set<Path> testLogsPaths =
        targetConfigs
            .stream()
            .map(targetConfig -> targetConfig.getTestLogsDirectory(repositoryName).getRoot())
            .map(Root::asPath)
            .distinct()
            .collect(toImmutableSet());
    if (testLogsPaths.size() == 1) {
      createLink(
          workspace,
          symlinkPrefix + "testlogs",
          Iterables.getOnlyElement(testLogsPaths),
          failures);
    } else {
      removeLink(workspace, symlinkPrefix + "testlogs", failures);
    }
    Set<Path> genfilesPaths =
        targetConfigs
            .stream()
            .map(targetConfig -> targetConfig.getGenfilesDirectory(repositoryName).getRoot())
            .map(Root::asPath)
            .distinct()
            .collect(toImmutableSet());
    if (genfilesPaths.size() == 1) {
      createLink(
          workspace,
          symlinkPrefix + "genfiles",
          Iterables.getOnlyElement(genfilesPaths),
          failures);
    } else {
      removeLink(workspace, symlinkPrefix + "genfiles", failures);
    }

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

  /**
   * Returns a convenient path to the specified file, relativizing it and using output-dir symlinks
   * if possible.  Otherwise, return a path relative to the workspace directory if possible.
   * Otherwise, return the absolute path.
   *
   * <p>This method must be called after the symlinks are created at the end of a build. If called
   * before, the pretty path may be incorrect if the symlinks end up pointing somewhere new.
   */
  public static PathFragment getPrettyPath(Path file, String workspaceName,
      Path workspaceDirectory, String symlinkPrefix, String productName) {
    if (NO_CREATE_SYMLINKS_PREFIX.equals(symlinkPrefix)) {
      return file.asFragment();
    }

    for (String link : LINKS) {
      PathFragment result = relativize(file, workspaceDirectory, symlinkPrefix + link);
      if (result != null) {
        return result;
      }
    }

    PathFragment result = relativize(file, workspaceDirectory,
        execRootSymlink(symlinkPrefix, workspaceName));
    if (result != null) {
      return result;
    }

    ImmutableList<String> outputSymlinkNames = getOutputSymlinkNames(productName, symlinkPrefix);
    checkArgument(!outputSymlinkNames.isEmpty());
    result = relativize(file, workspaceDirectory, outputSymlinkNames.get(0));
    if (result != null) {
      return result;
    }

    return file.asFragment();
  }

  // Helper to getPrettyPath.  Returns file, relativized w.r.t. the referent of
  // "linkname", or null if it was a not a child.
  private static PathFragment relativize(Path file, Path workspaceDirectory, String linkname) {
    PathFragment link = PathFragment.create(linkname);
    try {
      Path dir = workspaceDirectory.getRelative(link);
      PathFragment levelOneLinkTarget = dir.readSymbolicLink();
      if (levelOneLinkTarget.isAbsolute() &&
          file.startsWith(dir = file.getRelative(levelOneLinkTarget))) {
        return link.getRelative(file.relativeTo(dir));
      }
    } catch (IOException e) {
      /* ignore */
    }
    return null;
  }

  /**
   * 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<>();

    for (String outputSymlinkName : getOutputSymlinkNames(productName, symlinkPrefix)) {
      removeLink(workspace, outputSymlinkName, failures);
    }
    removeLink(workspace, execRootSymlink(symlinkPrefix, workspaceName), failures);
    removeLink(workspace, execRootSymlink(symlinkPrefix, workspace.getBaseName()), failures);
    removeLink(workspace, symlinkPrefix + "bin", failures);
    removeLink(workspace, symlinkPrefix + "testlogs", failures);
    removeLink(workspace, symlinkPrefix + "genfiles", 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;
    }
  }
}
