// Copyright 2014 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.skyframe;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.devtools.build.lib.unsafe.UnsafeProvider.getFieldOffset;
import static com.google.devtools.build.lib.util.HashCodes.hashObjects;

import com.google.common.base.MoreObjects;
import com.google.devtools.build.lib.actions.ActionLookupKey;
import com.google.devtools.build.lib.analysis.config.BuildConfigurationValue;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.query2.common.CqueryNode;
import com.google.devtools.build.lib.skyframe.config.BuildConfigurationKey;
import com.google.devtools.build.lib.skyframe.serialization.AsyncDeserializationContext;
import com.google.devtools.build.lib.skyframe.serialization.DeferredObjectCodec;
import com.google.devtools.build.lib.skyframe.serialization.SerializationContext;
import com.google.devtools.build.lib.skyframe.serialization.SerializationException;
import com.google.devtools.build.skyframe.SkyFunctionName;
import com.google.devtools.build.skyframe.SkyKey;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import com.google.errorprone.annotations.Keep;
import com.google.protobuf.CodedInputStream;
import com.google.protobuf.CodedOutputStream;
import java.io.IOException;
import java.util.Objects;
import javax.annotation.Nullable;

/**
 * In simple form, a ({@link Label}, {@link BuildConfigurationValue}) pair used to trigger immediate
 * dependency resolution and the rule analysis.
 *
 * <p>In practice, a ({@link Label} and post-transition {@link BuildConfigurationKey}) pair plus a
 * possible execution platform override {@link Label} with special constraints described as follows.
 *
 * <p>A build should not request keys with equal ({@link Label}, {@link BuildConfigurationValue})
 * pairs but different execution platform override {@link Label} if the invoked rule will register
 * actions. (This is potentially OK if all outputs of all registered actions incorporate the
 * execution platform in their name unless the build also requests keys without an override that
 * happen to resolve to the same execution platform.) In practice, this issue has not been seen in
 * any 'real' builds; however, pathologically failure could lead to multiple (potentially different)
 * ConfiguredTarget that have the same ({@link Label}, {@link BuildConfigurationValue}) pair.
 *
 * <p>Note that this key may be used to look up the generating action of an artifact.
 *
 * <p>TODO(blaze-configurability-team): Consider just using BuildOptions over a
 * BuildConfigurationKey.
 */
public class ConfiguredTargetKey implements ActionLookupKey {
  /**
   * Cache so that the number of ConfiguredTargetKey instances is {@code O(configured targets)} and
   * not {@code O(edges between configured targets)}.
   */
  private static final SkyKey.SkyKeyInterner<ConfiguredTargetKey> interner = SkyKey.newInterner();

  private final Label label;
  @Nullable private final BuildConfigurationKey configurationKey;
  private final int hashCode;

  private ConfiguredTargetKey(
      Label label, @Nullable BuildConfigurationKey configurationKey, int hashCode) {
    this.label = label;
    this.configurationKey = configurationKey;
    this.hashCode = hashCode;
  }

  @Override
  public final SkyFunctionName functionName() {
    return SkyFunctions.CONFIGURED_TARGET;
  }

  @Override
  public SkyKeyInterner<?> getSkyKeyInterner() {
    return interner;
  }

  @Override
  public Label getLabel() {
    return label;
  }

  @Nullable
  @Override
  public final BuildConfigurationKey getConfigurationKey() {
    return configurationKey;
  }

  @Nullable
  public Label getExecutionPlatformLabel() {
    return null;
  }

  /**
   * True if the target's rule transition should be applied.
   *
   * <p>True by default but set false when a non-idempotent rule transition is detected. It prevents
   * over-application of such transitions.
   */
  public boolean shouldApplyRuleTransition() {
    return true;
  }

  public final String prettyPrint() {
    if (getLabel() == null) {
      return "null";
    }
    return String.format("%s (%s)", getLabel(), formatConfigurationKey(configurationKey));
  }

  @Override
  public final int hashCode() {
    return hashCode;
  }

  @Override
  public final boolean equals(Object obj) {
    if (this == obj) {
      return true;
    }
    if (!(obj instanceof ConfiguredTargetKey)) {
      return false;
    }
    ConfiguredTargetKey other = (ConfiguredTargetKey) obj;
    return hashCode == other.hashCode
        && getLabel().equals(other.getLabel())
        && Objects.equals(configurationKey, other.configurationKey)
        && Objects.equals(getExecutionPlatformLabel(), other.getExecutionPlatformLabel())
        && shouldApplyRuleTransition() == other.shouldApplyRuleTransition();
  }

