// 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.auto.value.AutoValue;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
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.PackageSpecificationProvider;
import com.google.devtools.build.lib.analysis.ProviderCollection;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.RuleErrorConsumer;
import com.google.devtools.build.lib.analysis.platform.ToolchainInfo;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.collect.nestedset.Depset;
import com.google.devtools.build.lib.collect.nestedset.Depset.TypeException;
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.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.packages.Info;
import com.google.devtools.build.lib.packages.PackageSpecification.PackageGroupContents;
import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory.RuleErrorException;
import com.google.devtools.build.lib.packages.StarlarkInfo;
import com.google.devtools.build.lib.packages.StarlarkInfoWithSchema;
import com.google.devtools.build.lib.packages.StarlarkProviderWrapper;
import com.google.devtools.build.lib.packages.StructImpl;
import com.google.devtools.build.lib.rules.java.JavaPluginInfo.JavaPluginData;
import javax.annotation.Nullable;
import net.starlark.java.eval.Dict;
import net.starlark.java.eval.EvalException;
import net.starlark.java.eval.Sequence;
import net.starlark.java.eval.Starlark;
import net.starlark.java.eval.StarlarkValue;

/** Information about the JDK used by the <code>java_*</code> rules. */
@Immutable
public final class JavaToolchainProvider extends StarlarkInfoWrapper {

  public static final StarlarkProviderWrapper<JavaToolchainProvider> PROVIDER = new Provider();

  private JavaToolchainProvider(StarlarkInfo underlying) {
    super(underlying);
  }

