// 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.buildjar;

import static com.google.common.base.MoreObjects.firstNonNull;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.collect.ImmutableSet.toImmutableSet;

import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.buildjar.instrumentation.JacocoInstrumentationProcessor;
import com.google.devtools.build.buildjar.javac.BlazeJavacArguments;
import com.google.devtools.build.buildjar.javac.plugins.BlazeJavaCompilerPlugin;
import com.google.devtools.build.buildjar.javac.plugins.dependency.DependencyModule;
import com.google.devtools.build.buildjar.javac.plugins.processing.AnnotationProcessingModule;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;

/** All the information needed to perform a single Java library build operation. */
public final class JavaLibraryBuildRequest {
  private ImmutableList<String> javacOpts;

  /** Where to store source files generated by annotation processors. */
  private final Path sourceGenDir;

  /** The path to an output jar for source files generated by annotation processors. */
  private final Path generatedSourcesOutputJar;

  /** The path to an output jar for classfiles generated by annotation processors. */
  private final Path generatedClassOutputJar;

  private final ArrayList<Path> sourceFiles;
  private final ImmutableList<Path> sourceJars;

  private final ImmutableList<Path> sourcePath;
  private final ImmutableList<Path> classPath;
  private final ImmutableList<Path> bootClassPath;
  private final Path system;

  private final ImmutableList<Path> processorPath;
  private final List<String> processorNames;
  private final ImmutableSet<String> builtinProcessorNames;

  private final Path outputJar;
  private final Path nativeHeaderOutput;
  @Nullable private final String targetLabel;
  @Nullable private final String injectingRuleKind;

  private final Path classDir;
  private final Path tempDir;

  private JacocoInstrumentationProcessor jacocoInstrumentationProcessor;

  private final boolean compressJar;

  private final OptionsParser.ReduceClasspathMode reduceClasspathMode;
  private final int fullClasspathLength;
  private final int reducedClasspathLength;

  /** Repository for all dependency-related information. */
  private final DependencyModule dependencyModule;

  /** Repository for information about annotation processor-generated symbols. */
  private final AnnotationProcessingModule processingModule;

  /** List of plugins that are given to javac. */
  private final ImmutableList<BlazeJavaCompilerPlugin> plugins;

  /**
   * Constructs a build from a list of command args. Sets the same JavacRunner for both compilation
   * and annotation processing.
   *
   * @param optionsParser the parsed command line args.
   * @param extraPlugins extraneous plugins to use in addition to the strict dependency module.
   * @throws InvalidCommandLineException on any command line error
   */
  public JavaLibraryBuildRequest(
      OptionsParser optionsParser, List<BlazeJavaCompilerPlugin> extraPlugins)
      throws InvalidCommandLineException, IOException {
    this(optionsParser, extraPlugins, new DependencyModule.Builder());
  }