  @Override
  public final String toString() {
    // TODO(b/162809183): consider reverting to less verbose toString when bug is resolved.
    MoreObjects.ToStringHelper helper =
        MoreObjects.toStringHelper(this).add("label", getLabel()).add("config", configurationKey);
    if (getExecutionPlatformLabel() != null) {
      helper.add("executionPlatformLabel", getExecutionPlatformLabel());
    }
    return helper.toString();
  }

  /**
   * Key indicating that no rule transition should be applied to the configuration.
   *
   * <p>NOTE: although it's true that no rule transition is applied when there is a null
   * configuration, this key type is used to handle a special edge case described below. It should
   * only be used with a non-null configuration.
   *
   * <p>When a non-noop rule transition occurs, it creates a new <i>delegation</i> {@link
   * ConfiguredTargetKey} with the resulting configuration. This is so if different starting
   * configurations result in the same configuration after transition, they converge on the same
   * key-value entry in Skyframe.
   *
   * <p>This can be problematic when transitions are not idempotent because evaluation of the
   * <i>delegate</i> repeats the transition, resulting in a another <i>delegate</i>. In cases of
   * non-convergent transitions, this may lead to infinite expansion.
   *
   * <p>To ensure that transitions are effectively only applied once, prior to delegation, the
   * {@link ConfiguredTargetFunction} applies the transition a second time to check it for
   * idempotency. It sets {@link ConfiguredTargetKey#shouldApplyRuleTransition} false when it is not
   * idempotent.
   */
  private static final class ConfiguredTargetKeyWithFinalConfiguration extends ConfiguredTargetKey {
    // This is implemented using subtypes instead of adding a boolean field to `ConfiguredTargetKey`
    // to reduce memory cost.

    private ConfiguredTargetKeyWithFinalConfiguration(
        Label label, BuildConfigurationKey configurationKey, int hashCode) {
      super(label, checkNotNull(configurationKey), hashCode);
    }

    @Override
    public boolean shouldApplyRuleTransition() {
      return false;
    }
  }

  private static class ToolchainDependencyConfiguredTargetKey extends ConfiguredTargetKey {
    private final Label executionPlatformLabel;

    private ToolchainDependencyConfiguredTargetKey(
        Label label,
        @Nullable BuildConfigurationKey configurationKey,
        int hashCode,
        Label executionPlatformLabel) {
      super(label, configurationKey, hashCode);
      this.executionPlatformLabel = checkNotNull(executionPlatformLabel);
    }

    @Override
    public Label getExecutionPlatformLabel() {
      return executionPlatformLabel;
    }
  }

  private static final class ToolchainDependencyConfiguredTargetKeyWithFinalConfiguration
      extends ToolchainDependencyConfiguredTargetKey {
    private ToolchainDependencyConfiguredTargetKeyWithFinalConfiguration(
        Label label,
        BuildConfigurationKey configurationKey,
        int hashCode,
        Label executionPlatformLabel) {
      super(label, checkNotNull(configurationKey), hashCode, executionPlatformLabel);
    }

    @Override
    public boolean shouldApplyRuleTransition() {
      return false;
    }
  }

  public Builder toBuilder() {
    return builder()
        .setConfigurationKey(configurationKey)
        .setLabel(getLabel())
        .setExecutionPlatformLabel(getExecutionPlatformLabel())
        .setShouldApplyRuleTransition(shouldApplyRuleTransition());
  }

  /** Returns a new {@link Builder} to create instances of {@link ConfiguredTargetKey}. */
  public static Builder builder() {
    return new Builder();
  }

  /** Returns the {@link ConfiguredTargetKey} that owns {@code configuredTarget}. */
  public static ConfiguredTargetKey fromConfiguredTarget(CqueryNode configuredTarget) {
    // If configuredTarget is a MergedConfiguredTarget unwraps it first. MergedConfiguredTarget is
    // ephemeral and does not have a directly corresponding entry in Skyframe.
    //
    // The cast exists because the key passes through parts of analysis that work on both aspects
    // and configured targets. This process discards the key's specific type information.
    return (ConfiguredTargetKey) configuredTarget.unwrapIfMerged().getLookupKey();
  }

