// 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 com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.devtools.build.lib.rules.java.JavaCommon.collectJavaCompilationArgs;

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.config.CoreOptionConverters.StrictDepsMode;
import com.google.devtools.build.lib.rules.java.JavaConfiguration.JavaClasspathMode;
import com.google.devtools.build.lib.rules.java.JavaRuleOutputJarsProvider.OutputJar;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.annotation.Nullable;

/**
 * A class to create Java compile actions in a way that is consistent with java_library. Rules that
 * generate source files and emulate java_library on top of that should use this class instead of
 * the lower-level API in JavaCompilationHelper.
 *
 * <p>Rules that want to use this class are required to have an implicit dependency on the Java
 * compiler.
 */
public final class JavaLibraryHelper {
  private final RuleContext ruleContext;

  private Artifact output;
  private final List<Artifact> sourceJars = new ArrayList<>();
  private final List<Artifact> sourceFiles = new ArrayList<>();
  private final List<Artifact> resources = new ArrayList<>();

  /**
   * Contains all the dependencies; these are treated as both compile-time and runtime dependencies.
   */
  private final List<JavaCompilationArgsProvider> deps = new ArrayList<>();

  private final List<JavaCompilationArgsProvider> exports = new ArrayList<>();
  private JavaPluginInfoProvider plugins = JavaPluginInfoProvider.empty();
  private ImmutableList<String> javacOpts = ImmutableList.of();
  private ImmutableList<Artifact> sourcePathEntries = ImmutableList.of();
  private final List<Artifact> additionalOutputs = new ArrayList<>();

  /** @see {@link #setCompilationStrictDepsMode}. */
  private StrictDepsMode strictDepsMode = StrictDepsMode.ERROR;

  private final JavaClasspathMode classpathMode;
  private String injectingRuleKind;
  private boolean neverlink;

  public JavaLibraryHelper(RuleContext ruleContext) {
    this.ruleContext = ruleContext;
    ruleContext.getConfiguration();
    this.classpathMode = ruleContext.getFragment(JavaConfiguration.class).getReduceJavaClasspath();
  }

  public JavaLibraryHelper setNeverlink(boolean neverlink) {
    this.neverlink = neverlink;
    return this;
  }

  /**
   * Sets the final output jar; if this is not set, then the {@link #build} method throws an {@link
   * IllegalStateException}. Note that this class may generate not just the output itself, but also
   * a number of additional intermediate files and outputs.
   */
  public JavaLibraryHelper setOutput(Artifact output) {
    this.output = output;
    return this;
  }

  /** Adds the given source jars. Any .java files in these jars will be compiled. */
  public JavaLibraryHelper addSourceJars(Iterable<Artifact> sourceJars) {
    Iterables.addAll(this.sourceJars, sourceJars);
    return this;
  }

  /** Adds the given source jars. Any .java files in these jars will be compiled. */
  public JavaLibraryHelper addSourceJars(Artifact... sourceJars) {
    return this.addSourceJars(Arrays.asList(sourceJars));
  }

  public JavaLibraryHelper addResources(Iterable<Artifact> resources) {
    Iterables.addAll(this.resources, resources);
    return this;
  }

  public JavaLibraryHelper addDep(JavaCompilationArgsProvider provider) {
    checkNotNull(provider);
    this.deps.add(provider);
    return this;
  }

  /** Adds the given source files to be compiled. */
  public JavaLibraryHelper addSourceFiles(Iterable<Artifact> sourceFiles) {
    Iterables.addAll(this.sourceFiles, sourceFiles);
    return this;
  }

  public JavaLibraryHelper addExport(JavaCompilationArgsProvider provider) {
    exports.add(provider);
    return this;
  }

  public JavaLibraryHelper addAdditionalOutputs(Iterable<Artifact> outputs) {
    Iterables.addAll(additionalOutputs, outputs);
    return this;
  }

  public JavaLibraryHelper setPlugins(JavaPluginInfoProvider plugins) {
    checkNotNull(plugins, "plugins must not be null");
    checkState(this.plugins.isEmpty());
    this.plugins = plugins;
    return this;
  }

  /** Sets the compiler options. */
  public JavaLibraryHelper setJavacOpts(Iterable<String> javacOpts) {
    this.javacOpts = ImmutableList.copyOf(javacOpts);
    return this;
  }

  public JavaLibraryHelper setSourcePathEntries(List<Artifact> sourcepathEntries) {
    this.sourcePathEntries = ImmutableList.copyOf(sourcepathEntries);
    return this;
  }