  @Override
  public int hashCode() {
    try {
      // StructImpl.hashcode() is too expensive, just the label should be enough
      return getToolchainLabel().hashCode();
    } catch (RuleErrorException e) {
      throw new IllegalStateException(e);
    }
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj) {
      return true;
    }
    if (!(obj instanceof JavaToolchainProvider)) {
      return false;
    }
    return underlying.equals(((JavaToolchainProvider) obj).underlying);
  }

  /** Returns the Java Toolchain associated with the rule being analyzed or {@code null}. */
  public static JavaToolchainProvider from(RuleContext ruleContext) {
    ToolchainInfo toolchainInfo =
        ruleContext.getToolchainInfo(
            ruleContext
                .getPrerequisite(JavaRuleClasses.JAVA_TOOLCHAIN_TYPE_ATTRIBUTE_NAME)
                .getLabel());
    return from(toolchainInfo, ruleContext);
  }

  @VisibleForTesting
  public static JavaToolchainProvider from(ProviderCollection collection) {
    ToolchainInfo toolchainInfo = collection.get(ToolchainInfo.PROVIDER);
    return from(toolchainInfo, null);
  }

  @Nullable
  private static JavaToolchainProvider from(
      ToolchainInfo toolchainInfo, @Nullable RuleErrorConsumer errorConsumer) {
    if (toolchainInfo != null) {
      try {
        JavaToolchainProvider provider =
            JavaToolchainProvider.PROVIDER.wrap(toolchainInfo.getValue("java", Info.class));
        if (provider != null) {
          return provider;
        }
      } catch (EvalException | RuleErrorException e) {
        if (errorConsumer != null) {
          errorConsumer.ruleError(
              String.format("There was an error reading the Java toolchain: %s", e));
        }
      }
    }
    if (errorConsumer != null) {
      errorConsumer.ruleError("The selected Java toolchain is not a JavaToolchainProvider");
    }
    return null;
  }

  /** Returns the label for this {@code java_toolchain}. */
  public Label getToolchainLabel() throws RuleErrorException {
    return Preconditions.checkNotNull(getUnderlyingValue("label", Label.class));
  }

  /** Returns the target Java bootclasspath. */
  public BootClassPathInfo getBootclasspath() throws RuleErrorException {
    return BootClassPathInfo.PROVIDER.wrap(getUnderlyingValue("_bootclasspath_info", Info.class));
  }

  /** Returns the {@link Artifact}s of compilation tools. */
  public NestedSet<Artifact> getTools() throws RuleErrorException {
    return getUnderlyingNestedSet("tools", Artifact.class);
  }

  /** Returns the {@link JavaToolchainTool} for JavaBuilder */
  public JavaToolchainTool getJavaBuilder() throws RuleErrorException {
    return JavaToolchainTool.fromStarlark(getUnderlyingValue("_javabuilder", StructImpl.class));
  }

  /** Returns the {@link JavaToolchainTool} for the header compiler */
  @Nullable
  public JavaToolchainTool getHeaderCompiler() throws RuleErrorException {
    return JavaToolchainTool.fromStarlark(getUnderlyingValue("_header_compiler", StructImpl.class));
  }

  /**
   * Returns the {@link FilesToRunProvider} of the Header Compiler deploy jar for direct-classpath,
   * non-annotation processing actions.
   */
  @Nullable
  public JavaToolchainTool getHeaderCompilerDirect() throws RuleErrorException {
    return JavaToolchainTool.fromStarlark(
        getUnderlyingValue("_header_compiler_direct", StructImpl.class));
  }

  @Nullable
  @VisibleForTesting
  public StructImpl getAndroidLint() throws RuleErrorException {
    return getUnderlyingValue("_android_linter", StructImpl.class);
  }

  @Nullable
  public JspecifyInfo jspecifyInfo() throws RuleErrorException {
    return JspecifyInfo.fromStarlark(getUnderlyingValue("_jspecify_info", StarlarkValue.class));
  }

  @Nullable
  public JavaToolchainTool getBytecodeOptimizer() throws RuleErrorException {
    return JavaToolchainTool.fromStarlark(
        getUnderlyingValue("_bytecode_optimizer", StructImpl.class));
  }

  public ImmutableList<Artifact> getLocalJavaOptimizationConfiguration() throws RuleErrorException {
    return getUnderlyingSequence("_local_java_optimization_config", Artifact.class)
        .getImmutableList();
  }

  /** Returns class names of annotation processors that are built in to the header compiler. */
  public ImmutableSet<String> getHeaderCompilerBuiltinProcessors() throws RuleErrorException {
    return getUnderlyingNestedSet("_header_compiler_builtin_processors", String.class).toSet();
  }

  public ImmutableSet<String> getReducedClasspathIncompatibleProcessors()
      throws RuleErrorException {
    return getUnderlyingNestedSet("_reduced_classpath_incompatible_processors", String.class)
        .toSet();
  }

  /**
   * Returns {@code true} if header compilation should be forcibly disabled, overriding
   * --java_header_compilation.
   */
  public boolean getForciblyDisableHeaderCompilation() throws RuleErrorException {
    return getUnderlyingValue("_forcibly_disable_header_compilation", Boolean.class);
  }

  /** Returns the {@link FilesToRunProvider} of the SingleJar tool. */
  public FilesToRunProvider getSingleJar() throws RuleErrorException {
    return getUnderlyingValue("single_jar", FilesToRunProvider.class);
  }

  /**
   * Return the {@link FilesToRunProvider} of the tool that enforces one-version compliance of Java
   * binaries.
   */
  @Nullable
  public FilesToRunProvider getOneVersionBinary() throws RuleErrorException {
    return getUnderlyingValue("_one_version_tool", FilesToRunProvider.class);
  }

  /** Return the {@link Artifact} of the allowlist used by the one-version compliance checker. */
  @Nullable
  public Artifact getOneVersionAllowlist() throws RuleErrorException {
    return getUnderlyingValue("_one_version_allowlist", Artifact.class);
  }

  /**
   * Return the {@link Artifact} of the one-version allowlist for tests used by the one-version
   * compliance checker.
   */
  @Nullable
  public Artifact oneVersionAllowlistForTests() throws RuleErrorException {
    return getUnderlyingValue("_one_version_allowlist_for_tests", Artifact.class);
  }

  /** Returns the {@link Artifact} of the GenClass deploy jar */
  public Artifact getGenClass() throws RuleErrorException {
    return getUnderlyingValue("_gen_class", Artifact.class);
  }

  /**
   * Returns the {@link Artifact} of the latest timezone data resource jar that can be loaded by
   * Java 8 binaries.
   */
  @Nullable
  @VisibleForTesting
  public Artifact getTimezoneData() throws RuleErrorException {
    return getUnderlyingValue("_timezone_data", Artifact.class);
  }

  /** Returns the ijar executable */
  public FilesToRunProvider getIjar() throws RuleErrorException {
    return getUnderlyingValue("ijar", FilesToRunProvider.class);
  }

  /** Returns the map of target environment-specific javacopts. */
  private NestedSet<String> getCompatibleJavacOptions(String key) throws RuleErrorException {
    try {
      return Dict.noneableCast(
              underlying.getValue("_compatible_javacopts"),
              String.class,
              Depset.class,
              "_compatible_javacopts")
          .getOrDefault(
              key, Depset.of(String.class, NestedSetBuilder.emptySet(Order.NAIVE_LINK_ORDER)))
          .getSet(String.class);
    } catch (TypeException | EvalException e) {
      throw new RuleErrorException(e);
    }
  }

  public ImmutableList<String> getCompatibleJavacOptionsAsList(String key)
      throws RuleErrorException {
    return JavaHelper.tokenizeJavaOptions(getCompatibleJavacOptions(key));
  }

  /** Returns the list of default options for the java compiler. */
  public NestedSet<String> getJavacOptions(RuleContext ruleContext) throws RuleErrorException {
    NestedSetBuilder<String> result = NestedSetBuilder.naiveLinkOrder();
    result.addTransitive(javacOptions());
    if (ruleContext != null) {
      // TODO(b/78512644): require ruleContext to be non-null after java_common.default_javac_opts
      // is turned down
      result.addTransitive(ruleContext.getFragment(JavaConfiguration.class).getDefaultJavacFlags());
    }
    return result.build();
  }

  private NestedSet<String> javacOptions() throws RuleErrorException {
    return getUnderlyingNestedSet("_javacopts", String.class);
  }

  public ImmutableList<String> getJavacOptionsAsList(RuleContext ruleContext)
      throws RuleErrorException {
    ImmutableList.Builder<String> result =
        ImmutableList.<String>builder().addAll(JavaHelper.tokenizeJavaOptions(javacOptions()));
    if (ruleContext != null) {
      // TODO(b/78512644): require ruleContext to be non-null after java_common.default_javac_opts
      // is turned down
      result.addAll(
          ruleContext.getFragment(JavaConfiguration.class).getDefaultJavacFlagsForStarlarkAsList());
    }
    return result.build();
  }

  /**
   * Returns the NestedSet of default options for the JVM running the java compiler and associated
   * tools.
   */
  public NestedSet<String> getJvmOptions() throws RuleErrorException {
    return getUnderlyingNestedSet("jvm_opt", String.class);
  }

  /** Returns whether JavaBuilders supports running as a persistent worker or not. */
  public boolean getJavacSupportsWorkers() throws RuleErrorException {
    return getUnderlyingValue("_javac_supports_workers", Boolean.class);
  }

  /** Returns whether JavaBuilders supports running persistent workers in multiplex mode */
  public boolean getJavacSupportsMultiplexWorkers() throws RuleErrorException {
    return getUnderlyingValue("_javac_supports_multiplex_workers", Boolean.class);
  }

  /** Returns whether JavaBuilders supports running persistent workers with cancellation */
  public boolean getJavacSupportsWorkerCancellation() throws RuleErrorException {
    return getUnderlyingValue("_javac_supports_worker_cancellation", Boolean.class);
  }

  /** Returns the global {@code java_package_configuration} data. */
  public ImmutableList<JavaPackageConfigurationProvider> packageConfiguration()
      throws RuleErrorException {
    return JavaPackageConfigurationProvider.wrapSequence(
        getUnderlyingSequence("_package_configuration", StructImpl.class));
  }

  public FilesToRunProvider getJacocoRunner() throws RuleErrorException {
    return getUnderlyingValue("jacocorunner", FilesToRunProvider.class);
  }

  public FilesToRunProvider getProguardAllowlister() throws RuleErrorException {
    return getUnderlyingValue("proguard_allowlister", FilesToRunProvider.class);
  }

  public JavaRuntimeInfo getJavaRuntime() throws RuleErrorException {
    return JavaRuntimeInfo.PROVIDER.wrap(getUnderlyingValue("java_runtime", Info.class));
  }

  @AutoValue
  abstract static class JspecifyInfo {

    abstract JavaPluginData jspecifyProcessor();

    abstract NestedSet<Artifact> jspecifyImplicitDeps();

    abstract ImmutableList<String> jspecifyJavacopts();

    abstract ImmutableList<PackageSpecificationProvider> jspecifyPackages();

    boolean matches(Label label) {
      for (PackageSpecificationProvider provider : jspecifyPackages()) {
        for (PackageGroupContents specifications : provider.getPackageSpecifications().toList()) {
          if (specifications.containsPackage(label.getPackageIdentifier())) {
            return true;
          }
        }
      }
      return false;
    }

    @Nullable
    static JspecifyInfo fromStarlark(@Nullable StarlarkValue value) throws RuleErrorException {
      if (value == null || value == Starlark.NONE) {
        return null;
      } else if (value instanceof StructImpl) {
        StructImpl struct = (StructImpl) value;
        try {
          return new AutoValue_JavaToolchainProvider_JspecifyInfo(
              JavaPluginData.wrap(struct.getValue("processor")),
              Depset.noneableCast(
                  struct.getValue("implicit_deps"), Artifact.class, "implicit_deps"),
              Sequence.noneableCast(struct.getValue("javacopts"), String.class, "javacopts")
                  .getImmutableList(),
              Sequence.noneableCast(
                      struct.getValue("packages"), PackageSpecificationProvider.class, "packages")
                  .getImmutableList());
        } catch (EvalException e) {
          throw new RuleErrorException(e);
        }
      } else {
        throw new RuleErrorException("expected JspecifyInfo, got: " + Starlark.type(value));
      }
    }
  }

  private static class Provider extends StarlarkProviderWrapper<JavaToolchainProvider> {

    private Provider() {
      super(
          Label.parseCanonicalUnchecked("@_builtins//:common/java/java_toolchain.bzl"),
          "JavaToolchainInfo");
    }

    @Override
    public JavaToolchainProvider wrap(Info value) throws RuleErrorException {
      if (value instanceof StarlarkInfoWithSchema
          && value.getProvider().getKey().equals(getKey())) {
        return new JavaToolchainProvider((StarlarkInfo) value);
      } else {
        throw new RuleErrorException(
            "got value of type '" + Starlark.type(value) + "', want 'JavaToolchainInfo'");
      }
    }
  }
}
