// Copyright 2018 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.Predicates.not;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.collect.Iterables.concat;
import static com.google.common.collect.Streams.stream;
import static com.google.devtools.build.lib.rules.java.JavaCompilationArgsProvider.ClasspathType.BOTH;
import static com.google.devtools.build.lib.rules.java.JavaCompilationArgsProvider.ClasspathType.COMPILE_ONLY;
import static com.google.devtools.build.lib.rules.java.JavaCompilationArgsProvider.ClasspathType.RUNTIME_ONLY;
import static com.google.devtools.build.lib.rules.java.JavaInfo.streamProviders;
import static java.util.stream.Stream.concat;

import com.google.common.base.Ascii;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Streams;
import com.google.devtools.build.lib.actions.ActionRegistry;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.FilesToRunProvider;
import com.google.devtools.build.lib.analysis.actions.ActionConstructionContext;
import com.google.devtools.build.lib.analysis.actions.CustomCommandLine;
import com.google.devtools.build.lib.analysis.actions.SpawnAction;
import com.google.devtools.build.lib.analysis.config.CoreOptionConverters.StrictDepsMode;
import com.google.devtools.build.lib.analysis.starlark.StarlarkActionFactory;
import com.google.devtools.build.lib.analysis.starlark.StarlarkRuleContext;
import com.google.devtools.build.lib.cmdline.Label;
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.rules.cpp.CcInfo;
import com.google.devtools.build.lib.rules.java.JavaCompilationArgsProvider.ClasspathType;
import com.google.devtools.build.lib.rules.java.JavaRuleOutputJarsProvider.JavaOutput;
import com.google.devtools.build.lib.shell.ShellUtils;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Stream;
import javax.annotation.Nullable;
import net.starlark.java.eval.EvalException;
import net.starlark.java.eval.Sequence;
import net.starlark.java.eval.Starlark;
import net.starlark.java.eval.StarlarkThread;
import net.starlark.java.syntax.Location;

/** Implements logic for creating JavaInfo from different set of input parameters. */
final class JavaInfoBuildHelper {
  private static final JavaInfoBuildHelper INSTANCE = new JavaInfoBuildHelper();

  private JavaInfoBuildHelper() {}

  public static JavaInfoBuildHelper getInstance() {
    return INSTANCE;
  }

