// 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 com.google.common.base.Preconditions;
import com.google.common.collect.Interner;
import com.google.devtools.build.lib.actions.ActionLookupValue.ActionLookupKey;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.concurrent.BlazeInterners;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
import com.google.devtools.build.skyframe.SkyFunctionName;
import java.util.Objects;
import javax.annotation.Nullable;

/**
 * A (Label, Configuration key) pair. Note that this pair may be used to look up the generating
 * action of an artifact.
 */
@AutoCodec
public class ConfiguredTargetKey extends ActionLookupKey {
  private final Label label;
  @Nullable private final BuildConfigurationValue.Key configurationKey;

  private transient int hashCode;

  @AutoCodec.VisibleForSerialization
  ConfiguredTargetKey(Label label, @Nullable BuildConfigurationValue.Key configurationKey) {
    this.label = Preconditions.checkNotNull(label);
    this.configurationKey = configurationKey;
  }

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

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

  @Nullable
  final BuildConfigurationValue.Key getConfigurationKey() {
    return configurationKey;
  }

  @Nullable
  ToolchainContextKey getToolchainContextKey() {
    return null;
  }

  @Override
  public final int hashCode() {
    // We use the hash code caching strategy employed by java.lang.String. There are three subtle
    // things going on here:
    //
    // (1) We use a value of 0 to indicate that the hash code hasn't been computed and cached yet.
    // Yes, this means that if the hash code is really 0 then we will "recompute" it each time. But
    // this isn't a problem in practice since a hash code of 0 should be rare.
    //
    // (2) Since we have no synchronization, multiple threads can race here thinking there are the
    // first one to compute and cache the hash code.
    //
    // (3) Moreover, since 'hashCode' is non-volatile, the cached hash code value written from one
    // thread may not be visible by another.
    //
    // All three of these issues are benign from a correctness perspective; in the end we have no
    // overhead from synchronization, at the cost of potentially computing the hash code more than
    // once.
    int h = hashCode;
    if (h == 0) {
      h = computeHashCode();
      hashCode = h;
    }
    return h;
  }

  private final int computeHashCode() {
    int configVal = configurationKey == null ? 79 : configurationKey.hashCode();
    int toolchainContextVal =
        getToolchainContextKey() == null ? 47 : getToolchainContextKey().hashCode();
    return 31 * label.hashCode() + configVal + toolchainContextVal;
  }

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

  public final String prettyPrint() {
    if (label == null) {
      return "null";
    }
    return label.toString();
  }

  @Override
  public final String toString() {
    if (getToolchainContextKey() != null) {
      return String.format("%s %s %s", label, configurationKey, getToolchainContextKey());
    }
    return String.format("%s %s", label, configurationKey);
  }

  static class ConfiguredTargetKeyWithToolchainContext extends ConfiguredTargetKey {
    private final ToolchainContextKey toolchainContextKey;

    private ConfiguredTargetKeyWithToolchainContext(
        Label label,
        @Nullable BuildConfigurationValue.Key configurationKey,
        ToolchainContextKey toolchainContextKey) {
      super(label, configurationKey);
      this.toolchainContextKey = toolchainContextKey;
    }

    @Override
    @Nullable
    final ToolchainContextKey getToolchainContextKey() {
      return toolchainContextKey;
    }
  }

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

  /**
   * Caches so that the number of ConfiguredTargetKey instances is {@code O(configured targets)} and
   * not {@code O(edges between configured targets)}.
   */
  private static final Interner<ConfiguredTargetKey> interner = BlazeInterners.newWeakInterner();

  private static final Interner<ConfiguredTargetKeyWithToolchainContext>
      withToolchainContextInterner = BlazeInterners.newWeakInterner();

  /** A helper class to create instances of {@link ConfiguredTargetKey}. */
  public static class Builder {
    private Label label = null;
    private BuildConfigurationValue.Key configurationKey = null;
    private ToolchainContextKey toolchainContextKey = null;

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

    /**
     * Sets the {@link ConfiguredTarget} that we want a key for.
     *
     * <p>This sets both the label and configurationKey data.
     */
    public Builder setConfiguredTarget(ConfiguredTarget configuredTarget) {
      setLabel(configuredTarget.getOriginalLabel());
      if (this.configurationKey == null) {
        setConfigurationKey(configuredTarget.getConfigurationKey());
      }
      return this;
    }

    /** Sets the {@link BuildConfiguration} for the configured target. */
    public Builder setConfiguration(@Nullable BuildConfiguration buildConfiguration) {
      if (buildConfiguration == null) {
        return setConfigurationKey(null);
      } else {
        return setConfigurationKey(BuildConfigurationValue.key(buildConfiguration));
      }
    }

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

    /**
     * Sets the {@link ToolchainContextKey} this configured target should use for toolchain
     * resolution. When present, this overrides the normally determined toolchain context.
     */
    public Builder setToolchainContextKey(ToolchainContextKey toolchainContextKey) {
      this.toolchainContextKey = toolchainContextKey;
      return this;
    }

    /** Builds a new {@link ConfiguredTargetKey} based on the supplied data. */
    public ConfiguredTargetKey build() {
      if (this.toolchainContextKey != null) {
        return withToolchainContextInterner.intern(
            new ConfiguredTargetKeyWithToolchainContext(
                label, configurationKey, toolchainContextKey));
      }
      return interner.intern(new ConfiguredTargetKey(label, configurationKey));
    }
  }
}
