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

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

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

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

  public static ConfiguredTargetKey inTargetConfig(ConfiguredTarget configuredTarget) {
    return of(
        configuredTarget.getOriginalLabel(),
        configuredTarget.getConfigurationKey(),
        /*isHostConfiguration=*/ false);
  }

  /**
   * 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", label, configurationKey, isHostConfiguration());
  }

  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;
    }
  }
}