  /**
   * Creates JavaInfo instance from outputJar.
   *
   * @param javaOutput the artifacts that were created as a result of a compilation (e.g. javac,
   *     scalac, etc)
   * @param neverlink if true only use this library for compilation and not at runtime
   * @param compileTimeDeps compile time dependencies that were used to create the output jar
   * @param runtimeDeps runtime dependencies that are needed for this library
   * @param exports libraries to make available for users of this library. <a
   *     href="https://bazel.build/reference/be/java#java_library"
   *     target="_top">java_library.exports</a>
   * @param exportedPlugins A list of exported plugins.
   * @param nativeLibraries CC library dependencies that are needed for this library
   * @return new created JavaInfo instance
   */
  JavaInfo createJavaInfo(
      JavaOutput javaOutput,
      Boolean neverlink,
      Sequence<JavaInfo> compileTimeDeps,
      Sequence<JavaInfo> runtimeDeps,
      Sequence<JavaInfo> exports,
      Sequence<JavaPluginInfo> exportedPlugins,
      Sequence<CcInfo> nativeLibraries,
      Location location) {
    JavaInfo.Builder javaInfoBuilder = JavaInfo.Builder.create();
    javaInfoBuilder.setLocation(location);
    javaInfoBuilder.setNeverlink(neverlink);

    JavaCompilationArgsProvider.Builder javaCompilationArgsBuilder =
        JavaCompilationArgsProvider.builder();

    if (!neverlink) {
      javaCompilationArgsBuilder.addRuntimeJar(javaOutput.getClassJar());
    }
    if (javaOutput.getCompileJar() != null) {
      javaCompilationArgsBuilder.addDirectCompileTimeJar(
          /* interfaceJar= */ javaOutput.getCompileJar(), /* fullJar= */ javaOutput.getClassJar());
    }
    if (javaOutput.getCompileJdeps() != null) {
      javaCompilationArgsBuilder.addCompileTimeJavaDependencyArtifacts(
          NestedSetBuilder.create(Order.STABLE_ORDER, javaOutput.getCompileJdeps()));
    }

    JavaRuleOutputJarsProvider javaRuleOutputJarsProvider =
        JavaRuleOutputJarsProvider.builder().addJavaOutput(javaOutput).build();
    javaInfoBuilder.addProvider(JavaRuleOutputJarsProvider.class, javaRuleOutputJarsProvider);

    ClasspathType type = neverlink ? COMPILE_ONLY : BOTH;

    streamProviders(exports, JavaCompilationArgsProvider.class)
        .forEach(args -> javaCompilationArgsBuilder.addExports(args, type));
    streamProviders(compileTimeDeps, JavaCompilationArgsProvider.class)
        .forEach(args -> javaCompilationArgsBuilder.addDeps(args, type));

    streamProviders(runtimeDeps, JavaCompilationArgsProvider.class)
        .forEach(args -> javaCompilationArgsBuilder.addDeps(args, RUNTIME_ONLY));

    javaInfoBuilder.addProvider(
        JavaCompilationArgsProvider.class, javaCompilationArgsBuilder.build());

    javaInfoBuilder.javaPluginInfo(mergeExportedJavaPluginInfo(exportedPlugins, exports));

    javaInfoBuilder.addProvider(
        JavaSourceJarsProvider.class,
        createJavaSourceJarsProvider(
            javaOutput.getSourceJars(), concat(compileTimeDeps, runtimeDeps, exports)));

    javaInfoBuilder.addProvider(
        JavaGenJarsProvider.class,
        JavaGenJarsProvider.create(
            false,
            javaOutput.getGeneratedClassJar(),
            javaOutput.getGeneratedSourceJar(),
            JavaPluginInfo.empty(),
            JavaInfo.streamProviders(concat(compileTimeDeps, exports), JavaGenJarsProvider.class)
                .filter(not(JavaGenJarsProvider::isEmpty))
                .collect(toImmutableList())));

    javaInfoBuilder.setRuntimeJars(ImmutableList.of(javaOutput.getClassJar()));

    ImmutableList<JavaCcInfoProvider> transitiveNativeLibraries =
        Streams.concat(
                streamProviders(runtimeDeps, JavaCcInfoProvider.class),
                streamProviders(exports, JavaCcInfoProvider.class),
                streamProviders(compileTimeDeps, JavaCcInfoProvider.class),
                Stream.of(new JavaCcInfoProvider(CcInfo.merge(nativeLibraries))))
            .collect(toImmutableList());
    javaInfoBuilder.addProvider(
        JavaCcInfoProvider.class, JavaCcInfoProvider.merge(transitiveNativeLibraries));

    javaInfoBuilder.addProvider(
        JavaModuleFlagsProvider.class,
        JavaModuleFlagsProvider.merge(
            JavaInfo.streamProviders(
                    concat(compileTimeDeps, exports), JavaModuleFlagsProvider.class)
                .collect(toImmutableList())));

    return javaInfoBuilder.build();
  }

  /**
   * Creates action which creates archive with all source files inside. Takes all filer from
   * sourceFiles collection and all files from every sourceJars. Name of Artifact generated based on
   * outputJar.
   *
   * @param outputJar name of output Jar artifact.
   * @param outputSourceJar name of output source Jar artifact, or {@code null}. If unset, defaults
   *     to base name of the output jar with the suffix {@code -src.jar}.
   * @return generated artifact (can also be empty)
   */
  Artifact packSourceFiles(
      StarlarkActionFactory actions,
      Artifact outputJar,
      Artifact outputSourceJar,
      List<Artifact> sourceFiles,
      List<Artifact> sourceJars,
      JavaToolchainProvider javaToolchain)
      throws EvalException {
    if (outputJar == null && outputSourceJar == null) {
      throw Starlark.errorf(
          "pack_sources requires at least one of the parameters output_jar or output_source_jar");
    }
    // If we only have one source jar, return it directly to avoid action creation
    if (sourceFiles.isEmpty() && sourceJars.size() == 1 && outputSourceJar == null) {
      return sourceJars.get(0);
    }
    ActionRegistry actionRegistry = actions.asActionRegistry(actions);
    if (outputSourceJar == null) {
      outputSourceJar = getDerivedSourceJar(actions.getActionConstructionContext(), outputJar);
    }
    SingleJarActionBuilder.createSourceJarAction(
        actionRegistry,
        actions.getActionConstructionContext(),
        javaToolchain.getJavaSemantics(),
        NestedSetBuilder.<Artifact>wrap(Order.STABLE_ORDER, sourceFiles),
        NestedSetBuilder.<Artifact>wrap(Order.STABLE_ORDER, sourceJars),
        outputSourceJar,
        javaToolchain);
    return outputSourceJar;
  }