  /**
   * Constructs a build from a list of command args. Sets the same JavacRunner for both compilation
   * and annotation processing.
   *
   * @param optionsParser the parsed command line args.
   * @param extraPlugins extraneous plugins to use in addition to the strict dependency module.
   * @param depsBuilder a preconstructed dependency module builder.
   * @throws InvalidCommandLineException on any command line error
   */
  public JavaLibraryBuildRequest(
      OptionsParser optionsParser,
      List<BlazeJavaCompilerPlugin> extraPlugins,
      DependencyModule.Builder depsBuilder)
      throws InvalidCommandLineException, IOException {
    depsBuilder.setDirectJars(
        optionsParser.directJars().stream().map(Paths::get).collect(toImmutableSet()));
    if (optionsParser.getStrictJavaDeps() != null) {
      depsBuilder.setStrictJavaDeps(optionsParser.getStrictJavaDeps());
    }
    if (optionsParser.getOutputDepsProtoFile() != null) {
      depsBuilder.setOutputDepsProtoFile(Paths.get(optionsParser.getOutputDepsProtoFile()));
    }
    depsBuilder.addDepsArtifacts(asPaths(optionsParser.getDepsArtifacts()));
    depsBuilder.setPlatformJars(
        optionsParser.getBootClassPath().stream().map(Paths::get).collect(toImmutableSet()));
    if (optionsParser.reduceClasspathMode() != OptionsParser.ReduceClasspathMode.NONE) {
      depsBuilder.setReduceClasspath();
    }
    if (optionsParser.getTargetLabel() != null) {
      depsBuilder.setTargetLabel(optionsParser.getTargetLabel());
    }
    this.dependencyModule = depsBuilder.build();

    AnnotationProcessingModule.Builder processingBuilder = AnnotationProcessingModule.builder();
    if (optionsParser.getSourceGenDir() != null) {
      processingBuilder.setSourceGenDir(Paths.get(optionsParser.getSourceGenDir()));
    }
    if (optionsParser.getManifestProtoPath() != null) {
      processingBuilder.setManifestProtoPath(Paths.get(optionsParser.getManifestProtoPath()));
    }
    this.processingModule = processingBuilder.build();

    ImmutableList.Builder<BlazeJavaCompilerPlugin> pluginsBuilder =
        ImmutableList.<BlazeJavaCompilerPlugin>builder().add(dependencyModule.getPlugin());
    processingModule.registerPlugin(pluginsBuilder);
    pluginsBuilder.addAll(extraPlugins);
    this.plugins = pluginsBuilder.build();

    this.compressJar = optionsParser.compressJar();
    this.reduceClasspathMode = optionsParser.reduceClasspathMode();
    this.fullClasspathLength = optionsParser.fullClasspathLength();
    this.reducedClasspathLength = optionsParser.reducedClasspathLength();
    this.sourceFiles = new ArrayList<>(asPaths(optionsParser.getSourceFiles()));
    this.sourceJars = asPaths(optionsParser.getSourceJars());
    this.classPath = asPaths(optionsParser.getClassPath());
    this.sourcePath = asPaths(optionsParser.getSourcePath());
    this.bootClassPath = asPaths(optionsParser.getBootClassPath());
    this.system = asPath(optionsParser.getSystem());
    this.processorPath = asPaths(optionsParser.getProcessorPath());
    this.processorNames = optionsParser.getProcessorNames();
    this.builtinProcessorNames = ImmutableSet.copyOf(optionsParser.getBuiltinProcessorNames());
    // Since the default behavior of this tool with no arguments is "rm -fr <classDir>", let's not
    // default to ".", shall we?
    this.classDir = asPath(firstNonNull(optionsParser.getClassDir(), "classes"));
    this.tempDir = asPath(firstNonNull(optionsParser.getTempDir(), "_tmp"));
    this.outputJar = asPath(optionsParser.getOutputJar());
    this.nativeHeaderOutput = asPath(optionsParser.getNativeHeaderOutput());
    for (Map.Entry<String, List<String>> entry : optionsParser.getPostProcessors().entrySet()) {
      switch (entry.getKey()) {
        case "jacoco":
          this.jacocoInstrumentationProcessor =
              JacocoInstrumentationProcessor.create(entry.getValue());
          break;
        default:
          throw new AssertionError("unsupported post-processor " + entry.getKey());
      }
    }
    this.javacOpts = ImmutableList.copyOf(optionsParser.getJavacOpts());
    this.sourceGenDir = asPath(optionsParser.getSourceGenDir());
    this.generatedSourcesOutputJar = asPath(optionsParser.getGeneratedSourcesOutputJar());
    this.generatedClassOutputJar = asPath(optionsParser.getManifestProtoPath());
    this.targetLabel = optionsParser.getTargetLabel();
    this.injectingRuleKind = optionsParser.getInjectingRuleKind();
  }

  private static ImmutableList<Path> asPaths(Collection<String> paths) {
    return paths.stream().map(Paths::get).collect(toImmutableList());
  }

  @Nullable
  private static Path asPath(@Nullable String path) {
    return path != null ? Paths.get(path) : null;
  }

  public ImmutableList<String> getJavacOpts() {
    return javacOpts;
  }

  public void setJavacOpts(List<String> javacOpts) {
    this.javacOpts = ImmutableList.copyOf(javacOpts);
  }

  public Path getSourceGenDir() {
    return sourceGenDir;
  }

  public ImmutableList<Path> getSourcePath() {
    return sourcePath;
  }

  public Path getGeneratedSourcesOutputJar() {
    return generatedSourcesOutputJar;
  }

  public Path getGeneratedClassOutputJar() {
    return generatedClassOutputJar;
  }

  public ArrayList<Path> getSourceFiles() {
    // TODO(cushon): This is being modified after parsing to add files from source jars.
    return sourceFiles;
  }

  public ImmutableList<Path> getSourceJars() {
    return sourceJars;
  }

  public ImmutableList<Path> getClassPath() {
    return classPath;
  }

