// Copyright 2023 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.producers;

import static com.google.common.base.Preconditions.checkState;
import static com.google.devtools.build.lib.analysis.AspectResolutionHelpers.computeAspectCollection;
import static com.google.devtools.build.lib.analysis.producers.AttributeConfiguration.Kind.VISIBILITY;
import static com.google.devtools.build.lib.skyframe.ConfiguredTargetAndData.SPLIT_DEP_ORDERING;
import static java.util.Arrays.copyOfRange;
import static java.util.Arrays.sort;

import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.analysis.AspectCollection;
import com.google.devtools.build.lib.analysis.DuplicateException;
import com.google.devtools.build.lib.analysis.InconsistentAspectOrderException;
import com.google.devtools.build.lib.analysis.InconsistentNullConfigException;
import com.google.devtools.build.lib.analysis.InvalidVisibilityDependencyException;
import com.google.devtools.build.lib.analysis.config.DependencyEvaluationException;
import com.google.devtools.build.lib.analysis.configuredtargets.PackageGroupConfiguredTarget;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.packages.Aspect;
import com.google.devtools.build.lib.packages.NoSuchThingException;
import com.google.devtools.build.lib.skyframe.AspectCreationException;
import com.google.devtools.build.lib.skyframe.BaseTargetPrerequisitesSupplier;
import com.google.devtools.build.lib.skyframe.ConfiguredTargetAndData;
import com.google.devtools.build.lib.skyframe.ConfiguredTargetKey;
import com.google.devtools.build.lib.skyframe.ConfiguredValueCreationException;
import com.google.devtools.build.lib.skyframe.config.BuildConfigurationKey;
import com.google.devtools.build.skyframe.state.StateMachine;
import java.util.HashSet;
import java.util.Map;
import javax.annotation.Nullable;

/**
 * Computes requested prerequisite(s), applying any requested aspects.
 *
 * <p>A dependency is specified by a {@link Label} and an execution platform {@link Label} if it is
 * a toolchain.
 *
 * <p>Its configuration is determined by an {@link AttributeConfiguration}, which may be split and
 * result in multiple outputs.
 *
 * <p>Computes any specified aspects, applying the appropriate filtering, and merges them into the
 * resulting values.
 */