  private JavaSourceJarsProvider createJavaSourceJarsProvider(
      Iterable<Artifact> sourceJars, Iterable<JavaInfo> transitiveDeps) {
    NestedSetBuilder<Artifact> transitiveSourceJars = NestedSetBuilder.stableOrder();

    transitiveSourceJars.addAll(sourceJars);

    fetchSourceJars(transitiveDeps).forEach(transitiveSourceJars::addTransitive);

    return JavaSourceJarsProvider.create(transitiveSourceJars.build(), sourceJars);
  }

  private Stream<NestedSet<Artifact>> fetchSourceJars(Iterable<JavaInfo> javaInfos) {
    // TODO(b/123265803): This step should be only necessary if transitive source jar doesn't
    // include sourcejar at this level but they should.
    Stream<NestedSet<Artifact>> sourceJars =
        streamProviders(javaInfos, JavaSourceJarsProvider.class)
            .map(JavaSourceJarsProvider::getSourceJars)
            .map(sourceJarsList -> NestedSetBuilder.wrap(Order.STABLE_ORDER, sourceJarsList));

    Stream<NestedSet<Artifact>> transitiveSourceJars =
        streamProviders(javaInfos, JavaSourceJarsProvider.class)
            .map(JavaSourceJarsProvider::getTransitiveSourceJars);

    return concat(transitiveSourceJars, sourceJars);
  }

  private static JavaModuleFlagsProvider createJavaModuleFlagsProvider(
      List<String> addExports, List<String> addOpens, Iterable<JavaInfo> transitiveDeps) {
    return JavaModuleFlagsProvider.create(
        addExports, addOpens, streamProviders(transitiveDeps, JavaModuleFlagsProvider.class));
  }

  private JavaPluginInfo mergeExportedJavaPluginInfo(
      Iterable<JavaPluginInfo> plugins, Iterable<JavaInfo> javaInfos) {
    return JavaPluginInfo.mergeWithoutJavaOutputs(
        concat(
            plugins,
            stream(javaInfos)
                .map(JavaInfo::getJavaPluginInfo)
                .filter(Objects::nonNull)
                .collect(toImmutableList())));
  }

