// Copyright 2017 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 com.google.common.base.Preconditions.checkNotNull;

import com.google.common.base.Preconditions;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.CommandLineItem;
import com.google.devtools.build.lib.actions.ParamFileInfo;
import com.google.devtools.build.lib.actions.ParameterFile.ParameterFileType;
import com.google.devtools.build.lib.analysis.FilesToRunProvider;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.actions.CustomCommandLine;
import com.google.devtools.build.lib.analysis.actions.CustomCommandLine.VectorArg;
import com.google.devtools.build.lib.analysis.actions.SpawnAction;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory.RuleErrorException;
import com.google.devtools.build.lib.rules.java.JavaConfiguration.OneVersionEnforcementLevel;
import com.google.devtools.build.lib.skyframe.serialization.VisibleForSerialization;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.SerializationConstant;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import javax.annotation.Nullable;

/** Utility for generating a call to the one-version binary. */
public final class OneVersionCheckActionBuilder {

  private OneVersionCheckActionBuilder() {}

  private OneVersionEnforcementLevel enforcementLevel;
  private JavaToolchainProvider javaToolchain;
  private NestedSet<Artifact> jarsToCheck;

  public static OneVersionCheckActionBuilder newBuilder() {
    return new OneVersionCheckActionBuilder();
  }

  @CanIgnoreReturnValue
  public OneVersionCheckActionBuilder useToolchain(JavaToolchainProvider toolchain) {
    javaToolchain = toolchain;
    return this;
  }

  @CanIgnoreReturnValue
  public OneVersionCheckActionBuilder checkJars(NestedSet<Artifact> jarsToCheck) {
    this.jarsToCheck = jarsToCheck;
    return this;
  }

  @CanIgnoreReturnValue
  public OneVersionCheckActionBuilder withEnforcementLevel(
      OneVersionEnforcementLevel enforcementLevel) {
    Preconditions.checkArgument(
        enforcementLevel != OneVersionEnforcementLevel.OFF,
        "one version enforcement actions shouldn't be built if the enforcement "
            + "level is set to off");
    this.enforcementLevel = enforcementLevel;
    return this;
  }

  @Nullable
  public Artifact build(RuleContext ruleContext) throws InterruptedException, RuleErrorException {
    Preconditions.checkNotNull(enforcementLevel);
    Preconditions.checkNotNull(javaToolchain);
    Preconditions.checkNotNull(jarsToCheck);

    FilesToRunProvider oneVersionTool = javaToolchain.getOneVersionBinary();
    Artifact oneVersionAllowlist;
    if (ruleContext.isTestTarget()) {
      oneVersionAllowlist = javaToolchain.oneVersionAllowlistForTests();
    } else {
      oneVersionAllowlist = javaToolchain.getOneVersionAllowlist();
    }
    if (oneVersionTool == null || oneVersionAllowlist == null) {
      return null;
    }

    Artifact outputArtifact =
        ruleContext.getImplicitOutputArtifact(JavaSemantics.JAVA_ONE_VERSION_ARTIFACT);

    CustomCommandLine.Builder oneVersionArgsBuilder =
        CustomCommandLine.builder()
            .addExecPath("--output", outputArtifact)
            .addExecPath("--whitelist", oneVersionAllowlist);
    if (enforcementLevel == OneVersionEnforcementLevel.WARNING) {
      oneVersionArgsBuilder.add("--succeed_on_found_violations");
    }
    oneVersionArgsBuilder.addAll("--inputs", jarAndTargetVectorArg(jarsToCheck));
    CustomCommandLine oneVersionArgs = oneVersionArgsBuilder.build();
    ruleContext.registerAction(
        new SpawnAction.Builder()
            .addOutput(outputArtifact)
            .addInput(oneVersionAllowlist)
            .addTransitiveInputs(jarsToCheck)
            .setExecutable(oneVersionTool)
            .addCommandLine(
                oneVersionArgs,
                ParamFileInfo.builder(ParameterFileType.SHELL_QUOTED).setUseAlways(true).build())
            .setMnemonic("JavaOneVersion")
            .setProgressMessage("Checking for one-version violations in %s", ruleContext.getLabel())
            .build(ruleContext));
    return outputArtifact;
  }

  static VectorArg<String> jarAndTargetVectorArg(NestedSet<Artifact> jarsToCheck) {
    return VectorArg.of(jarsToCheck).mapped(EXPAND_TO_JAR_AND_TARGET);
  }

  @SerializationConstant @VisibleForSerialization
  static final CommandLineItem.MapFn<Artifact> EXPAND_TO_JAR_AND_TARGET =
      (jar, args) ->
          args.accept(jar.getExecPathString() + "," + getArtifactOwnerGeneralizedLabel(jar));

  private static String getArtifactOwnerGeneralizedLabel(Artifact artifact) {
    Label label = checkNotNull(artifact.getOwnerLabel(), artifact);
    return label.getRepository().isMain()
        ? label.toString()
        // Escape '@' prefix for .params file.
        : "@" + label;
  }
}
