// 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.AliasProvider;
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;

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

  private static Label getLabel(ConfiguredTarget configuredTarget) {
    AliasProvider aliasProvider = configuredTarget.getProvider(AliasProvider.class);
    return aliasProvider != null
        ? aliasProvider.getAliasChain().get(0)
        : configuredTarget.getLabel();
  }

  public static ConfiguredTargetKey of(
      ConfiguredTarget configuredTarget, BuildConfiguration buildConfiguration) {
    return of(getLabel(configuredTarget), buildConfiguration);
  }

  public static ConfiguredTargetKey of(
      ConfiguredTarget configuredTarget,
      BuildConfigurationValue.Key configurationKey,
      boolean isHostConfiguration) {
    return of(getLabel(configuredTarget), configurationKey, isHostConfiguration);
  }

  /**
   * 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<HostConfiguredTargetKey> hostInterner =
      BlazeInterners.newWeakInterner();

  public static ConfiguredTargetKey of(Label label, @Nullable BuildConfiguration configuration) {
    KeyAndHost keyAndHost = keyFromConfiguration(configuration);
    return of(label, keyAndHost.key, keyAndHost.isHost);
  }

  @AutoCodec.Instantiator
  public static ConfiguredTargetKey of(
      Label label,
      @Nullable BuildConfigurationValue.Key configurationKey,
      boolean isHostConfiguration) {
    if (isHostConfiguration) {
      return hostInterner.intern(new HostConfiguredTargetKey(label, configurationKey));
    } else {
      return interner.intern(new ConfiguredTargetKey(label, configurationKey));
    }
  }

  static KeyAndHost keyFromConfiguration(@Nullable BuildConfiguration configuration) {
    return configuration == null
        ? KeyAndHost.NULL_INSTANCE
        : new KeyAndHost(
            BuildConfigurationValue.key(configuration), configuration.isHostConfiguration());
  }

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

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

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

  @Override
  public 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 int computeHashCode() {
    int configVal = configurationKey == null ? 79 : configurationKey.hashCode();
    return 31 * label.hashCode() + configVal + (isHostConfiguration() ? 41 : 0);
  }

  @Override
  public 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 this.isHostConfiguration() == other.isHostConfiguration()
        && Objects.equals(label, other.label)
        && Objects.equals(configurationKey, other.configurationKey);
  }

  public boolean isHostConfiguration() {
    return false;
  }

  public String prettyPrint() {
    if (label == null) {
      return "null";
    }
    return isHostConfiguration() ? (label + " (host)") : label.toString();
  }

  @Override
  public String toString() {
    return String.format(
        "%s %s %s (%s)",
        label,
        configurationKey,
        isHostConfiguration(),
        System.identityHashCode(this));
  }

  static class HostConfiguredTargetKey extends ConfiguredTargetKey {
    private HostConfiguredTargetKey(
        Label label, @Nullable BuildConfigurationValue.Key configurationKey) {
      super(label, configurationKey);
    }

    @Override
    public boolean isHostConfiguration() {
      return true;
    }
  }

  /**
   * Simple wrapper class for turning a {@link BuildConfiguration} into a {@link
   * BuildConfigurationValue.Key} and boolean isHost.
   */
  public static class KeyAndHost {
    private static final KeyAndHost NULL_INSTANCE = new KeyAndHost(null, false);

    @Nullable public final BuildConfigurationValue.Key key;
    final boolean isHost;

    private KeyAndHost(@Nullable BuildConfigurationValue.Key key, boolean isHost) {
      this.key = key;
      this.isHost = isHost;
    }
  }
}
