// Copyright 2015 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.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.collect.Interner;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.analysis.config.BuildOptions;
import com.google.devtools.build.lib.analysis.config.FragmentClassSet;
import com.google.devtools.build.lib.concurrent.BlazeInterners;
import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec.VisibleForSerialization;
import com.google.devtools.build.skyframe.SkyFunctionName;
import com.google.devtools.build.skyframe.SkyKey;
import com.google.devtools.build.skyframe.SkyValue;
import com.google.devtools.common.options.OptionsParsingException;
import java.io.Serializable;
import java.util.Objects;

/** A Skyframe value representing a {@link BuildConfiguration}. */
// TODO(bazel-team): mark this immutable when BuildConfiguration is immutable.
// @Immutable
@AutoCodec
@ThreadSafe
public class BuildConfigurationValue implements SkyValue {
  private final BuildConfiguration configuration;

  BuildConfigurationValue(BuildConfiguration configuration) {
    this.configuration = configuration;
  }

  public BuildConfiguration getConfiguration() {
    return configuration;
  }

  /**
   * Creates a new configuration key based on the given options, after applying a platform mapping
   * transformation.
   *
   * @param platformMappingValue sky value that can transform a configuration key based on a
   *     platform mapping
   * @param fragments set of options fragments this configuration should cover
   * @param options the desired configuration
   * @throws OptionsParsingException if the platform mapping cannot be parsed
   */
  public static Key keyWithPlatformMapping(
      PlatformMappingValue platformMappingValue,
      FragmentClassSet fragments,
      BuildOptions options)
      throws OptionsParsingException {
    return platformMappingValue.map(keyWithoutPlatformMapping(fragments, options));
  }

  /**
   * Returns the key for a requested configuration.
   *
   * <p>Callers are responsible for applying the platform mapping or ascertaining that a platform
   * mapping is not required.
   *
   * @param fragments the fragments the configuration should contain
   * @param options the {@link BuildOptions} object the {@link BuildOptions} should be rebuilt from
   */
  public static Key keyWithoutPlatformMapping(FragmentClassSet fragments, BuildOptions options) {
    return Key.create(fragments, options);
  }

  /**
   * Returns a configuration key for the given configuration.
   *
   * <p>Note that this key creation method does not apply a platform mapping, it is assumed that the
   * passed configuration was created with one such and thus its key does not need to be mapped
   * again.
   *
   * @param buildConfiguration configuration whose key is requested
   */
  public static Key key(BuildConfiguration buildConfiguration) {
    return keyWithoutPlatformMapping(
        buildConfiguration.fragmentClasses(), buildConfiguration.getOptions());
  }

  /** {@link SkyKey} for {@link BuildConfigurationValue}. */
  @AutoCodec
  public static final class Key implements SkyKey, Serializable {
    private static final Interner<Key> keyInterner = BlazeInterners.newWeakInterner();

    private final FragmentClassSet fragments;
    private final BuildOptions options;
    private final int hashCode;

    @AutoCodec.Instantiator
    @VisibleForSerialization
    static Key create(FragmentClassSet fragments, BuildOptions options) {
      return keyInterner.intern(new Key(fragments, options));
    }

    private Key(FragmentClassSet fragments, BuildOptions options) {
      this.fragments = Preconditions.checkNotNull(fragments);
      this.options = Preconditions.checkNotNull(options);
      this.hashCode = Objects.hash(fragments, options);
    }

    @VisibleForTesting
    public FragmentClassSet getFragments() {
      return fragments;
    }

    public BuildOptions getOptions() {
      return options;
    }

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

    @Override
    public boolean equals(Object o) {
      if (this == o) {
        return true;
      }
      if (!(o instanceof Key)) {
        return false;
      }
      Key otherConfig = (Key) o;
      return options.equals(otherConfig.options) && fragments.equals(otherConfig.fragments);
    }

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

    @Override
    public String toString() {
      // This format is depended on by integration tests.
      // TODO(blaze-configurability-team): This should at least include the length of fragments.
      // to at least remind devs that this Key has TWO key parts.
      return "BuildConfigurationValue.Key[" + options.checksum() + "]";
    }

    /**
     * Return a string representation that can be safely used for comparison purposes.
     *
     * <p>Unlike toString, which is short and good for printing in debug contexts, this is long
     * because it includes sufficient information in options and fragments. toString alone is
     * insufficient because multiple Keys can have the same options checksum (and thus same
     * toString) but different fragments.
     *
     * <p>This function is meant to address two potential, trimming-related scenarios: 1. If
     * trimming by only trimming BuildOptions (e.g. --trim_test_configuration), then after the
     * initial trimming, fragments has extra classes (corresponding to those trimmed). Notably,
     * dependencies of trimmed targets will create Keys with a properly trimmed set of fragments.
     * Thus, will easily have two Keys with the same (trimmed) BuildOptions but different fragments
     * yet corresponding to the same (trimmed) BuildConfigurationValue.
     *
     * <p>2. If trimming by only trimming fragments (at time of this comment, unsure whether this is
     * ever done in active code), then BuildOptions has extra classes. The returned
     * BuildConfigurationValue is properly trimmed (with the extra classes BuildOptions removed)
     * although notably with a different checksum compared to the Key checksum. Note that given a
     * target that is doing trimming like this, the reverse dependency of the target (i.e. without
     * trimming) could easily involve a Key with the same (untrimmed!) BuildOptions but different
     * fragments. However, unlike in case 1, they will correspond to different
     * BuildConfigurationValue.
     */
    public String toComparableString() {
      return "BuildConfigurationValue.Key[" + options.checksum() + ", " + fragments + "]";
    }
  }
}
