// 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 com.google.common.base.Ascii;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration.Fragment;
import com.google.devtools.build.lib.analysis.config.BuildOptions;
import com.google.devtools.build.lib.analysis.config.CoreOptionConverters.StrictDepsMode;
import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException;
import com.google.devtools.build.lib.analysis.skylark.annotations.SkylarkConfigurationField;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.EventHandler;
import com.google.devtools.build.lib.skylarkbuildapi.java.JavaConfigurationApi;
import com.google.devtools.common.options.TriState;
import java.util.Map;
import javax.annotation.Nullable;

/** A java compiler configuration containing the flags required for compilation. */
@Immutable
public final class JavaConfiguration extends Fragment implements JavaConfigurationApi {

  /** Values for the --java_classpath option */
  public enum JavaClasspathMode {
    /** Use full transitive classpaths, the default behavior. */
    OFF,
    /** JavaBuilder computes the reduced classpath before invoking javac. */
    JAVABUILDER,
    /** Bazel computes the reduced classpath and tries it in a separate action invocation. */
    BAZEL
  }

  /** Values for the --experimental_one_version_enforcement option */
  public enum OneVersionEnforcementLevel {
    /** Don't attempt to check for one version violations (the default) */
    OFF,
    /**
     * Check for one version violations, emit warnings to stderr if any are found, but don't break
     * the binary.
     */
    WARNING,
    /**
     * Check for one version violations, emit warnings to stderr if any are found, and break the
     * rule if it's found.
     */
    ERROR
  }

  /** Values for the --experimental_import_deps_checking option */
  public enum ImportDepsCheckingLevel {
    /** Turn off the import_deps checking. */
    OFF,
    /** Emit warnings when the dependencies of java_import/aar_import are not complete. */
    WARNING,
    /** Emit errors when the dependencies of java_import/aar_import are not complete. */
    ERROR
  }

  private final ImmutableList<String> commandLineJavacFlags;
  private final Label javaLauncherLabel;
  private final boolean useIjars;
  private final boolean useHeaderCompilation;
  private final boolean generateJavaDeps;
  private final boolean strictDepsJavaProtos;
  private final boolean isDisallowStrictDepsForJpl;
  private final OneVersionEnforcementLevel enforceOneVersion;
  private final boolean enforceOneVersionOnJavaTests;
  private final ImportDepsCheckingLevel importDepsCheckingLevel;
  private final boolean allowRuntimeDepsOnNeverLink;
  private final JavaClasspathMode javaClasspath;
  private final boolean inmemoryJdepsFiles;
  private final ImmutableList<String> defaultJvmFlags;
  private final ImmutableList<String> checkedConstraints;
  private final StrictDepsMode strictJavaDeps;
  private final String fixDepsTool;
  private final Label proguardBinary;
  private final ImmutableList<Label> extraProguardSpecs;
  private final TriState bundleTranslations;
  private final ImmutableList<Label> translationTargets;
  private final ImmutableMap<String, Optional<Label>> bytecodeOptimizers;
  private final boolean enforceProguardFileExtension;
  private final Label toolchainLabel;
  private final Label runtimeLabel;
  private final boolean explicitJavaTestDeps;
  private final boolean jplPropagateCcLinkParamsStore;
  private final boolean addTestSupportToCompileTimeDeps;
  private final boolean isJlplStrictDepsEnforced;
  private final ImmutableList<Label> pluginList;
  private final boolean requireJavaToolchainHeaderCompilerDirect;
  private final boolean disallowResourceJars;
  private final boolean loadJavaRulesFromBzl;
  private final boolean disallowLegacyJavaToolchainFlags;
  private final boolean experimentalTurbineAnnotationProcessing;

  // TODO(dmarting): remove once we have a proper solution for #2539
  private final boolean useLegacyBazelJavaTest;

