// Copyright 2022 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.analysis.constraints;

import static com.google.common.collect.ImmutableList.toImmutableList;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.ConfiguredTargetValue;
import com.google.devtools.build.lib.analysis.DependencyKind;
import com.google.devtools.build.lib.analysis.FileProvider;
import com.google.devtools.build.lib.analysis.FilesToRunProvider;
import com.google.devtools.build.lib.analysis.IncompatiblePlatformProvider;
import com.google.devtools.build.lib.analysis.Runfiles;
import com.google.devtools.build.lib.analysis.RunfilesProvider;
import com.google.devtools.build.lib.analysis.TargetAndConfiguration;
import com.google.devtools.build.lib.analysis.TransitiveDependencyState;
import com.google.devtools.build.lib.analysis.TransitiveInfoProviderMapBuilder;
import com.google.devtools.build.lib.analysis.config.BuildConfigurationValue;
import com.google.devtools.build.lib.analysis.config.ConfigConditions;
import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget;
import com.google.devtools.build.lib.analysis.platform.ConstraintValueInfo;
import com.google.devtools.build.lib.analysis.platform.PlatformInfo;
import com.google.devtools.build.lib.analysis.platform.PlatformProviderUtils;
import com.google.devtools.build.lib.analysis.test.TestActionBuilder;
import com.google.devtools.build.lib.analysis.test.TestConfiguration;
import com.google.devtools.build.lib.analysis.test.TestProvider;
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.events.ExtendedEventHandler;
import com.google.devtools.build.lib.packages.BuildType;
import com.google.devtools.build.lib.packages.ConfiguredAttributeMapper;
import com.google.devtools.build.lib.packages.ConfiguredAttributeMapper.ValidationException;
import com.google.devtools.build.lib.packages.PackageSpecification;
import com.google.devtools.build.lib.packages.PackageSpecification.PackageGroupContents;
import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.packages.Target;
import com.google.devtools.build.lib.skyframe.ConfiguredTargetAndData;
import com.google.devtools.build.lib.skyframe.ConfiguredTargetKey;
import com.google.devtools.build.lib.skyframe.RuleConfiguredTargetValue;
import com.google.devtools.build.lib.util.OrderedSetMultimap;
import com.google.devtools.build.skyframe.SkyValue;
import com.google.devtools.build.skyframe.state.StateMachine;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
import javax.annotation.Nullable;

/**
 * Helpers for creating configured targets that are incompatible.
 *
 * <p>A target is considered incompatible if any of the following applies:
 *
 * <ol>
 *   <li>The target's <code>target_compatible_with</code> attribute specifies a constraint that is
 *       not present in the target platform. The target is said to be "directly incompatible".
 *   <li>One or more of the target's dependencies is incompatible. The target is said to be
 *       "indirectly incompatible."
 * </ol>
 *
 * The intent of these helpers is that they get called as early in the analysis phase as possible.
 * That's why there are two helpers instead of just one. The first helper determines direct
 * incompatibility very early in the analysis phase. If a target is not directly incompatible, the
 * dependencies need to be analysed and then we can check for indirect incompatibility. Doing these
 * checks as early as possible allows us to skip analysing unused dependencies and ignore unused
 * toolchains.
 *
 * <p>See https://bazel.build/docs/platforms#skipping-incompatible-targets for more information on
 * incompatible target skipping.
 */
public class IncompatibleTargetChecker {
  /**
   * Creates an incompatible configured target if it is "directly incompatible".
   *
   * <p>In other words, this state machine checks if a target is incompatible because of its
   * "target_compatible_with" attribute.
   *
   * <p>Outputs an {@code Optional} {@link RuleConfiguredTargetValue} as follows.
   *
   * <ul>
   *   <li>{@code Optional.empty()}: The target is not directly incompatible. Analysis can continue.
   *   <li>{@code !Optional.empty()}: The target is directly incompatible. Analysis should not
   *       continue.
   * </ul>
   */
  public static class IncompatibleTargetProducer implements StateMachine, Consumer<SkyValue> {
    private final TargetAndConfiguration targetAndConfiguration;
    private final ConfiguredTargetKey configuredTargetKey;
    private final ConfigConditions configConditions;
    // Non-null when the target has an associated rule and does not opt out of toolchain resolution.
    @Nullable private final PlatformInfo platformInfo;
    private final TransitiveDependencyState transitiveState;