  public JavaLibraryHelper setInjectingRuleKind(String injectingRuleKind) {
    this.injectingRuleKind = injectingRuleKind;
    return this;
  }

  /**
   * When in strict mode, compiling the source-jars passed to this JavaLibraryHelper will break if
   * they depend on classes not in any of the {@link
   * JavaCompilationArgsProvider#getDirectCompileTimeJars()} passed in {@link #addDep}, even if they
   * do appear in {@link JavaCompilationArgsProvider#getTransitiveCompileTimeJars()}. That is,
   * depending on a class requires a direct dependency on it.
   *
   * <p>Contrast this with the strictness-parameter to {@link #buildCompilationArgsProvider}, which
   * controls whether others depending on the result of this compilation, can perform strict-deps
   * checks at all.
   *
   * <p>Defaults to {@link StrictDepsMode#ERROR}.
   */
  public JavaLibraryHelper setCompilationStrictDepsMode(StrictDepsMode strictDepsMode) {
    this.strictDepsMode = strictDepsMode;
    return this;
  }

  /**
   * Creates the compile actions (including the ones for ijar and source jar). Also fills in the
   * {@link JavaRuleOutputJarsProvider.Builder} with the corresponding compilation outputs.
   *
   * @param semantics implementation specific java rules semantics
   * @param javaToolchainProvider used for retrieving misc java tools
   * @param hostJavabase the target of the host javabase used to retrieve the java executable and
   *     its necessary inputs
   * @param outputJarsBuilder populated with the outputs of the created actions
   * @param outputSourceJar if not-null, the output of an source jar action that will be created
   */
  public JavaCompilationArtifacts build(
      JavaSemantics semantics,
      JavaToolchainProvider javaToolchainProvider,
      JavaRuntimeInfo hostJavabase,
      JavaRuleOutputJarsProvider.Builder outputJarsBuilder,
      boolean createOutputSourceJar,
      @Nullable Artifact outputSourceJar)
      throws InterruptedException {
    return build(
        semantics,
        javaToolchainProvider,
        hostJavabase,
        outputJarsBuilder,
        createOutputSourceJar,
        outputSourceJar,
        /* javaInfoBuilder= */ null,
        ImmutableList.of(), // ignored when javaInfoBuilder is null
        ImmutableList.of());
  }

