// 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 static com.google.common.collect.ImmutableSet.toImmutableSet;
import static com.google.devtools.build.lib.analysis.config.StarlarkDefinedConfigTransition.COMMAND_LINE_OPTION_PREFIX;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.VerifyException;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.analysis.BlazeDirectories;
import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider;
import com.google.devtools.build.lib.analysis.PlatformOptions;
import com.google.devtools.build.lib.analysis.config.BuildConfigurationValue;
import com.google.devtools.build.lib.analysis.config.BuildOptions;
import com.google.devtools.build.lib.analysis.config.CoreOptions;
import com.google.devtools.build.lib.analysis.config.FragmentFactory;
import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException;
import com.google.devtools.build.lib.analysis.config.OptionInfo;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.RepositoryName;
import com.google.devtools.build.lib.packages.RuleClassProvider;
import com.google.devtools.build.lib.packages.semantics.BuildLanguageOptions;
import com.google.devtools.build.lib.util.Fingerprint;
import com.google.devtools.build.skyframe.SkyFunction;
import com.google.devtools.build.skyframe.SkyFunctionException;
import com.google.devtools.build.skyframe.SkyKey;
import com.google.devtools.build.skyframe.SkyValue;
import com.google.devtools.common.options.OptionDefinition;
import com.google.devtools.common.options.OptionMetadataTag;
import com.google.devtools.common.options.OptionsParsingException;
import java.util.Map;
import java.util.TreeMap;
import javax.annotation.Nullable;
import net.starlark.java.eval.StarlarkSemantics;

/** A builder for {@link BuildConfigurationValue} instances. */
public final class BuildConfigurationFunction implements SkyFunction {

  // The length of the hash of the config tacked onto the end of the output path.
  // Limited for ergonomics and MAX_PATH reasons.
  private static final int HASH_LENGTH = 12;

  private final BlazeDirectories directories;
  private final ConfiguredRuleClassProvider ruleClassProvider;
  private final FragmentFactory fragmentFactory = new FragmentFactory();

  public BuildConfigurationFunction(
      BlazeDirectories directories, RuleClassProvider ruleClassProvider) {
    this.directories = directories;
    this.ruleClassProvider = (ConfiguredRuleClassProvider) ruleClassProvider;
  }

  @Override
  @Nullable
  public SkyValue compute(SkyKey skyKey, Environment env)
      throws InterruptedException, BuildConfigurationFunctionException {
    WorkspaceNameValue workspaceNameValue = (WorkspaceNameValue) env
        .getValue(WorkspaceNameValue.key());
    if (workspaceNameValue == null) {
      return null;
    }

    StarlarkSemantics starlarkSemantics = PrecomputedValue.STARLARK_SEMANTICS.get(env);
    if (starlarkSemantics == null) {
      return null;
    }
    BuildConfigurationKey key = (BuildConfigurationKey) skyKey.argument();

    BuildOptions targetOptions = key.getOptions();

    String transitionDirectoryNameFragment;
    if (targetOptions
        .get(CoreOptions.class)
        .outputDirectoryNamingScheme
        .equals(CoreOptions.OutputDirectoryNamingScheme.DIFF_AGAINST_BASELINE)) {
      // Herein lies a hack to apply platform mappings to the baseline options.
      // TODO(blaze-configurability-team): this should become unnecessary once --platforms is marked
      //   as EXPLICIT_IN_OUTPUT_PATH
      PlatformMappingValue platformMappingValue =
          (PlatformMappingValue)
              env.getValue(
                  PlatformMappingValue.Key.create(
                      targetOptions.get(PlatformOptions.class).platformMappings));
      if (platformMappingValue == null) {
        return null;
      }
      BuildOptions baselineOptions = PrecomputedValue.BASELINE_CONFIGURATION.get(env);
      try {
        BuildOptions mappedBaselineOptions =
            BuildConfigurationKey.withPlatformMapping(platformMappingValue, baselineOptions)
                .getOptions();
        transitionDirectoryNameFragment =
            computeNameFragmentWithDiff(targetOptions, mappedBaselineOptions);
      } catch (OptionsParsingException e) {
        throw new BuildConfigurationFunctionException(e);
      }
    } else {
      transitionDirectoryNameFragment =
          computeNameFragmentWithAffectedByStarlarkTransition(targetOptions);
    }

    try {
      return BuildConfigurationValue.create(
          targetOptions,
          RepositoryName.createUnvalidated(workspaceNameValue.getName()),
          starlarkSemantics.getBool(BuildLanguageOptions.EXPERIMENTAL_SIBLING_REPOSITORY_LAYOUT),
          transitionDirectoryNameFragment,
          // Arguments below this are server-global.
          directories,
          ruleClassProvider,
          fragmentFactory);
    } catch (InvalidConfigurationException e) {
      throw new BuildConfigurationFunctionException(e);
    }
  }

