// Copyright 2022 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.runtime;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.analysis.BlazeDirectories;
import com.google.devtools.build.lib.vfs.FileSystem;
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 java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Factory for creating {@link PathFragment}s from command-line options.
 *
 * <p>The difference between this and using {@link PathFragment#create(String)} directly is that
 * this factory replaces values starting with {@code %<name>%} with the corresponding (named) roots
 * (e.g., {@code %workspace%/foo} becomes {@code </path/to/workspace>/foo}).
 */
public final class CommandLinePathFactory {
  /** An exception thrown while attempting to resolve a path. */
  public static class CommandLinePathFactoryException extends IOException {
    public CommandLinePathFactoryException(String message) {
      super(message);
    }
  }

  private static final Pattern REPLACEMENT_PATTERN = Pattern.compile("^(%([a-z_]+)%/+)?([^%].*)$");

  private static final Splitter PATH_SPLITTER = Splitter.on(File.pathSeparator);

  private final FileSystem fileSystem;
  private final ImmutableMap<String, Path> roots;

  @VisibleForTesting
  public CommandLinePathFactory(FileSystem fileSystem, ImmutableMap<String, Path> roots) {
    this.fileSystem = Preconditions.checkNotNull(fileSystem);
    this.roots = Preconditions.checkNotNull(roots);
  }

  static CommandLinePathFactory create(FileSystem fileSystem, BlazeDirectories directories) {
    Preconditions.checkNotNull(fileSystem);
    Preconditions.checkNotNull(directories);

    ImmutableMap.Builder<String, Path> wellKnownRoots = ImmutableMap.builder();

    // This is necessary because some tests don't have a workspace set.
    Path workspace = directories.getWorkspace();
    if (workspace != null) {
      wellKnownRoots.put("workspace", workspace);
    }

    return new CommandLinePathFactory(fileSystem, wellKnownRoots.build());
  }

  /** Creates a {@link Path}. */
  public Path create(Map<String, String> env, String value) throws IOException {
    Preconditions.checkNotNull(env);
    Preconditions.checkNotNull(value);

    Matcher matcher = REPLACEMENT_PATTERN.matcher(value);
    Preconditions.checkArgument(matcher.matches());

    String rootName = matcher.group(2);
    PathFragment path = PathFragment.create(matcher.group(3));
    if (path.containsUplevelReferences()) {
      throw new CommandLinePathFactoryException(
          String.format(
              Locale.US, "Path must not contain any uplevel references ('..'), got '%s'", value));
    }

    // Case 1: `path` is relative to a well-known root.
    if (!Strings.isNullOrEmpty(rootName)) {
      Path root = roots.get(rootName);
      if (root == null) {
        throw new CommandLinePathFactoryException(
            String.format(Locale.US, "Unknown root %s", rootName));
      }
      return root.getRelative(path);
    }

    // Case 2: `value` is an absolute path.
    if (path.isAbsolute()) {
      return fileSystem.getPath(path);
    }

    // Case 3: `value` is a relative path.
    //
    // Since relative paths from the command-line are ambiguous to where they are relative to (i.e.,
    // relative to the workspace?, the directory Bazel is running in? relative to the `.bazelrc` the
    // flag is from?), we only allow relative paths with a single segment (i.e., no `/`) and treat
    // it as relative to the user's `PATH`.
    if (path.segmentCount() > 1) {
      throw new CommandLinePathFactoryException(
          "Path must either be absolute or not contain any path separators");
    }

    String pathVariable = env.getOrDefault("PATH", "");
    if (!Strings.isNullOrEmpty(pathVariable)) {
      for (String lookupPath : PATH_SPLITTER.split(pathVariable)) {
        Path maybePath = fileSystem.getPath(lookupPath).getRelative(path);
        if (maybePath.exists(Symlinks.FOLLOW)
            && maybePath.isFile(Symlinks.FOLLOW)
            && maybePath.isExecutable()) {
          return maybePath;
        }
      }
    }

    throw new FileNotFoundException(
        String.format(
            Locale.US, "Could not find file with name '%s' on PATH '%s'", path, pathVariable));
  }
}