  JavaConfiguration(JavaOptions javaOptions) throws InvalidConfigurationException {
    this.commandLineJavacFlags =
        ImmutableList.copyOf(JavaHelper.tokenizeJavaOptions(javaOptions.javacOpts));
    this.javaLauncherLabel = javaOptions.javaLauncher;
    this.useIjars = javaOptions.useIjars;
    this.useHeaderCompilation = javaOptions.headerCompilation;
    this.generateJavaDeps =
        javaOptions.javaDeps || javaOptions.javaClasspath != JavaClasspathMode.OFF;
    this.javaClasspath = javaOptions.javaClasspath;
    this.inmemoryJdepsFiles = javaOptions.inmemoryJdepsFiles;
    this.defaultJvmFlags = ImmutableList.copyOf(javaOptions.jvmOpts);
    this.checkedConstraints = ImmutableList.copyOf(javaOptions.checkedConstraints);
    this.strictJavaDeps = javaOptions.strictJavaDeps;
    this.fixDepsTool = javaOptions.fixDepsTool;
    this.proguardBinary = javaOptions.proguard;
    this.extraProguardSpecs = ImmutableList.copyOf(javaOptions.extraProguardSpecs);
    this.enforceProguardFileExtension = javaOptions.enforceProguardFileExtension;
    this.bundleTranslations = javaOptions.bundleTranslations;
    this.toolchainLabel = javaOptions.javaToolchain;
    this.runtimeLabel = javaOptions.javaBase;
    this.useLegacyBazelJavaTest = javaOptions.legacyBazelJavaTest;
    this.strictDepsJavaProtos = javaOptions.strictDepsJavaProtos;
    this.isDisallowStrictDepsForJpl = javaOptions.isDisallowStrictDepsForJpl;
    this.enforceOneVersion = javaOptions.enforceOneVersion;
    this.enforceOneVersionOnJavaTests = javaOptions.enforceOneVersionOnJavaTests;
    this.importDepsCheckingLevel = javaOptions.importDepsCheckingLevel;
    this.allowRuntimeDepsOnNeverLink = javaOptions.allowRuntimeDepsOnNeverLink;
    this.explicitJavaTestDeps = javaOptions.explicitJavaTestDeps;
    this.jplPropagateCcLinkParamsStore = javaOptions.jplPropagateCcLinkParamsStore;
    this.isJlplStrictDepsEnforced = javaOptions.isJlplStrictDepsEnforced;
    this.disallowResourceJars = javaOptions.disallowResourceJars;
    this.loadJavaRulesFromBzl = javaOptions.loadJavaRulesFromBzl;
    this.addTestSupportToCompileTimeDeps = javaOptions.addTestSupportToCompileTimeDeps;

    ImmutableList.Builder<Label> translationsBuilder = ImmutableList.builder();
    for (String s : javaOptions.translationTargets) {
      try {
        Label label = Label.parseAbsolute(s, ImmutableMap.of());
        translationsBuilder.add(label);
      } catch (LabelSyntaxException e) {
        throw new InvalidConfigurationException(
            "Invalid translations target '"
                + s
                + "', make "
                + "sure it uses correct absolute path syntax.",
            e);
      }
    }
    this.translationTargets = translationsBuilder.build();

    ImmutableMap.Builder<String, Optional<Label>> optimizersBuilder = ImmutableMap.builder();
    for (Map.Entry<String, Label> optimizer : javaOptions.bytecodeOptimizers.entrySet()) {
      String mnemonic = optimizer.getKey();
      if (optimizer.getValue() == null && !"Proguard".equals(mnemonic)) {
        throw new InvalidConfigurationException("Must supply label for optimizer " + mnemonic);
      }
      optimizersBuilder.put(mnemonic, Optional.fromNullable(optimizer.getValue()));
    }
    this.bytecodeOptimizers = optimizersBuilder.build();
    this.pluginList = ImmutableList.copyOf(javaOptions.pluginList);
    this.requireJavaToolchainHeaderCompilerDirect =
        javaOptions.requireJavaToolchainHeaderCompilerDirect;
    this.disallowLegacyJavaToolchainFlags = javaOptions.disallowLegacyJavaToolchainFlags;
    this.experimentalTurbineAnnotationProcessing =
        javaOptions.experimentalTurbineAnnotationProcessing;

    if (javaOptions.disallowLegacyJavaToolchainFlags) {
      if (!javaOptions.javaBase.equals(javaOptions.defaultJavaBase())) {
        throw new InvalidConfigurationException(
            String.format(
                "--javabase=%s is no longer supported, use --platforms instead (see #7849)",
                javaOptions.javaBase));
      }
      if (!javaOptions.getHostJavaBase().equals(javaOptions.defaultHostJavaBase())) {
        throw new InvalidConfigurationException(
            String.format(
                "--host_javabase=%s is no longer supported, use --platforms instead (see #7849)",
                javaOptions.getHostJavaBase()));
      }
      if (!javaOptions.javaToolchain.equals(javaOptions.defaultJavaToolchain())) {
        throw new InvalidConfigurationException(
            String.format(
                "--java_toolchain=%s is no longer supported, use --platforms instead (see #7849)",
                javaOptions.javaToolchain));
      }
      if (!javaOptions.hostJavaToolchain.equals(javaOptions.defaultJavaToolchain())) {
        throw new InvalidConfigurationException(
            String.format(
                "--host_java_toolchain=%s is no longer supported, use --platforms instead (see"
                    + " #7849)",
                javaOptions.hostJavaToolchain));
      }
    }
  }