  /** A helper class to create instances of {@link ConfiguredTargetKey}. */
  public static final class Builder
      implements DeferredObjectCodec.DeferredValue<ConfiguredTargetKey> {
    private Label label = null;
    private BuildConfigurationKey configurationKey = null;
    private Label executionPlatformLabel = null;
    private boolean shouldApplyRuleTransition = true;

    private Builder() {}

    /** Sets the label for the target. */
    @CanIgnoreReturnValue
    public Builder setLabel(Label label) {
      this.label = label;
      return this;
    }

    /** Sets the {@link BuildConfigurationValue} for the configured target. */
    @CanIgnoreReturnValue
    public Builder setConfiguration(@Nullable BuildConfigurationValue buildConfiguration) {
      return setConfigurationKey(buildConfiguration == null ? null : buildConfiguration.getKey());
    }

    /** Sets the configuration key for the configured target. */
    @CanIgnoreReturnValue
    public Builder setConfigurationKey(@Nullable BuildConfigurationKey configurationKey) {
      this.configurationKey = configurationKey;
      return this;
    }

    /**
     * Sets the execution platform {@link Label} this configured target should use for toolchain
     * resolution. When present, this overrides the normally determined execution platform.
     */
    @CanIgnoreReturnValue
    public Builder setExecutionPlatformLabel(@Nullable Label executionPlatformLabel) {
      this.executionPlatformLabel = executionPlatformLabel;
      return this;
    }

    @CanIgnoreReturnValue
    public Builder setShouldApplyRuleTransition(boolean shouldApplyRuleTransition) {
      this.shouldApplyRuleTransition = shouldApplyRuleTransition;
      return this;
    }

    /** Builds a new {@link ConfiguredTargetKey} based on the supplied data. */
    public ConfiguredTargetKey build() {
      int hashCode =
          computeHashCode(
              label, configurationKey, executionPlatformLabel, shouldApplyRuleTransition);
      ConfiguredTargetKey newKey;
      if (executionPlatformLabel == null) {
        newKey =
            shouldApplyRuleTransition
                ? new ConfiguredTargetKey(label, configurationKey, hashCode)
                : new ConfiguredTargetKeyWithFinalConfiguration(label, configurationKey, hashCode);
      } else {
        newKey =
            shouldApplyRuleTransition
                ? new ToolchainDependencyConfiguredTargetKey(
                    label, configurationKey, hashCode, executionPlatformLabel)
                : new ToolchainDependencyConfiguredTargetKeyWithFinalConfiguration(
                    label, configurationKey, hashCode, executionPlatformLabel);
      }
      return interner.intern(newKey);
    }

    /** Implements the {@link DeferredObjectCodec.DeferredValue} used for deserialization. */
    @Override
    public ConfiguredTargetKey call() {
      return build();
    }
  }

  private static int computeHashCode(
      Label label,
      @Nullable BuildConfigurationKey configurationKey,
      @Nullable Label executionPlatformLabel,
      boolean shouldApplyRuleTransition) {
    int hashCode = hashObjects(label, configurationKey, executionPlatformLabel);
    if (!shouldApplyRuleTransition) {
      hashCode = ~hashCode;
    }
    return hashCode;
  }

  private static String formatConfigurationKey(@Nullable BuildConfigurationKey key) {
    if (key == null) {
      return "null";
    }
    return key.getOptions().checksum();
  }

  /** Codec for all {@link ConfiguredTargetKey} subtypes. */
  @Keep
  private static class ConfiguredTargetKeyCodec extends DeferredObjectCodec<ConfiguredTargetKey> {
    @Override
    public Class<ConfiguredTargetKey> getEncodedClass() {
      return ConfiguredTargetKey.class;
    }

    @Override
    public void serialize(
        SerializationContext context, ConfiguredTargetKey key, CodedOutputStream codedOut)
        throws SerializationException, IOException {
      context.serialize(key.getLabel(), codedOut);
      context.serialize(key.getConfigurationKey(), codedOut);
      context.serialize(key.getExecutionPlatformLabel(), codedOut);
      codedOut.writeBoolNoTag(key.shouldApplyRuleTransition());
    }

    @Override
    public DeferredValue<ConfiguredTargetKey> deserializeDeferred(
        AsyncDeserializationContext context, CodedInputStream codedIn)
        throws SerializationException, IOException {
      Builder builder = builder();
      context.deserialize(codedIn, builder, LABEL_OFFSET);
      context.deserialize(codedIn, builder, CONFIGURATION_KEY_OFFSET);
      context.deserialize(codedIn, builder, EXECUTION_PLATFORM_LABEL_OFFSET);
      return builder.setShouldApplyRuleTransition(codedIn.readBool());
    }
  }

  // Below are Builder offsets, used for deserialization.

  private static final long LABEL_OFFSET;
  private static final long CONFIGURATION_KEY_OFFSET;
  private static final long EXECUTION_PLATFORM_LABEL_OFFSET;

  static {
    try {
      LABEL_OFFSET = getFieldOffset(Builder.class, "label");
      CONFIGURATION_KEY_OFFSET = getFieldOffset(Builder.class, "configurationKey");
      EXECUTION_PLATFORM_LABEL_OFFSET = getFieldOffset(Builder.class, "executionPlatformLabel");
    } catch (NoSuchFieldException e) {
      throw new ExceptionInInitializerError(e);
    }
  }
}
