// 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.actions.Artifact;
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.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.Package;
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;
    @Nullable private final NestedSetBuilder<Package> transitivePackages;

    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,
        @Nullable NestedSetBuilder<Package> transitivePackages,
        ResultSink sink,
        StateMachine runAfter) {
      this.targetAndConfiguration = targetAndConfiguration;
      this.configuredTargetKey = configuredTargetKey;
      this.configConditions = configConditions;
      this.platformInfo = platformInfo;
      this.transitivePackages = transitivePackages;
      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(),
                    transitivePackages)));
        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,
      @Nullable NestedSetBuilder<Package> transitivePackages) {
    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(),
            transitivePackages));
  }

  /** 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,
      @Nullable NestedSetBuilder<Package> transitivePackages) {
    // 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.
    NestedSet<Artifact> filesToBuild = NestedSetBuilder.emptySet(Order.STABLE_ORDER);
    FileProvider fileProvider = new FileProvider(filesToBuild);
    FilesToRunProvider filesToRunProvider = new FilesToRunProvider(filesToBuild, null, null);

    TransitiveInfoProviderMapBuilder providerBuilder =
        new TransitiveInfoProviderMapBuilder()
            .put(incompatiblePlatformProvider)
            .add(RunfilesProvider.simple(Runfiles.EMPTY))
            .add(fileProvider)
            .add(filesToRunProvider)
            .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, transitivePackages == null ? null : transitivePackages.build());
  }

  /**
   * 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())));
  }
}