  public JavaInfo createJavaCompileAction(
      StarlarkRuleContext starlarkRuleContext,
      List<Artifact> sourceJars,
      List<Artifact> sourceFiles,
      Artifact outputJar,
      Artifact outputSourceJar,
      List<String> javacOpts,
      List<JavaInfo> deps,
      List<JavaInfo> runtimeDeps,
      List<JavaInfo> exports,
      List<JavaPluginInfo> plugins,
      List<JavaPluginInfo> exportedPlugins,
      List<CcInfo> nativeLibraries,
      List<Artifact> annotationProcessorAdditionalInputs,
      List<Artifact> annotationProcessorAdditionalOutputs,
      String strictDepsMode,
      JavaToolchainProvider javaToolchain,
      ImmutableList<Artifact> sourcepathEntries,
      List<Artifact> resources,
      List<Artifact> resourceJars,
      List<Artifact> classpathResources,
      Boolean neverlink,
      Boolean enableAnnotationProcessing,
      Boolean enableCompileJarAction,
      boolean enableJSpecify,
      boolean includeCompilationInfo,
      JavaSemantics javaSemantics,
      Object injectingRuleKind,
      List<String> addExports,
      List<String> addOpens,
      StarlarkThread thread)
      throws EvalException, InterruptedException {

    JavaToolchainProvider toolchainProvider = javaToolchain;

    JavaPluginInfo pluginInfo = mergeExportedJavaPluginInfo(plugins, deps);
    ImmutableList.Builder<String> allJavacOptsBuilder =
        ImmutableList.<String>builder()
            .addAll(toolchainProvider.getJavacOptions(starlarkRuleContext.getRuleContext()))
            .addAll(
                javaSemantics.getCompatibleJavacOptions(
                    starlarkRuleContext.getRuleContext(), toolchainProvider));
    if (pluginInfo
        .plugins()
        .processorClasses()
        .toSet()
        .contains("com.google.devtools.build.runfiles.AutoBazelRepositoryProcessor")) {
      allJavacOptsBuilder.add(
          "-Abazel.repository=" + starlarkRuleContext.getRuleContext().getRepository().getName());
    }
    allJavacOptsBuilder
        .addAll(
            JavaCommon.computePerPackageJavacOpts(
                starlarkRuleContext.getRuleContext(), toolchainProvider))
        .addAll(JavaModuleFlagsProvider.toFlags(addExports, addOpens))
        .addAll(tokenize(javacOpts));

    JavaLibraryHelper helper =
        new JavaLibraryHelper(starlarkRuleContext.getRuleContext())
            .setOutput(outputJar)
            .addSourceJars(sourceJars)
            .addSourceFiles(sourceFiles)
            .addResources(resources)
            .addResourceJars(resourceJars)
            .addClasspathResources(classpathResources)
            .setSourcePathEntries(sourcepathEntries)
            .addAdditionalOutputs(annotationProcessorAdditionalOutputs)
            .enableJspecify(enableJSpecify)
            .setJavacOpts(allJavacOptsBuilder.build());

    if (injectingRuleKind != Starlark.NONE) {
      helper.setInjectingRuleKind((String) injectingRuleKind);
    }

    streamProviders(runtimeDeps, JavaCompilationArgsProvider.class).forEach(helper::addRuntimeDep);
    streamProviders(deps, JavaCompilationArgsProvider.class).forEach(helper::addDep);
    streamProviders(exports, JavaCompilationArgsProvider.class).forEach(helper::addExport);
    helper.setCompilationStrictDepsMode(getStrictDepsMode(Ascii.toUpperCase(strictDepsMode)));
    // Optimization: skip this if there are no annotation processors, to avoid unnecessarily
    // disabling the direct classpath optimization if `enable_annotation_processor = False`
    // but there aren't any annotation processors.
    if (!enableAnnotationProcessing && !pluginInfo.plugins().processorClasses().isEmpty()) {
      pluginInfo = pluginInfo.disableAnnotationProcessing();
      helper.enableDirectClasspath(false);
    }
    helper.setPlugins(pluginInfo);
    helper.setNeverlink(neverlink);

    JavaRuleOutputJarsProvider.Builder outputJarsBuilder = JavaRuleOutputJarsProvider.builder();

    boolean createOutputSourceJar =
        !(sourceJars.size() == 1
            && sourceFiles.isEmpty()
            && sourceJars.get(0).equals(outputSourceJar));
    if (outputSourceJar == null) {
      outputSourceJar = getDerivedSourceJar(starlarkRuleContext.getRuleContext(), outputJar);
    }

    JavaInfo.Builder javaInfoBuilder = JavaInfo.Builder.create();
    JavaCompilationArtifacts artifacts =
        helper.build(
            javaSemantics,
            toolchainProvider,
            outputJarsBuilder,
            createOutputSourceJar,
            includeCompilationInfo,
            outputSourceJar,
            enableCompileJarAction,
            javaInfoBuilder,
            // Include JavaGenJarsProviders from both deps and exports in the JavaGenJarsProvider
            // added to javaInfoBuilder for this target.
            JavaInfo.streamProviders(concat(deps, exports), JavaGenJarsProvider.class)
                .filter(not(JavaGenJarsProvider::isEmpty))
                .collect(toImmutableList()),
            ImmutableList.copyOf(annotationProcessorAdditionalInputs));

    JavaCompilationArgsProvider javaCompilationArgsProvider =
        helper.buildCompilationArgsProvider(artifacts, true, neverlink);

    ImmutableList<Artifact> outputSourceJars = ImmutableList.of(outputSourceJar);

    // When sources are not provided, the subsequent output Jar will be empty. As such, the output
    // Jar is omitted from the set of Runtime Jars.
    if (!sourceJars.isEmpty() || !sourceFiles.isEmpty() || !resources.isEmpty()) {
      javaInfoBuilder.setRuntimeJars(ImmutableList.of(outputJar));
    }

    ImmutableList<JavaCcInfoProvider> transitiveNativeLibraries =
        Streams.concat(
                streamProviders(runtimeDeps, JavaCcInfoProvider.class),
                streamProviders(exports, JavaCcInfoProvider.class),
                streamProviders(deps, JavaCcInfoProvider.class),
                Stream.of(new JavaCcInfoProvider(CcInfo.merge(nativeLibraries))))
            .collect(toImmutableList());

    return javaInfoBuilder
        .addProvider(JavaCompilationArgsProvider.class, javaCompilationArgsProvider)
        .addProvider(
            JavaSourceJarsProvider.class,
            createJavaSourceJarsProvider(outputSourceJars, concat(runtimeDeps, exports, deps)))
        .addProvider(JavaRuleOutputJarsProvider.class, outputJarsBuilder.build())
        .javaPluginInfo(mergeExportedJavaPluginInfo(exportedPlugins, exports))
        .addProvider(JavaCcInfoProvider.class, JavaCcInfoProvider.merge(transitiveNativeLibraries))
        .addProvider(
            JavaModuleFlagsProvider.class,
            createJavaModuleFlagsProvider(addExports, addOpens, concat(runtimeDeps, exports, deps)))
        .setNeverlink(neverlink)
        .build();
  }