    private final ResultSink sink;

    private final StateMachine runAfter;

    private final ImmutableList.Builder<ConstraintValueInfo> invalidConstraintValuesBuilder =
        new ImmutableList.Builder<>();

    /** Sink for the output of this state machine. */
    public interface ResultSink {
      void acceptIncompatibleTarget(Optional<RuleConfiguredTargetValue> incompatibleTarget);

      void acceptValidationException(ValidationException e);
    }

    public IncompatibleTargetProducer(
        TargetAndConfiguration targetAndConfiguration,
        ConfiguredTargetKey configuredTargetKey,
        ConfigConditions configConditions,
        @Nullable PlatformInfo platformInfo,
        TransitiveDependencyState transitiveState,
        ResultSink sink,
        StateMachine runAfter) {
      this.targetAndConfiguration = targetAndConfiguration;
      this.configuredTargetKey = configuredTargetKey;
      this.configConditions = configConditions;
      this.platformInfo = platformInfo;
      this.transitiveState = transitiveState;
      this.sink = sink;
      this.runAfter = runAfter;
    }

    @Override
    public StateMachine step(Tasks tasks, ExtendedEventHandler listener) {
      Rule rule = targetAndConfiguration.getTarget().getAssociatedRule();
      if (rule == null || !rule.useToolchainResolution() || platformInfo == null) {
        sink.acceptIncompatibleTarget(Optional.empty());
        return runAfter;
      }

      BuildConfigurationValue configuration = targetAndConfiguration.getConfiguration();
      // Retrieves the label list for the target_compatible_with attribute.
      ConfiguredAttributeMapper attrs =
          ConfiguredAttributeMapper.of(rule, configConditions.asProviders(), configuration);
      if (!attrs.has("target_compatible_with", BuildType.LABEL_LIST)) {
        sink.acceptIncompatibleTarget(Optional.empty());
        return runAfter;
      }

      // Resolves the constraint labels, checking for invalid configured attributes.
      List<Label> targetCompatibleWith;
      try {
        targetCompatibleWith = attrs.getAndValidate("target_compatible_with", BuildType.LABEL_LIST);
      } catch (ValidationException e) {
        sink.acceptValidationException(e);
        return runAfter;
      }
      for (Label label : targetCompatibleWith) {
        tasks.lookUp(
            ConfiguredTargetKey.builder()
                .setLabel(label)
                .setConfiguration(configuration)
                .build()
                .toKey(),
            this);
      }
      return this::processResult;
    }

    @Override
    public void accept(SkyValue value) {
      var configuredTarget = ((ConfiguredTargetValue) value).getConfiguredTarget();
      @Nullable ConstraintValueInfo info = PlatformProviderUtils.constraintValue(configuredTarget);
      if (info == null || platformInfo.constraints().hasConstraintValue(info)) {
        return;
      }
      invalidConstraintValuesBuilder.add(info);
    }

    private StateMachine processResult(Tasks tasks, ExtendedEventHandler listener) {
      var invalidConstraintValues = invalidConstraintValuesBuilder.build();
      if (!invalidConstraintValues.isEmpty()) {
        sink.acceptIncompatibleTarget(
            Optional.of(
                createIncompatibleRuleConfiguredTarget(
                    configuredTargetKey,
                    targetAndConfiguration.getConfiguration(),
                    configConditions,
                    IncompatiblePlatformProvider.incompatibleDueToConstraints(
                        platformInfo.label(), invalidConstraintValues),
                    targetAndConfiguration.getTarget().getAssociatedRule().getRuleClass(),
                    transitiveState)));
        return runAfter;
      }
      sink.acceptIncompatibleTarget(Optional.empty());
      return runAfter;
    }
  }

