// Copyright 2015 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 com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.actions.Artifact;
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.SpawnAction;
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.RuleClass.ConfiguredTargetFactory.RuleErrorException;
import java.util.Collection;

/**
 * Helpers for implementing rules which export Proguard specs.
 *
 * <p>This is not a ConfiguredTargetFactory; $proguard_library, which this class implements, is an
 * abstract rule class, and simply contributes this functionality to other rules.
 */
public final class ProguardLibrary {

  private static final String LOCAL_SPEC_ATTRIBUTE = "proguard_specs";
  private static final ImmutableSet<String> DEPENDENCY_ATTRIBUTES =
      ImmutableSet.of("deps", "exports", "runtime_deps", "plugins", "exported_plugins");

  private final RuleContext ruleContext;

  /** Creates a new ProguardLibrary wrapping the given RuleContext. */
  public ProguardLibrary(RuleContext ruleContext) {
    this.ruleContext = ruleContext;
  }

  /** Collects the validated proguard specs exported by this rule and its dependencies. */
  public NestedSet<Artifact> collectProguardSpecs() throws RuleErrorException {
    return collectProguardSpecs(DEPENDENCY_ATTRIBUTES);
  }

  /**
   * Collects the validated proguard specs exported by this rule and its dependencies through the
   * given attributes.
   */
  public NestedSet<Artifact> collectProguardSpecs(Iterable<String> attributes)
      throws RuleErrorException {
    NestedSetBuilder<Artifact> specsBuilder = NestedSetBuilder.naiveLinkOrder();

    for (String attribute : attributes) {
      specsBuilder.addTransitive(collectProguardSpecsFromAttribute(attribute));
    }

    Collection<Artifact> localSpecs = collectLocalProguardSpecs();
    if (!localSpecs.isEmpty()) {
      // Pass our local proguard configs through the validator, which checks an allowlist.
      FilesToRunProvider proguardAllowlister =
          JavaToolchainProvider.from(ruleContext).getProguardAllowlister();
      if (proguardAllowlister == null) {
        ruleContext.ruleError(
            "java_toolchain.proguard_allowlister is required to use proguard_specs");
        return specsBuilder.build();
      }
      for (Artifact specToValidate : localSpecs) {
        specsBuilder.add(validateProguardSpec(ruleContext, proguardAllowlister, specToValidate));
      }
    }

    return specsBuilder.build();
  }

  /** Collects the unvalidated proguard specs exported by this rule. */
  public ImmutableList<Artifact> collectLocalProguardSpecs() {
    if (!ruleContext.attributes().has(LOCAL_SPEC_ATTRIBUTE, BuildType.LABEL_LIST)) {
      return ImmutableList.of();
    }
    return ruleContext.getPrerequisiteArtifacts(LOCAL_SPEC_ATTRIBUTE).list();
  }

  /**
   * Collects the proguard specs exported by dependencies on the given LABEL_LIST/LABEL attribute.
   */
  private NestedSet<Artifact> collectProguardSpecsFromAttribute(String attributeName) {
    if (!ruleContext.attributes().has(attributeName, BuildType.LABEL_LIST)
        && !ruleContext.attributes().has(attributeName, BuildType.LABEL)) {
      return NestedSetBuilder.emptySet(Order.NAIVE_LINK_ORDER);
    }
    NestedSetBuilder<Artifact> dependencySpecsBuilder = NestedSetBuilder.naiveLinkOrder();
    for (ProguardSpecProvider provider :
        ruleContext.getPrerequisites(attributeName, ProguardSpecProvider.PROVIDER)) {
      dependencySpecsBuilder.addTransitive(provider.getTransitiveProguardSpecs());
    }
    return dependencySpecsBuilder.build();
  }

  /**
   * Creates an action to run the Proguard allowlister over the given Proguard spec and returns the
   * validated Proguard spec, ready to be exported.
   */
  private Artifact validateProguardSpec(
      RuleContext ruleContext, FilesToRunProvider proguardAllowlister, Artifact specToValidate)
      throws RuleErrorException {
    // If we're validating j/a/b/testapp/proguard.cfg, the output will be:
    // j/a/b/testapp/proguard.cfg_valid
    Artifact output =
        ruleContext.getUniqueDirectoryArtifact(
            "validated_proguard",
            specToValidate
                .getRootRelativePath()
                .replaceName(specToValidate.getFilename() + "_valid"),
            ruleContext.getBinOrGenfilesDirectory());
    SpawnAction.Builder builder =
        new SpawnAction.Builder().addInput(specToValidate).addOutput(output);
    if (proguardAllowlister.getExecutable().getExtension().equals("jar")) {
      builder
          .setJarExecutable(
              JavaCommon.getHostJavaExecutable(ruleContext),
              proguardAllowlister.getExecutable(),
              JavaToolchainProvider.from(ruleContext).getJvmOptions())
          .addTransitiveInputs(JavaRuntimeInfo.forHost(ruleContext).javaBaseInputs());
    } else {
      // TODO(b/170769708): remove this branch and require java_toolchain.proguard_allowlister to
      // always be a _deploy.jar
      builder.setExecutable(proguardAllowlister);
    }
    builder
        .setProgressMessage("Validating proguard configuration")
        .setMnemonic("ValidateProguard")
        .addCommandLine(
            CustomCommandLine.builder()
                .addExecPath("--path", specToValidate)
                .addExecPath("--output", output)
                .build());
    ruleContext.registerAction(builder.build(ruleContext));
    return output;
  }
}