  private static List<String> tokenize(List<String> input) throws EvalException {
    List<String> output = new ArrayList<>();
    for (String token : input) {
      try {
        ShellUtils.tokenize(output, token);
      } catch (ShellUtils.TokenizationException e) {
        throw Starlark.errorf("%s", e.getMessage());
      }
    }
    return output;
  }

  public Artifact buildIjar(
      StarlarkActionFactory actions,
      Artifact inputJar,
      @Nullable Artifact outputJar,
      @Nullable Label targetLabel,
      JavaToolchainProvider javaToolchain)
      throws EvalException {
    Artifact interfaceJar;
    if (outputJar != null) {
      interfaceJar = outputJar;
    } else {
      String ijarBasename = FileSystemUtils.removeExtension(inputJar.getFilename()) + "-ijar.jar";
      interfaceJar = actions.declareFile(ijarBasename, inputJar);
    }
    FilesToRunProvider ijarTarget = javaToolchain.getIjar();
    CustomCommandLine.Builder commandLine =
        CustomCommandLine.builder().addExecPath(inputJar).addExecPath(interfaceJar);
    if (targetLabel != null) {
      commandLine.addLabel("--target_label", targetLabel);
    }
    SpawnAction.Builder actionBuilder =
        new SpawnAction.Builder()
            .addInput(inputJar)
            .addOutput(interfaceJar)
            .setExecutable(ijarTarget)
            .setProgressMessage("Extracting interface for jar %s", inputJar.getFilename())
            .addCommandLine(commandLine.build())
            .useDefaultShellEnvironment()
            .setMnemonic("JavaIjar");
    actions.registerAction(actionBuilder.build(actions.getActionConstructionContext()));
    return interfaceJar;
  }

  public Artifact stampJar(
      StarlarkActionFactory actions,
      Artifact inputJar,
      Label targetLabel,
      JavaToolchainProvider javaToolchain)
      throws EvalException {
    String basename = FileSystemUtils.removeExtension(inputJar.getFilename()) + "-stamped.jar";
    Artifact outputJar = actions.declareFile(basename, inputJar);
    // ijar doubles as a stamping tool
    FilesToRunProvider ijarTarget = javaToolchain.getIjar();
    CustomCommandLine.Builder commandLine =
        CustomCommandLine.builder()
            .addExecPath(inputJar)
            .addExecPath(outputJar)
            .add("--nostrip_jar")
            .addLabel("--target_label", targetLabel);
    SpawnAction.Builder actionBuilder =
        new SpawnAction.Builder()
            .addInput(inputJar)
            .addOutput(outputJar)
            .setExecutable(ijarTarget)
            .setProgressMessage("Stamping target label into jar %s", inputJar.getFilename())
            .addCommandLine(commandLine.build())
            .useDefaultShellEnvironment()
            .setMnemonic("JavaIjar");
    actions.registerAction(actionBuilder.build(actions.getActionConstructionContext()));
    return outputJar;
  }

  private static StrictDepsMode getStrictDepsMode(String strictDepsMode) {
    switch (strictDepsMode) {
      case "OFF":
        return StrictDepsMode.OFF;
      case "ERROR":
      case "DEFAULT":
        return StrictDepsMode.ERROR;
      case "WARN":
        return StrictDepsMode.WARN;
      default:
        throw new IllegalArgumentException(
            "StrictDepsMode "
                + strictDepsMode
                + " not allowed."
                + " Only OFF and ERROR values are accepted.");
    }
  }

  private static Artifact getDerivedSourceJar(
      ActionConstructionContext context, Artifact outputJar) {
    return JavaCompilationHelper.derivedArtifact(context, outputJar, "", "-src.jar");
  }
}