  public JavaCompilationArtifacts build(
      JavaSemantics semantics,
      JavaToolchainProvider javaToolchainProvider,
      JavaRuntimeInfo hostJavabase,
      JavaRuleOutputJarsProvider.Builder outputJarsBuilder,
      boolean createOutputSourceJar,
      @Nullable Artifact outputSourceJar,
      @Nullable JavaInfo.Builder javaInfoBuilder,
      Iterable<JavaGenJarsProvider> transitiveJavaGenJars,
      ImmutableList<Artifact> additionalJavaBaseInputs)
      throws InterruptedException {

    Preconditions.checkState(output != null, "must have an output file; use setOutput()");
    Preconditions.checkState(
        !createOutputSourceJar || outputSourceJar != null,
        "outputSourceJar cannot be null when createOutputSourceJar is true");

    JavaTargetAttributes.Builder attributes = new JavaTargetAttributes.Builder(semantics);
    attributes.addSourceJars(sourceJars);
    attributes.addSourceFiles(sourceFiles);
    addDepsToAttributes(attributes);
    attributes.setStrictJavaDeps(strictDepsMode);
    attributes.setTargetLabel(ruleContext.getLabel());
    attributes.setInjectingRuleKind(injectingRuleKind);
    attributes.setSourcePath(sourcePathEntries);
    JavaCommon.addPlugins(attributes, plugins);
    attributes.addAdditionalOutputs(additionalOutputs);

    for (Artifact resource : resources) {
      attributes.addResource(
          JavaHelper.getJavaResourcePath(semantics, ruleContext, resource), resource);
    }

    if (isStrict() && classpathMode != JavaClasspathMode.OFF) {
      JavaCompilationHelper.addDependencyArtifactsToAttributes(attributes, deps);
    }

    JavaCompilationArtifacts.Builder artifactsBuilder = new JavaCompilationArtifacts.Builder();
    JavaCompilationHelper helper =
        new JavaCompilationHelper(
            ruleContext,
            semantics,
            javacOpts,
            attributes,
            javaToolchainProvider,
            hostJavabase,
            additionalJavaBaseInputs);
    JavaCompileOutputs<Artifact> outputs = helper.createOutputs(output);
    artifactsBuilder.setCompileTimeDependencies(outputs.depsProto());
    helper.createCompileAction(outputs);

    Artifact iJar = null;
    if (!sourceJars.isEmpty() || !sourceFiles.isEmpty()) {
      artifactsBuilder.addRuntimeJar(output);
      iJar = helper.createCompileTimeJarAction(output, artifactsBuilder);
    }

    if (createOutputSourceJar) {
      helper.createSourceJarAction(
          outputSourceJar, outputs.genSource(), javaToolchainProvider, hostJavabase);
    }
    ImmutableList<Artifact> outputSourceJars =
        outputSourceJar == null ? ImmutableList.of() : ImmutableList.of(outputSourceJar);
    outputJarsBuilder
        .addOutputJar(new OutputJar(output, iJar, outputs.manifestProto(), outputSourceJars))
        .setJdeps(outputs.depsProto())
        .setNativeHeaders(outputs.nativeHeader());

    JavaCompilationArtifacts javaArtifacts = artifactsBuilder.build();
    if (javaInfoBuilder != null) {
      ClasspathConfiguredFragment classpathFragment =
          new ClasspathConfiguredFragment(
              javaArtifacts,
              attributes.build(),
              neverlink,
              JavaCompilationHelper.getBootClasspath(javaToolchainProvider));

      javaInfoBuilder.addProvider(
          JavaCompilationInfoProvider.class,
          new JavaCompilationInfoProvider.Builder()
              .setJavacOpts(javacOpts)
              .setBootClasspath(classpathFragment.getBootClasspath())
              .setCompilationClasspath(classpathFragment.getCompileTimeClasspath())
              .setRuntimeClasspath(classpathFragment.getRuntimeClasspath())
              .build());

      javaInfoBuilder.addProvider(
          JavaGenJarsProvider.class,
          createJavaGenJarsProvider(
              helper, outputs.genClass(), outputs.genSource(), transitiveJavaGenJars));
    }

    return javaArtifacts;
  }

  private JavaGenJarsProvider createJavaGenJarsProvider(
      JavaCompilationHelper helper,
      @Nullable Artifact genClassJar,
      @Nullable Artifact genSourceJar,
      Iterable<JavaGenJarsProvider> transitiveJavaGenJars) {
    return JavaGenJarsProvider.create(
        helper.usesAnnotationProcessing(),
        genClassJar,
        genSourceJar,
        plugins,
        transitiveJavaGenJars);
  }

  /**
   * Returns a JavaCompilationArgsProvider that fully encapsulates this compilation, based on the
   * result of a call to build(). (that is, it contains the compile-time and runtime jars, separated
   * by direct vs transitive jars).
   *
   * @param isReportedAsStrict if true, the result's direct JavaCompilationArgs only contain classes
   *     resulting from compiling the source-jars. If false, the direct JavaCompilationArgs contain
   *     both these classes, as well as any classes from transitive dependencies. A value of 'false'
   *     means this compilation cannot be checked for strict-deps, by any consumer (depending)
   *     compilation. Contrast this with {@link #setCompilationStrictDepsMode}.
   */
  public JavaCompilationArgsProvider buildCompilationArgsProvider(
      JavaCompilationArtifacts artifacts, boolean isReportedAsStrict, boolean isNeverlink) {

    JavaCompilationArgsProvider directArgs =
        collectJavaCompilationArgs(
            /* isNeverLink= */ isNeverlink,
            /* srcLessDepsExport= */ false,
            artifacts,
            deps,
            /* runtimeDeps= */ ImmutableList.of(),
            exports);

    if (!isReportedAsStrict) {
      directArgs = JavaCompilationArgsProvider.makeNonStrict(directArgs);
    }
    return directArgs;
  }

  private void addDepsToAttributes(JavaTargetAttributes.Builder attributes) {
    JavaCompilationArgsProvider argsProvider = JavaCompilationArgsProvider.merge(deps);

    if (isStrict()) {
      attributes.addDirectJars(argsProvider.getDirectCompileTimeJars());
    }

    attributes.addCompileTimeClassPathEntries(argsProvider.getTransitiveCompileTimeJars());
    attributes.addRuntimeClassPathEntries(argsProvider.getRuntimeJars());
  }

  private boolean isStrict() {
    return strictDepsMode != StrictDepsMode.OFF;
  }
}