  @Override
  // TODO(bazel-team): this is the command-line passed options, we should remove from skylark
  // probably.
  public ImmutableList<String> getDefaultJavacFlags() {
    return commandLineJavacFlags;
  }

  @Override
  public String getStrictJavaDepsName() {
    return Ascii.toLowerCase(strictJavaDeps.name());
  }

  @Override
  public void reportInvalidOptions(EventHandler reporter, BuildOptions buildOptions) {
    if ((bundleTranslations == TriState.YES) && translationTargets.isEmpty()) {
      reporter.handle(
          Event.error(
              "Translations enabled, but no message translations specified. "
                  + "Use '--message_translations' to select the message translations to use"));
    }
  }

  /** Returns true iff Java compilation should use ijars. */
  public boolean getUseIjars() {
    return useIjars;
  }

  /** Returns true iff Java header compilation is enabled. */
  public boolean useHeaderCompilation() {
    return useHeaderCompilation;
  }

  /** Returns true iff dependency information is generated after compilation. */
  public boolean getGenerateJavaDeps() {
    return generateJavaDeps;
  }

  public JavaClasspathMode getReduceJavaClasspath() {
    return javaClasspath;
  }

  public boolean inmemoryJdepsFiles() {
    return inmemoryJdepsFiles;
  }

  public ImmutableList<String> getDefaultJvmFlags() {
    return defaultJvmFlags;
  }

  public ImmutableList<String> getCheckedConstraints() {
    return checkedConstraints;
  }

  public StrictDepsMode getStrictJavaDeps() {
    return strictJavaDeps;
  }

  public StrictDepsMode getFilteredStrictJavaDeps() {
    StrictDepsMode strict = getStrictJavaDeps();
    switch (strict) {
      case STRICT:
      case DEFAULT:
        return StrictDepsMode.ERROR;
      default: // OFF, WARN, ERROR
        return strict;
    }
  }

  /** Which tool to use for fixing dependency errors. */
  public String getFixDepsTool() {
    return fixDepsTool;
  }

  /** @return proper label only if --java_launcher= is specified, otherwise null. */
  public Label getJavaLauncherLabel() {
    return javaLauncherLabel;
  }

  /** Returns the label provided with --proguard_top, if any. */
  @SkylarkConfigurationField(
      name = "proguard_top",
      doc = "Returns the label provided with --proguard_top, if any.",
      defaultInToolRepository = true)
  @Nullable
  public Label getProguardBinary() {
    return proguardBinary;
  }