  public ImmutableList<Path> getBootClassPath() {
    return bootClassPath;
  }

  public Path getSystem() {
    return system;
  }

  public ImmutableList<Path> getProcessorPath() {
    return processorPath;
  }

  public List<String> getProcessors() {
    // TODO(bazel-team): This might be modified by a JavaLibraryBuilder to enable specific
    // annotation processors.
    return processorNames;
  }

  public Path getOutputJar() {
    return outputJar;
  }

  public Path getNativeHeaderOutput() {
    return nativeHeaderOutput;
  }

  public Path getClassDir() {
    return classDir;
  }

  public Path getTempDir() {
    return tempDir;
  }

  public Path getNativeHeaderDir() {
    return getTempDir().resolve("native_headers");
  }

  public JacocoInstrumentationProcessor getJacocoInstrumentationProcessor() {
    return jacocoInstrumentationProcessor;
  }

  public boolean compressJar() {
    return compressJar;
  }

  public OptionsParser.ReduceClasspathMode reduceClasspathMode() {
    return reduceClasspathMode;
  }

  public int fullClasspathLength() {
    return fullClasspathLength;
  }

  public int reducedClasspathLength() {
    return reducedClasspathLength;
  }

  public DependencyModule getDependencyModule() {
    return dependencyModule;
  }

  public AnnotationProcessingModule getProcessingModule() {
    return processingModule;
  }

  public ImmutableList<BlazeJavaCompilerPlugin> getPlugins() {
    return plugins;
  }

  @Nullable
  public String getTargetLabel() {
    return targetLabel;
  }

  @Nullable
  public String getInjectingRuleKind() {
    return injectingRuleKind;
  }

  public BlazeJavacArguments toBlazeJavacArguments(ImmutableList<Path> classPath) {
    BlazeJavacArguments.Builder builder =
        BlazeJavacArguments.builder()
            .classPath(classPath)
            .classOutput(getClassDir())
            .bootClassPath(getBootClassPath())
            .system(getSystem())
            .javacOptions(makeJavacArguments())
            .sourceFiles(ImmutableList.copyOf(getSourceFiles()))
            .processors(null)
            .builtinProcessors(builtinProcessorNames)
            .sourcePath(getSourcePath())
            .sourceOutput(getSourceGenDir())
            .processorPath(getProcessorPath())
            .plugins(getPlugins());
    // Performance optimization: when reduced classpaths are enabled, stop the compilation after
    // the first diagnostic that would result in fallback to the transitive classpath. The user
    // only sees diagnostics from the fallback compilation, so collecting additional diagnostics
    // from the reduced classpath compilation is a waste of time.
    // Exception: this doesn't hold if annotation processing is enabled, since diagnostics may be
    // resolved during subsequent processing rounds.
    if (reduceClasspathMode.equals(OptionsParser.ReduceClasspathMode.BAZEL_REDUCED)
        && getProcessors().isEmpty()) {
      builder.failFast(getProcessors().isEmpty());
    }
    if (getNativeHeaderOutput() != null) {
      builder.nativeHeaderOutput(getNativeHeaderDir());
    }
    return builder.build();
  }

  /** Constructs a command line that can be used for a javac invocation. */
  ImmutableList<String> makeJavacArguments() {
    ImmutableList.Builder<String> javacArguments = ImmutableList.builder();
    // default to -implicit:none, but allow the user to override with -implicit:class.
    javacArguments.add("-implicit:none");
    javacArguments.addAll(getJavacOpts());

    if (!getProcessors().isEmpty() && !getSourceFiles().isEmpty()) {
      // ImmutableSet.copyOf maintains order
      ImmutableSet<String> deduplicatedProcessorNames = ImmutableSet.copyOf(getProcessors());
      javacArguments.add("-processor");
      javacArguments.add(Joiner.on(',').join(deduplicatedProcessorNames));
    } else {
      // This is necessary because some jars contain discoverable annotation processors that
      // previously didn't run, and they break builds if the "-proc:none" option is not passed to
      // javac.
      javacArguments.add("-proc:none");
    }

    for (String option : getJavacOpts()) {
      if (option.startsWith("-J")) { // ignore the VM options.
        continue;
      }
      if (option.equals("-processor") || option.equals("-processorpath")) {
        throw new IllegalStateException(
            "Using "
                + option
                + " in javacopts is no longer supported."
                + " Use a java_plugin() rule instead.");
      }
    }

    return javacArguments.build();
  }
}
