// Copyright 2016 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.proto;

import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget.Mode;
import com.google.devtools.build.lib.rules.java.JavaCompilationArgsProvider;
import com.google.devtools.build.lib.rules.java.JavaConfiguration;
import com.google.devtools.build.lib.rules.java.JavaInfo;
import com.google.devtools.build.lib.syntax.Type;

public class StrictDepsUtils {

  /**
   * Used in JavaXXXProtoLibrary.java files to construct a JCAP from 'deps', where those were
   * populated by the Aspect it injected.
   *
   * <p>Takes care of strict deps.
   */
  public static JavaCompilationArgsProvider constructJcapFromAspectDeps(
      RuleContext ruleContext,
      Iterable<JavaProtoLibraryAspectProvider> javaProtoLibraryAspectProviders) {
    return constructJcapFromAspectDeps(
        ruleContext, javaProtoLibraryAspectProviders, /* alwaysStrict= */ false);
  }

  public static JavaCompilationArgsProvider constructJcapFromAspectDeps(
      RuleContext ruleContext,
      Iterable<JavaProtoLibraryAspectProvider> javaProtoLibraryAspectProviders,
      boolean alwaysStrict) {
    JavaCompilationArgsProvider strictCompProvider =
        JavaCompilationArgsProvider.merge(
            ruleContext.getPrerequisites("deps", Mode.TARGET, JavaCompilationArgsProvider.class));
    if (alwaysStrict || StrictDepsUtils.isStrictDepsJavaProtoLibrary(ruleContext)) {
      return strictCompProvider;
    } else {
      JavaCompilationArgsProvider.Builder nonStrictDirectJars =
          JavaCompilationArgsProvider.builder();
      for (JavaProtoLibraryAspectProvider p : javaProtoLibraryAspectProviders) {
        JavaCompilationArgsProvider args = p.getNonStrictCompArgs();
        nonStrictDirectJars
            .addRuntimeJars(args.getRuntimeJars())
            .addDirectCompileTimeJars(
                /* interfaceJars= */ args.getDirectCompileTimeJars(),
                /* fullJars= */ args.getDirectFullCompileTimeJars())
            .addTransitiveCompileTimeJars(args.getTransitiveCompileTimeJars())
            .addInstrumentationMetadata(args.getInstrumentationMetadata());
      }
      // Don't collect .jdeps recursively for legacy "feature" compatibility reasons. Collecting
      // .jdeps here is probably a mistake; see JavaCompilationArgsProvider#makeNonStrict.
      return nonStrictDirectJars
          .addCompileTimeJavaDependencyArtifacts(
              strictCompProvider.getCompileTimeJavaDependencyArtifacts())
          .build();
    }
  }

  /**
   * Creates a JavaCompilationArgsProvider that's used when java_proto_library sets strict_deps=0.
   * It contains the jars a proto_library (or the proto aspect) produced, as well as all transitive
   * proto jars, and the proto runtime jars, all described as direct dependencies.
   */
  public static JavaCompilationArgsProvider createNonStrictCompilationArgsProvider(
      Iterable<JavaProtoLibraryAspectProvider> deps,
      JavaCompilationArgsProvider directJars,
      ImmutableList<TransitiveInfoCollection> protoRuntimes) {
    JavaCompilationArgsProvider.Builder result = JavaCompilationArgsProvider.builder();
    result.addExports(directJars);
    for (JavaProtoLibraryAspectProvider p : deps) {
      result.addExports(p.getNonStrictCompArgs());
    }
    for (TransitiveInfoCollection t : protoRuntimes) {
      JavaCompilationArgsProvider p = JavaInfo.getProvider(JavaCompilationArgsProvider.class, t);
      if (p != null) {
        result.addExports(p);
      }
    }
    return result.build();
  }

  /**
   * Returns true iff 'ruleContext' should enforce strict-deps.
   *
   * <p>Using this method requires requesting the JavaConfiguration fragment.
   */
  public static boolean isStrictDepsJavaProtoLibrary(RuleContext ruleContext) {
    if (ruleContext.getFragment(JavaConfiguration.class).strictDepsJavaProtos()
        || !ruleContext.attributes().has("strict_deps", Type.BOOLEAN)) {
      return true;
    }
    return (boolean) ruleContext.getRule().getAttributeContainer().getAttr("strict_deps");
  }
}