final class PrerequisitesProducer
    implements StateMachine,
        ConfiguredTargetAndDataProducer.ResultSink,
        ConfiguredAspectProducer.ResultSink {
  interface ResultSink {
    void acceptPrerequisitesValue(ConfiguredTargetAndData[] prerequisites);

    void acceptPrerequisitesError(NoSuchThingException error);

    void acceptPrerequisitesError(InvalidVisibilityDependencyException error);

    void acceptPrerequisitesCreationError(ConfiguredValueCreationException error);

    void acceptPrerequisitesAspectError(DependencyEvaluationException error);

    void acceptPrerequisitesAspectError(AspectCreationException error);
  }

  // -------------------- Input --------------------
  private final PrerequisiteParameters parameters;
  private final Label label;
  @Nullable // Non-null for toolchain prerequisites.
  private final Label executionPlatformLabel;
  private final AttributeConfiguration configuration;
  private final ImmutableList<Aspect> propagatingAspects;
  private final boolean useBaseTargetPrerequisitesSupplier;

  // -------------------- Output --------------------
  private final ResultSink sink;

  // -------------------- Internal State --------------------
  private ConfiguredTargetAndData[] configuredTargets;
  private boolean hasError;

  PrerequisitesProducer(
      PrerequisiteParameters parameters,
      Label label,
      @Nullable Label executionPlatformLabel,
      AttributeConfiguration configuration,
      ImmutableList<Aspect> propagatingAspects,
      ResultSink sink,
      boolean useBaseTargetPrerequisitesSupplier) {
    this.parameters = parameters;
    this.label = label;
    this.executionPlatformLabel = executionPlatformLabel;
    this.configuration = configuration;
    this.propagatingAspects = propagatingAspects;
    this.sink = sink;
    this.useBaseTargetPrerequisitesSupplier = useBaseTargetPrerequisitesSupplier;

    // size > 0 guaranteed by contract of SplitTransition.
    int size = configuration.count();
    this.configuredTargets = new ConfiguredTargetAndData[size];
  }

  @Override
  public StateMachine step(Tasks tasks) {
    BaseTargetPrerequisitesSupplier baseTargetPrerequisitesSupplier =
        useBaseTargetPrerequisitesSupplier ? parameters.baseTargetPrerequisitesSupplier() : null;
    switch (configuration.kind()) {
      case VISIBILITY:
        tasks.enqueue(
            new ConfiguredTargetAndDataProducer(
                getPrerequisiteKey(/* configurationKey= */ null),
                /* transitionKeys= */ ImmutableList.of(),
                parameters.transitiveState(),
                (ConfiguredTargetAndDataProducer.ResultSink) this,
                /* outputIndex= */ 0,
                baseTargetPrerequisitesSupplier));
        break;
      case NULL_TRANSITION_KEYS:
        tasks.enqueue(
            new ConfiguredTargetAndDataProducer(
                getPrerequisiteKey(/* configurationKey= */ null),
                configuration.nullTransitionKeys(),
                parameters.transitiveState(),
                (ConfiguredTargetAndDataProducer.ResultSink) this,
                /* outputIndex= */ 0,
                baseTargetPrerequisitesSupplier));
        break;
      case UNARY:
        tasks.enqueue(
            new ConfiguredTargetAndDataProducer(
                getPrerequisiteKey(configuration.unary()),
                /* transitionKeys= */ ImmutableList.of(),
                parameters.transitiveState(),
                (ConfiguredTargetAndDataProducer.ResultSink) this,
                /* outputIndex= */ 0,
                baseTargetPrerequisitesSupplier));
        break;
      case SPLIT:
        int index = 0;
        for (Map.Entry<String, BuildConfigurationKey> entry : configuration.split().entrySet()) {
          tasks.enqueue(
              new ConfiguredTargetAndDataProducer(
                  getPrerequisiteKey(entry.getValue()),
                  ImmutableList.of(entry.getKey()),
                  parameters.transitiveState(),
                  (ConfiguredTargetAndDataProducer.ResultSink) this,
                  index,
                  baseTargetPrerequisitesSupplier));
          ++index;
        }
        break;
    }
    return this::computeConfiguredAspects;
  }

  @Override
  public void acceptConfiguredTargetAndData(ConfiguredTargetAndData value, int index) {
    configuredTargets[index] = value;
  }

  @Override
  public void acceptConfiguredTargetAndDataError(NoSuchThingException error) {
    hasError = true;
    sink.acceptPrerequisitesError(error);
  }

  @Override
  public void acceptConfiguredTargetAndDataError(InconsistentNullConfigException error) {
    hasError = true;
    if (configuration.kind() == VISIBILITY) {
      // The target was configurable, but used as a visibility dependency. This is invalid because
      // only `PackageGroup`s are accepted as visibility dependencies and those are not
      // configurable. Propagates the exception with more precise information.
      sink.acceptPrerequisitesError(new InvalidVisibilityDependencyException(label));
      return;
    }
    // `configuration.kind()` was `NULL_TRANSITION_KEYS`. This is only used when the target is in
    // the same package as the parent and not configurable so this should never happen.
    throw new IllegalStateException(error);
  }

  @Override
  public void acceptConfiguredTargetAndDataError(ConfiguredValueCreationException error) {
    hasError = true;
    sink.acceptPrerequisitesCreationError(error);
  }

  private StateMachine computeConfiguredAspects(Tasks tasks) {
    if (hasError) {
      return DONE;
    }

    if (configuration.kind() == VISIBILITY) {
      // Verifies that the dependency is a `package_group`. The value is always at index 0 because
      // the `VISIBILITY` configuration is always unary.
      if (!(configuredTargets[0].getConfiguredTarget() instanceof PackageGroupConfiguredTarget)) {
        sink.acceptPrerequisitesError(new InvalidVisibilityDependencyException(label));
        return DONE;
      }
    }

    cleanupValues();

    AspectCollection aspects;
    try {
      // All configured targets in the set have the same underlying target so using an arbitrary one
      // for aspect filtering is safe.
      aspects = computeAspectCollection(configuredTargets[0], propagatingAspects);
    } catch (InconsistentAspectOrderException e) {
      sink.acceptPrerequisitesAspectError(new DependencyEvaluationException(e));
      return DONE;
    }

    if (aspects.isEmpty()) { // Short circuits if there are no aspects.
      sink.acceptPrerequisitesValue(configuredTargets);
      return DONE;
    }

    for (int i = 0; i < configuredTargets.length; ++i) {
      ConfiguredTargetAndData target = configuredTargets[i];
      configuredTargets[i] = null;
      tasks.enqueue(
          new ConfiguredAspectProducer(
              aspects,
              target,
              (ConfiguredAspectProducer.ResultSink) this,
              i,
              parameters.transitiveState()));
    }
    return this::emitMergedTargets;
  }

  @Override
  public void acceptConfiguredAspectMergedTarget(
      int outputIndex, ConfiguredTargetAndData mergedTarget) {
    configuredTargets[outputIndex] = mergedTarget;
  }

  @Override
  public void acceptConfiguredAspectError(DuplicateException error) {
    hasError = true;
    sink.acceptPrerequisitesAspectError(
        new DependencyEvaluationException(
            new ConfiguredValueCreationException(
                parameters.location(),
                error.getMessage(),
                parameters.label(),
                parameters.eventId(),
                /* rootCauses= */ null,
                /* detailedExitCode= */ null),
            /* depReportedOwnError= */ false));
  }

  @Override
  public void acceptConfiguredAspectError(AspectCreationException error) {
    hasError = true;
    sink.acceptPrerequisitesAspectError(error);
  }

  private StateMachine emitMergedTargets(Tasks tasks) {
    if (!hasError) {
      sink.acceptPrerequisitesValue(configuredTargets);
    }
    return DONE;
  }

  private ConfiguredTargetKey getPrerequisiteKey(@Nullable BuildConfigurationKey configurationKey) {
    var key = ConfiguredTargetKey.builder().setLabel(label).setConfigurationKey(configurationKey);
    if (executionPlatformLabel != null) {
      key.setExecutionPlatformLabel(executionPlatformLabel);
    }
    return key.build();
  }

  private void cleanupValues() {
    if (configuredTargets.length == 1) {
      return;
    }
    // Otherwise, there was a split transition.

    if (configuredTargets[0].getConfiguration() == null) {
      // The resulting configurations are null. Aggregates the transition keys.
      var keys = new ImmutableList.Builder<String>();
      keys.addAll(configuredTargets[0].getTransitionKeys());
      for (int i = 1; i < configuredTargets.length; ++i) {
        checkState(
            configuredTargets[i].getConfiguration() == null,
            "inconsistent split transition result from %s to %s",
            parameters.label(),
            label);
        keys.addAll(configuredTargets[i].getTransitionKeys());
      }
      configuredTargets =
          new ConfiguredTargetAndData[] {configuredTargets[0].copyWithTransitionKeys(keys.build())};
      return;
    }

    // Deduplicates entries that have identical configurations and thus identical values, keeping
    // only the first entry with the configuration.
    var seenConfigurations = new HashSet<BuildConfigurationKey>();
    int firstIndex = 0;
    for (int i = 0; i < configuredTargets.length; ++i) {
      if (!seenConfigurations.add(configuredTargets[i].getConfigurationKey())) {
        // The target at `i` was a duplicate of a previous target. Deletes it by:
        // 1. overwriting it with the first target; and
        // 2. removing the slot previously associated with the first target.
        configuredTargets[i] = configuredTargets[firstIndex++];
      }
    }
    if (firstIndex > 0) {
      configuredTargets = copyOfRange(configuredTargets, firstIndex, configuredTargets.length);
    }
    sort(configuredTargets, SPLIT_DEP_ORDERING);
  }
}
