// 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.rules.java;

import static java.util.stream.Collectors.joining;

import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.collect.nestedset.Order;
import com.google.devtools.build.lib.packages.BuildType;
import com.google.devtools.build.lib.packages.Type;
import com.google.devtools.build.lib.shell.ShellUtils;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.annotation.Nullable;

/** Utility methods for use by Java-related parts of Bazel. */
// TODO(bazel-team): Merge with JavaUtil.
public abstract class JavaHelper {

  private JavaHelper() {}

  /**
   * Returns the java launcher implementation for the given target, if any. A null return value
   * means "use the JDK launcher".
   */
  @Nullable
  public static TransitiveInfoCollection launcherForTarget(
      JavaSemantics semantics, RuleContext ruleContext) {
    String launcher = filterLauncherForTarget(ruleContext);
    return (launcher == null) ? null : ruleContext.getPrerequisite(launcher);
  }

  /**
   * Returns the java launcher artifact for the given target, if any. A null return value means "use
   * the JDK launcher".
   */
  @Nullable
  public static Artifact launcherArtifactForTarget(
      JavaSemantics semantics, RuleContext ruleContext) {
    String launcher = filterLauncherForTarget(ruleContext);
    return (launcher == null) ? null : ruleContext.getPrerequisiteArtifact(launcher);
  }

  /**
   * Control structure abstraction for safely extracting a prereq from the launcher attribute or
   * {@code --java_launcher} flag.
   *
   * <p>Returns {@code null} if either {@code create_executable} or {@code use_launcher} are
   * disabled.
   */
  @Nullable
  private static String filterLauncherForTarget(RuleContext ruleContext) {
    // create_executable=0 disables the launcher
    if (ruleContext.getRule().isAttrDefined("create_executable", Type.BOOLEAN)
        && !ruleContext.attributes().get("create_executable", Type.BOOLEAN)) {
      return null;
    }
    // use_launcher=False disables the launcher
    if (ruleContext.getRule().isAttrDefined("use_launcher", Type.BOOLEAN)
        && !ruleContext.attributes().get("use_launcher", Type.BOOLEAN)) {
      return null;
    }
    // BUILD rule "launcher" attribute
    if (ruleContext.getRule().isAttrDefined("launcher", BuildType.LABEL)
        && ruleContext.attributes().get("launcher", BuildType.LABEL) != null) {
      return "launcher";
    }
    // Blaze flag --java_launcher
    JavaConfiguration javaConfig = ruleContext.getFragment(JavaConfiguration.class);
    if (ruleContext.getRule().isAttrDefined(":java_launcher", BuildType.LABEL)
        && javaConfig.getJavaLauncherLabel() != null) {
      return ":java_launcher";
    }
    return null;
  }

  /**
   * Flattens a set of javacopts and tokenizes the contents.
   *
   * <p>Since javac allows passing the same option multiple times, and the right-most one wins,
   * multiple instances of the same option+value get de-duped by the NestedSet. So when combining
   * multiple NestedSets, we store them in reverse order, and reverse again after flattening. This
   * preserves the right-most occurrence in its correct position, thus achieving the correct
   * semantics.
   *
   * @param inOpts the set of opts to tokenize
   */
  public static ImmutableList<String> tokenizeJavaOptions(NestedSet<String> inOpts) {
    return tokenizeJavaOptions(inOpts.toList().reverse());
  }

  /**
   * Javac options require special processing - People use them and expect the options to be
   * tokenized.
   */
  public static ImmutableList<String> tokenizeJavaOptions(Iterable<String> inOpts) {
    // Ideally, this would be in the options parser. Unfortunately,
    // the options parser can't handle a converter that expands
    // from a value X into a List<X> and allow-multiple at the
    // same time.
    List<String> result = new ArrayList<>();
    for (String current : inOpts) {
      try {
        ShellUtils.tokenize(result, current);
      } catch (ShellUtils.TokenizationException ex) {
        // Tokenization failed; this likely means that the user
        // did not want tokenization to happen on their argument.
        // (Any tokenization where we should produce an error
        // has already been done by the shell that invoked
        // blaze). Therefore, pass the argument through to
        // the tool, so that we can see the original error.
        result.add(current);
      }
    }
    return ImmutableList.copyOf(result);
  }

  /**
   * De-tokenizes a collection of {@code javac} options into a {@link NestedSet}.
   *
   * <p>Each option is shell-escaped to get back the original option as-is when we tokenize the
   * depset.
   *
   * @param javacOpts the {@code javac} options to detokenize
   * @return A {@link NestedSet} of the supplied options concatenated into a single string separated
   *     by ' '.
   */
  public static NestedSet<String> detokenizeJavaOptions(Collection<String> javacOpts) {
    if (javacOpts.isEmpty()) {
      return NestedSetBuilder.emptySet(Order.NAIVE_LINK_ORDER);
    }
    return NestedSetBuilder.create(
        Order.NAIVE_LINK_ORDER,
        javacOpts.stream().map(ShellUtils::shellEscape).collect(joining(" ")));
  }

  public static PathFragment getJavaResourcePath(
      JavaSemantics semantics, RuleContext ruleContext, Artifact resource) {
    boolean siblingRepositoryLayout = ruleContext.getConfiguration().isSiblingRepositoryLayout();
    PathFragment resourcePath = resource.getOutputDirRelativePath(siblingRepositoryLayout);
    PathFragment repoExecPath =
        ruleContext
            .getLabel()
            .getRepository()
            .getExecPath(siblingRepositoryLayout);
    if (!repoExecPath.isEmpty() && resourcePath.startsWith(repoExecPath)) {
      resourcePath = resourcePath.relativeTo(repoExecPath);
    }

    if (!ruleContext.attributes().has("resource_strip_prefix", Type.STRING)
        || !ruleContext.attributes().isAttributeValueExplicitlySpecified("resource_strip_prefix")) {
      return semantics.getDefaultJavaResourcePath(resourcePath);
    }

    PathFragment prefix =
        PathFragment.create(ruleContext.attributes().get("resource_strip_prefix", Type.STRING));

    if (!resourcePath.startsWith(prefix)) {
      ruleContext.attributeError(
          "resource_strip_prefix",
          String.format(
              "Resource file '%s' is not under the specified prefix to strip", resourcePath));
      return resourcePath;
    }

    return resourcePath.relativeTo(prefix);
  }
}