  /** Returns all labels provided with --extra_proguard_specs. */
  public ImmutableList<Label> getExtraProguardSpecs() {
    return extraProguardSpecs;
  }

  /** Returns whether ProGuard configuration files are required to use a *.pgcfg extension. */
  public boolean enforceProguardFileExtension() {
    return enforceProguardFileExtension;
  }

  /** Returns the raw translation targets. */
  public ImmutableList<Label> getTranslationTargets() {
    return translationTargets;
  }

  /** Returns true if the we should build translations. */
  public boolean buildTranslations() {
    return (bundleTranslations != TriState.NO) && !translationTargets.isEmpty();
  }

  /** Returns whether translations were explicitly disabled. */
  public boolean isTranslationsDisabled() {
    return bundleTranslations == TriState.NO;
  }

  /** Returns the label of the default java_toolchain rule */
  @SkylarkConfigurationField(
      name = "java_toolchain",
      doc = "Returns the label of the default java_toolchain rule.",
      defaultLabel = "//tools/jdk:toolchain",
      defaultInToolRepository = true)
  public Label getToolchainLabel() {
    if (disallowLegacyJavaToolchainFlags) {
      throw new IllegalStateException("--java_toolchain is no longer supported");
    }
    return toolchainLabel;
  }

  /** Returns the label of the {@code java_runtime} rule representing the JVM in use. */
  public Label getRuntimeLabel() {
    return runtimeLabel;
  }

  /** Returns ordered list of optimizers to run. */
  public ImmutableMap<String, Optional<Label>> getBytecodeOptimizers() {
    return bytecodeOptimizers;
  }

  /**
   * Returns true if java_test in Bazel should behave in legacy mode that existed before we
   * open-sourced our test runner.
   */
  public boolean useLegacyBazelJavaTest() {
    return useLegacyBazelJavaTest;
  }


  /**
   * Make it mandatory for java_test targets to explicitly declare any JUnit or Hamcrest
   * dependencies instead of accidentally obtaining them from the TestRunner's dependencies.
   */
  public boolean explicitJavaTestDeps() {
    return explicitJavaTestDeps;
  }

  /**
   * Returns an enum representing whether or not Bazel should attempt to enforce one-version
   * correctness on java_binary rules using the 'oneversion' tool in the java_toolchain.
   *
   * <p>One-version correctness will inspect for multiple non-identical versions of java classes in
   * the transitive dependencies for a java_binary.
   */
  public OneVersionEnforcementLevel oneVersionEnforcementLevel() {
    return enforceOneVersion;
  }

  public boolean enforceOneVersionOnJavaTests() {
    return enforceOneVersionOnJavaTests;
  }

  public ImportDepsCheckingLevel getImportDepsCheckingLevel() {
    return importDepsCheckingLevel;
  }

  public boolean getAllowRuntimeDepsOnNeverLink() {
    return allowRuntimeDepsOnNeverLink;
  }

  public boolean strictDepsJavaProtos() {
    return strictDepsJavaProtos;
  }

  public boolean isDisallowStrictDepsForJpl() {
    return isDisallowStrictDepsForJpl;
  }

  public boolean jplPropagateCcLinkParamsStore() {
    return jplPropagateCcLinkParamsStore;
  }

  public boolean addTestSupportToCompileTimeDeps() {
    return addTestSupportToCompileTimeDeps;
  }

  public boolean isJlplStrictDepsEnforced() {
    return isJlplStrictDepsEnforced;
  }

  @Override
  public ImmutableList<Label> getPlugins() {
    return pluginList;
  }

  public boolean requireJavaToolchainHeaderCompilerDirect() {
    return requireJavaToolchainHeaderCompilerDirect;
  }

  public boolean disallowResourceJars() {
    return disallowResourceJars;
  }

  public boolean loadJavaRulesFromBzl() {
    return loadJavaRulesFromBzl;
  }

  public boolean experimentalTurbineAnnotationProcessing() {
    return experimentalTurbineAnnotationProcessing;
  }
}