  private static final class BuildConfigurationFunctionException extends SkyFunctionException {
    BuildConfigurationFunctionException(Exception e) {
      super(e, Transience.PERSISTENT);
    }
  }

  /**
   * Compute the hash for the new BuildOptions based on the names and values of all options (both
   * native and Starlark) that are different from some supplied baseline configuration.
   */
  private static String computeNameFragmentWithDiff(
      BuildOptions toOptions, BuildOptions baselineOptions) {
    // Quick short-circuit for trivial case.
    if (toOptions.equals(baselineOptions)) {
      return "";
    }

    // TODO(blaze-configurability-team): As a mild performance update, getFirst already includes
    //   details of the corresponding option. Could incorporate this instead of hashChosenOptions
    //   regenerating the OptionDefinitions and values.
    BuildOptions.OptionsDiff diff = BuildOptions.diff(toOptions, baselineOptions);
    // Note: getFirst only excludes options trimmed between baselineOptions to toOptions and this is
    //   considered OK as a given Rule should not be being built with options of different
    //   trimmings. See longform note in {@link ConfiguredTargetKey} for details.
    ImmutableSet<String> chosenNativeOptions =
        diff.getFirst().keySet().stream()
            .filter(
                optionDef ->
                    !optionDef.hasOptionMetadataTag(OptionMetadataTag.EXPLICIT_IN_OUTPUT_PATH))
            .map(OptionDefinition::getOptionName)
            .collect(toImmutableSet());
    // Note: getChangedStarlarkOptions includes all changed options, added options and removed
    //   options between baselineOptions and toOptions. This is necessary since there is no current
    //   notion of trimming a Starlark option: 'null' or non-existent justs means set to default.
    ImmutableSet<String> chosenStarlarkOptions =
        diff.getChangedStarlarkOptions().stream().map(Label::toString).collect(toImmutableSet());
    return hashChosenOptions(toOptions, chosenNativeOptions, chosenStarlarkOptions);
  }

  /**
   * Compute the output directory name fragment corresponding to the new BuildOptions based on the
   * names and values of all options (both native and Starlark) previously transitioned anywhere in
   * the build by Starlark transitions. Options only set on command line are not affecting the
   * computation.
   *
   * @param toOptions the {@link BuildOptions} to use to calculate which we need to compute {@code
   *     transitionDirectoryNameFragment}.
   */
  private static String computeNameFragmentWithAffectedByStarlarkTransition(
      BuildOptions toOptions) {
    CoreOptions buildConfigOptions = toOptions.get(CoreOptions.class);
    if (buildConfigOptions.affectedByStarlarkTransition.isEmpty()) {
      return "";
    }

    ImmutableList.Builder<String> affectedNativeOptions = ImmutableList.builder();
    ImmutableList.Builder<String> affectedStarlarkOptions = ImmutableList.builder();

    for (String optionName : buildConfigOptions.affectedByStarlarkTransition) {
      if (optionName.startsWith(COMMAND_LINE_OPTION_PREFIX)) {
        String nativeOptionName = optionName.substring(COMMAND_LINE_OPTION_PREFIX.length());
        affectedNativeOptions.add(nativeOptionName);
      } else {
        affectedStarlarkOptions.add(optionName);
      }
    }

    return hashChosenOptions(
        toOptions, affectedNativeOptions.build(), affectedStarlarkOptions.build());
  }

