// 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 com.google.auto.value.AutoOneOf;
import com.google.devtools.build.lib.actions.ActionLookupKey;
import com.google.devtools.build.lib.analysis.ConfiguredTargetValue;
import com.google.devtools.build.lib.analysis.InconsistentNullConfigException;
import com.google.devtools.build.lib.analysis.InvalidVisibilityDependencyException;
import com.google.devtools.build.lib.analysis.TargetAndConfiguration;
import com.google.devtools.build.lib.analysis.config.BuildConfigurationValue;
import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException;
import com.google.devtools.build.lib.analysis.config.StarlarkTransitionCache;
import com.google.devtools.build.lib.analysis.config.transitions.TransitionFactory;
import com.google.devtools.build.lib.analysis.starlark.StarlarkTransition.TransitionException;
import com.google.devtools.build.lib.buildeventstream.BuildEventIdUtil;
import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos.BuildEventId;
import com.google.devtools.build.lib.events.ExtendedEventHandler;
import com.google.devtools.build.lib.packages.NoSuchPackageException;
import com.google.devtools.build.lib.packages.NoSuchTargetException;
import com.google.devtools.build.lib.packages.PackageGroup;
import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.packages.RuleTransitionData;
import com.google.devtools.build.lib.packages.Target;
import com.google.devtools.build.lib.skyframe.BuildConfigurationKey;
import com.google.devtools.build.lib.skyframe.ConfiguredTargetKey;
import com.google.devtools.build.lib.skyframe.ConfiguredValueCreationException;
import com.google.devtools.build.lib.util.DetailedExitCode;
import com.google.devtools.build.skyframe.SkyValue;
import com.google.devtools.build.skyframe.state.StateMachine;
import com.google.devtools.common.options.OptionsParsingException;
import java.util.function.Consumer;
import javax.annotation.Nullable;
import net.starlark.java.syntax.Location;

/**
 * Computes the target and configuration for a configured target key.
 *
 * <p>If the key has a configuration and the target is configurable, attempts to apply a rule side
 * transition. If the target is not configurable, directly transitions to the null configuration. If
 * the resulting configuration already has an owner, delegates to the owner instead of recomputing
 * the configured target.
 *
 * <p>If the key does not have a configuration, it was requested as a visibility dependency.
 * Verifies that the {@link Target} is a {@link PackageGroup}, throwing {@link
 * InvalidVisibilityDependencyException} if that's not the case.
 */