  /**
   * Creates an incompatible target if it is "indirectly incompatible".
   *
   * <p>In other words, this function checks if a target is incompatible because of one of its
   * dependencies. If a dependency is incompatible, then this target is also incompatible.
   *
   * <p>This function returns an {@code Optional} of a {@link RuleConfiguredTargetValue}. This
   * provides two states of return values:
   *
   * <ul>
   *   <li>{@code Optional.empty()}: The target is not indirectly incompatible. Analysis can
   *       continue.
   *   <li>{@code !Optional.empty()}: The target is indirectly incompatible. Analysis should not
   *       continue.
   * </ul>
   */
  public static Optional<RuleConfiguredTargetValue> createIndirectlyIncompatibleTarget(
      TargetAndConfiguration targetAndConfiguration,
      ConfiguredTargetKey configuredTargetKey,
      OrderedSetMultimap<DependencyKind, ConfiguredTargetAndData> depValueMap,
      ConfigConditions configConditions,
      @Nullable PlatformInfo platformInfo,
      TransitiveDependencyState transitiveState) {
    Target target = targetAndConfiguration.getTarget();
    Rule rule = target.getAssociatedRule();

    if (rule == null || rule.getRuleClass().equals("toolchain")) {
      return Optional.empty();
    }

    // Find all the incompatible dependencies.
    ImmutableList<ConfiguredTarget> incompatibleDeps =
        depValueMap.values().stream()
            .map(ConfiguredTargetAndData::getConfiguredTarget)
            .filter(
                dep -> RuleContextConstraintSemantics.checkForIncompatibility(dep).isIncompatible())
            .collect(toImmutableList());
    if (incompatibleDeps.isEmpty()) {
      return Optional.empty();
    }

    BuildConfigurationValue configuration = targetAndConfiguration.getConfiguration();
    Label platformLabel = platformInfo != null ? platformInfo.label() : null;
    return Optional.of(
        createIncompatibleRuleConfiguredTarget(
            configuredTargetKey,
            configuration,
            configConditions,
            IncompatiblePlatformProvider.incompatibleDueToTargets(platformLabel, incompatibleDeps),
            rule.getRuleClass(),
            transitiveState));
  }

  /** Thrown if this target is platform-incompatible with the current build. */
  public static class IncompatibleTargetException extends Exception {
    private final RuleConfiguredTargetValue target;

    public IncompatibleTargetException(RuleConfiguredTargetValue target) {
      this.target = target;
    }

    public RuleConfiguredTargetValue target() {
      return target;
    }
  }

  /** Creates an incompatible target. */
  private static RuleConfiguredTargetValue createIncompatibleRuleConfiguredTarget(
      ConfiguredTargetKey configuredTargetKey,
      BuildConfigurationValue configuration,
      ConfigConditions configConditions,
      IncompatiblePlatformProvider incompatiblePlatformProvider,
      String ruleClassString,
      TransitiveDependencyState transitiveState) {
    // Create dummy instances of the necessary data for a configured target. None of this data will
    // actually be used because actions associated with incompatible targets must not be evaluated.
    TransitiveInfoProviderMapBuilder providerBuilder =
        new TransitiveInfoProviderMapBuilder()
            .put(incompatiblePlatformProvider)
            .add(RunfilesProvider.simple(Runfiles.EMPTY))
            .add(FileProvider.EMPTY)
            .add(FilesToRunProvider.EMPTY)
            .add(
                new SupportedEnvironments(
                    EnvironmentCollection.EMPTY, EnvironmentCollection.EMPTY, ImmutableMap.of()));
    if (configuration.hasFragment(TestConfiguration.class)) {
      // Create a dummy TestProvider instance so that other parts of the code base stay happy. Even
      // though this test will never execute, some code still expects the provider.
      TestProvider.TestParams testParams = TestActionBuilder.createEmptyTestParams();
      providerBuilder.put(TestProvider.class, new TestProvider(testParams));
    }

    RuleConfiguredTarget configuredTarget =
        new RuleConfiguredTarget(
            configuredTargetKey,
            convertVisibility(),
            providerBuilder.build(),
            configConditions.asProviders(),
            ruleClassString);
    return new RuleConfiguredTargetValue(configuredTarget, transitiveState.transitivePackages());
  }

  /**
   * Generates visibility for an incompatible target.
   *
   * <p>The intent is for this function is to match ConfiguredTargetFactory.convertVisibility().
   * Since visibility is currently validated after incompatibility is evaluated, however, it doesn't
   * matter what visibility we set here. To keep it simple, we pretend that all incompatible targets
   * are public.
   *
   * <p>TODO(#16044): Set up properly validated visibility here.
   */
  private static NestedSet<PackageGroupContents> convertVisibility() {
    return NestedSetBuilder.create(
        Order.STABLE_ORDER,
        PackageGroupContents.create(ImmutableList.of(PackageSpecification.everything())));
  }
}