  /**
   * Compute a hash of the given BuildOptions by hashing only the options referenced in both
   * chosenNative and chosenStarlark. The order of the chosen order does not matter (as this
   * function will effectively sort them into a canonical order) and the pre-hash for each option
   * will be of the form (//command_line_option:[native option]|[Starlark option label])=[value].
   *
   * <p>If a supplied native option does not exist, it is skipped (as it is presumed non-existence
   * is due to trimming).
   *
   * <p>If a supplied Starlark option does exist, the pre-hash will be [Starlark option label]@null
   * (as it is presumed non-existence is due to being set to default value).
   */
  private static String hashChosenOptions(
      BuildOptions toOptions, Iterable<String> chosenNative, Iterable<String> chosenStarlark) {
    // TODO(blaze-configurability-team): A mild performance optimization would have this be global.
    ImmutableMap<String, OptionInfo> optionInfoMap = OptionInfo.buildMapFrom(toOptions);

    // Note that the TreeMap guarantees a stable ordering of keys and thus
    // it is okay if chosenNative or chosenStarlark do not have a stable iteration order
    TreeMap<String, Object> toHash = new TreeMap<>();
    for (String nativeOptionName : chosenNative) {
      Object value;
      try {
        OptionInfo optionInfo = optionInfoMap.get(nativeOptionName);
        if (optionInfo == null) {
          // This can occur if toOptions has been trimmed but the supplied chosen native options
          // includes that trimmed options.
          // (e.g. legacy naming mode, using --trim_test_configuration and --test_arg transition).
          continue;
        }
        value =
            optionInfo
                .getDefinition()
                .getField()
                .get(toOptions.get(optionInfoMap.get(nativeOptionName).getOptionClass()));
      } catch (IllegalAccessException e) {
        throw new VerifyException(
            "IllegalAccess for option " + nativeOptionName + ": " + e.getMessage());
      }
      // TODO(blaze-configurability-team): The commandline option is legacy and can be removed
      //   after fixing up all the associated tests.
      toHash.put("//command_line_option:" + nativeOptionName, value);
    }
    for (String starlarkOptionName : chosenStarlark) {
      Object value =
          toOptions.getStarlarkOptions().get(Label.parseAbsoluteUnchecked(starlarkOptionName));
      toHash.put(starlarkOptionName, value);
    }

    if (toHash.isEmpty()) {
      return "";
    } else {
      ImmutableList.Builder<String> hashStrs = ImmutableList.builderWithExpectedSize(toHash.size());
      for (Map.Entry<String, Object> singleOptionAndValue : toHash.entrySet()) {
        Object value = singleOptionAndValue.getValue();
        if (value != null) {
          hashStrs.add(singleOptionAndValue.getKey() + "=" + value);
        } else {
          // Avoid using =null to different from value being the non-null String "null"
          hashStrs.add(singleOptionAndValue.getKey() + "@null");
        }
      }
      return transitionDirectoryNameFragment(hashStrs.build());
    }
  }

  @VisibleForTesting
  public static String transitionDirectoryNameFragment(Iterable<String> opts) {
    Fingerprint fp = new Fingerprint();
    for (String opt : opts) {
      fp.addString(opt);
    }
    // Shorten the hash to 48 bits. This should provide sufficient collision avoidance
    // (that is, we don't expect anyone to experience a collision ever).
    // Shortening the hash is important for Windows paths that tend to be short.
    String suffix = fp.hexDigestAndReset().substring(0, HASH_LENGTH);
    return "ST-" + suffix;
  }
}