public final class TargetAndConfigurationProducer
    implements StateMachine, Consumer<SkyValue>, TargetProducer.ResultSink {
  /** Accepts results of this producer. */
  public interface ResultSink {
    void acceptTargetAndConfiguration(TargetAndConfiguration value, ConfiguredTargetKey fullKey);

    void acceptTargetAndConfigurationDelegatedValue(ConfiguredTargetValue value);

    void acceptTargetAndConfigurationError(TargetAndConfigurationError error);
  }

  /** Tagged union of possible errors. */
  @AutoOneOf(TargetAndConfigurationError.Kind.class)
  public abstract static class TargetAndConfigurationError {
    /** Tags the error type. */
    public enum Kind {
      CONFIGURED_VALUE_CREATION,
      INVALID_VISIBILITY_DEPENDENCY,
      INCONSISTENT_NULL_CONFIG
    }

    public abstract Kind kind();

    public abstract ConfiguredValueCreationException configuredValueCreation();

    public abstract InvalidVisibilityDependencyException invalidVisibilityDependency();

    public abstract InconsistentNullConfigException inconsistentNullConfig();

    private static TargetAndConfigurationError of(ConfiguredValueCreationException e) {
      return AutoOneOf_TargetAndConfigurationProducer_TargetAndConfigurationError
          .configuredValueCreation(e);
    }

    // TODO(b/261521010): enable this error once Rule transitions are removed from dependency
    // resolution.
    // private static TargetAndConfigurationError of(InvalidVisibilityDependencyException e) {
    // return AutoOneOf_TargetAndConfigurationProducer_TargetAndConfigurationError
    // .invalidVisibilityDependency(e);
    // }

    // TODO(b/261521010): delete this error once Rule transitions are removed from dependency
    // resolution.
    private static TargetAndConfigurationError of(InconsistentNullConfigException e) {
      return AutoOneOf_TargetAndConfigurationProducer_TargetAndConfigurationError
          .inconsistentNullConfig(e);
    }
  }

  // -------------------- Input --------------------
  private final ConfiguredTargetKey preRuleTransitionKey;
  @Nullable private final TransitionFactory<RuleTransitionData> trimmingTransitionFactory;
  private final StarlarkTransitionCache transitionCache;

  private final TransitiveDependencyState transitiveState;

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

  // -------------------- Internal State --------------------
  private Target target;

  public TargetAndConfigurationProducer(
      ConfiguredTargetKey preRuleTransitionKey,
      @Nullable TransitionFactory<RuleTransitionData> trimmingTransitionFactory,
      StarlarkTransitionCache transitionCache,
      TransitiveDependencyState transitiveState,
      ResultSink sink) {
    this.preRuleTransitionKey = preRuleTransitionKey;
    this.trimmingTransitionFactory = trimmingTransitionFactory;
    this.transitionCache = transitionCache;
    this.transitiveState = transitiveState;
    this.sink = sink;
  }

  @Override
  public StateMachine step(Tasks tasks, ExtendedEventHandler listener) {
    return new TargetProducer(
        preRuleTransitionKey.getLabel(),
        transitiveState,
        (TargetProducer.ResultSink) this,
        /* runAfter= */ this::determineConfiguration);
  }

  @Override
  public void acceptTarget(Target target) {
    this.target = target;
  }

  @Override
  public void acceptTargetError(NoSuchPackageException e) {
    emitError(e.getMessage(), /* location= */ null, e.getDetailedExitCode());
  }

  @Override
  public void acceptTargetError(NoSuchTargetException e, Location location) {
    emitError(e.getMessage(), location, e.getDetailedExitCode());
  }

  private StateMachine determineConfiguration(Tasks tasks, ExtendedEventHandler listener) {
    if (target == null) {
      return DONE; // There was an error.
    }

    // TODO(b/261521010): after removing the rule transition from dependency resolution, remove
    // this. It won't be possible afterwards because null configuration keys will only be used for
    // visibility dependencies.
    BuildConfigurationKey configurationKey = preRuleTransitionKey.getConfigurationKey();
    if ((configurationKey != null) != target.isConfigurable()) {
      // We somehow ended up in a target that requires a non-null configuration as a dependency of
      // one that requires a null configuration or the other way round. This is always an error, but
      // we need to analyze the dependencies of the latter target to realize that. Short-circuit the
      // evaluation to avoid doing useless work and running code with a null configuration that's
      // not prepared for it.
      sink.acceptTargetAndConfigurationError(
          TargetAndConfigurationError.of(new InconsistentNullConfigException()));
      return DONE;
    }

    // TODO(b/261521010): after removing the rule transition from dependency resolution, the logic
    // here changes.
    //
    // A null configuration key will only be used for visibility dependencies so when that's true, a
    // check that the target is a PackageGroup will be performed, throwing
    // InvalidVisibilityDependencyException on failure.
    if (configurationKey == null) {
      // The ConfiguredTargetKey cannot fan-in in this case.
      sink.acceptTargetAndConfiguration(
          new TargetAndConfiguration(target, /* configuration= */ null), preRuleTransitionKey);
      return DONE;
    }

    return new RuleTransitionConfigurationProducer();
  }

  /** Applies any requested rule transition before producing the final configuration. */
  private class RuleTransitionConfigurationProducer
      implements StateMachine,
          RuleTransitionApplier.ResultSink,
          ValueOrExceptionSink<InvalidConfigurationException> {
    // -------------------- Internal State --------------------
    private BuildConfigurationKey configurationKey;
    private ConfiguredTargetKey fullKey;

    @Override
    public StateMachine step(Tasks tasks, ExtendedEventHandler listener) {
      return new RuleTransitionApplier(
          preRuleTransitionKey.getConfigurationKey(),
          target.getAssociatedRule(),
          trimmingTransitionFactory,
          transitionCache,
          (RuleTransitionApplier.ResultSink) this,
          /* runAfter= */ this::processTransitionedKey);
    }

    @Override
    public void acceptRuleTransitionResult(BuildConfigurationKey result) {
      this.configurationKey = result;
    }

    @Override
    public void acceptRuleTransitionError(TransitionException e) {
      emitTransitionErrorMessage(e.getMessage());
    }

    @Override
    public void acceptRuleTransitionError(OptionsParsingException e) {
      emitTransitionErrorMessage(e.getMessage());
    }

    private StateMachine processTransitionedKey(Tasks tasks, ExtendedEventHandler listener) {
      if (configurationKey == null) {
        return DONE; // There was an error.
      }

      if (!configurationKey.equals(preRuleTransitionKey.getConfigurationKey())) {
        fullKey =
            ConfiguredTargetKey.builder()
                .setDelegate(preRuleTransitionKey)
                .setConfigurationKey(configurationKey)
                .build();
        ActionLookupKey delegate = fullKey.toKey();
        if (!delegate.equals(preRuleTransitionKey)) {
          // Delegates to the key that already owns this configuration.
          delegateTo(tasks, delegate);
          return DONE;
        }
      } else {
        fullKey = preRuleTransitionKey;
      }

      // This key owns the configuration and the computation completes normally.
      tasks.lookUp(
          configurationKey,
          InvalidConfigurationException.class,
          (ValueOrExceptionSink<InvalidConfigurationException>) this);
      return DONE;
    }

    @Override
    public void acceptValueOrException(
        @Nullable SkyValue value, @Nullable InvalidConfigurationException error) {
      if (value != null) {
        sink.acceptTargetAndConfiguration(
            new TargetAndConfiguration(target, (BuildConfigurationValue) value), fullKey);
        return;
      }
      emitTransitionErrorMessage(error.getMessage());
    }

    private void emitTransitionErrorMessage(String message) {
      // The target must be a rule because these errors happen during the Rule transition.
      Rule rule = target.getAssociatedRule();
      emitError(message, rule.getLocation(), /* exitCode= */ null);
    }
  }

  private void delegateTo(Tasks tasks, ActionLookupKey delegate) {
    tasks.lookUp(delegate, (Consumer<SkyValue>) this);
  }

  @Override
  public void accept(SkyValue value) {
    sink.acceptTargetAndConfigurationDelegatedValue((ConfiguredTargetValue) value);
  }

  private void emitError(
      String message, @Nullable Location location, @Nullable DetailedExitCode exitCode) {
    sink.acceptTargetAndConfigurationError(
        TargetAndConfigurationError.of(
            new ConfiguredValueCreationException(
                location,
                message,
                preRuleTransitionKey.getLabel(),
                getConfigurationId(preRuleTransitionKey.getConfigurationKey()),
                /* rootCauses= */ null,
                exitCode)));
  }

  private static BuildEventId getConfigurationId(@Nullable BuildConfigurationKey configurationKey) {
    return configurationKey == null
        ? BuildEventIdUtil.nullConfigurationId()
        : BuildEventIdUtil.configurationId(configurationKey.getOptions().checksum());
  }
}
