// Copyright 2022 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.ImmutableMap.toImmutableMap;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static com.google.devtools.build.lib.packages.RuleClass.Builder.STARLARK_BUILD_SETTING_DEFAULT_ATTR_NAME;

import com.google.common.base.Preconditions;
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.starlark.StarlarkBuildSettingsDetailsValue;
import com.google.devtools.build.lib.analysis.starlark.StarlarkTransition.TransitionException;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.packages.BuildType.SelectorList;
import com.google.devtools.build.lib.packages.NoSuchPackageException;
import com.google.devtools.build.lib.packages.NoSuchTargetException;
import com.google.devtools.build.lib.packages.Package;
import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.packages.Target;
import com.google.devtools.build.lib.packages.Type;
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.build.skyframe.SkyframeIterableResult;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;

/** A builder for {@link StarlarkBuildSettingsDetailsValue} instances. */
final class StarlarkBuildSettingsDetailsFunction implements SkyFunction {

  // Use the plain strings rather than reaching into the Alias class and adding a dependency edge.
  // TODO(blaze-configurability-team): We can probably afford the edge now that this is
  //   inside of skyframe_cluster.
  private static final String ALIAS_RULE_NAME = "alias";
  private static final String ALIAS_ACTUAL_ATTRIBUTE_NAME = "actual";

  public StarlarkBuildSettingsDetailsFunction() {}

  @Override
  @Nullable
  public SkyValue compute(SkyKey skyKey, Environment env)
      throws InterruptedException, StarlarkBuildSettingsDetailsException {
    StarlarkBuildSettingsDetailsValue.Key key = (StarlarkBuildSettingsDetailsValue.Key) skyKey;

    // Ideally, callers would bypass StarlarkBuildSettingsDetailsFunction entirely when the
    // key is empty but provide a fast escape here just in case.
    if (key.buildSettings().isEmpty()) {
      return StarlarkBuildSettingsDetailsValue.EMPTY;
    }

    try {
      ImmutableMap<PackageValue.Key, PackageValue> buildSettingPackages =
          getBuildSettingPackages(env, key.buildSettings());
      if (buildSettingPackages == null) {
        return null;
      }

      // Each setting is unique so don't need a merge function.
      ImmutableMap<Label, Rule> rawSettingToActualRule =
          key.buildSettings().stream()
              .collect(
                  toImmutableMap(
                      setting -> setting,
                      setting -> getActual(buildSettingPackages, setting).getAssociatedRule()));
      ImmutableSet<Rule> actualRules = ImmutableSet.copyOf(rawSettingToActualRule.values());

      // Calculate info based on the actual rules
      // Different rules have different labels so don't need a merge function
      ImmutableMap<Label, Object> buildSettingToDefault =
          actualRules.stream()
              .collect(
                  toImmutableMap(
                      Rule::getLabel,
                      rule -> {
                        if (rule.getRuleClassObject().getBuildSetting().allowsMultiple()) {
                          return ImmutableList.of(
                              rule.getAttr(STARLARK_BUILD_SETTING_DEFAULT_ATTR_NAME));
                        }
                        return rule.getAttr(STARLARK_BUILD_SETTING_DEFAULT_ATTR_NAME);
                      }));
      ImmutableMap<Label, Type<?>> buildSettingToType =
          actualRules.stream()
              .collect(
                  toImmutableMap(
                      Rule::getLabel,
                      rule -> rule.getRuleClassObject().getBuildSetting().getType()));
      ImmutableSet<Label> buildSettingIsAllowsMultiple =
          actualRules.stream()
              .filter(rule -> rule.getRuleClassObject().getBuildSetting().allowsMultiple())
              .map(Rule::getLabel)
              .collect(toImmutableSet());

      // Calculate the alias table (filtering out non-aliases!)
      ImmutableMap<Label, Label> aliasToActual =
          rawSettingToActualRule.entrySet().stream()
              .filter(entry -> !entry.getKey().equals(entry.getValue().getLabel()))
              .collect(toImmutableMap(Map.Entry::getKey, entry -> entry.getValue().getLabel()));

      return StarlarkBuildSettingsDetailsValue.create(
          buildSettingToDefault, buildSettingToType, buildSettingIsAllowsMultiple, aliasToActual);

    } catch (TransitionException e) {
      throw new StarlarkBuildSettingsDetailsException(e);
    }
  }

  /**
   * Given a {@link ConfigurationTransition} find all build settings read or set by the transition
   * and load their packages.
   *
   * <p>In the case that build settings are referred to by aliases, we do a couple loops of package
   * loading. We generally don't expect build settings to be aliased multiple times so we don't
   * expect this while loop (and relevant null return) to happen more than two or three times (and
   * usually only once).
   *
   * @return the package keys and values of build settings or null if not all packages are
   *     available. if not null, and some build settings are referenced by alias, the returned map
   *     will include both alias and actual packages to allow for alias chain following at a later
   *     state.
   */
  @Nullable
  private static ImmutableMap<PackageValue.Key, PackageValue> getBuildSettingPackages(
      SkyFunction.Environment env, ImmutableSet<Label> buildSettings)
      throws InterruptedException, TransitionException {
    HashMap<PackageValue.Key, PackageValue> buildSettingPackages = new HashMap<>();
    // This happens before cycle detection so keep track of all seen build settings to ensure
    // we don't get stuck in endless loops (e.g. //alias1->//alias2 && //alias2->alias1)
    Set<Label> allSeenBuildSettings = new HashSet<>();
    ImmutableSet<Label> unverifiedBuildSettings = buildSettings;
    while (!unverifiedBuildSettings.isEmpty()) {
      for (Label buildSetting : unverifiedBuildSettings) {
        if (!allSeenBuildSettings.add(buildSetting)) {
          throw new TransitionException(
              String.format(
                  "Dependency cycle involving '%s' detected in aliased build settings",
                  buildSetting));
        }
      }
      ImmutableSet<PackageValue.Key> packageKeys =
          getPackageKeysFromLabels(unverifiedBuildSettings);
      SkyframeIterableResult newlyLoaded = env.getOrderedValuesAndExceptions(packageKeys);
      if (env.valuesMissing()) {
        return null;
      }
      for (SkyKey packageKey : packageKeys) {
        try {
          SkyValue skyValue = newlyLoaded.nextOrThrow(NoSuchPackageException.class);
          buildSettingPackages.put((PackageValue.Key) packageKey, (PackageValue) skyValue);
        } catch (NoSuchPackageException e) {
          throw new TransitionException(e);
        }
      }
      unverifiedBuildSettings =
          verifyBuildSettingsAndGetAliases(buildSettingPackages, unverifiedBuildSettings);
    }
    return ImmutableMap.copyOf(buildSettingPackages);
  }

  /** Given a set of labels, return a set of their package {@link PackageValue.Key}s. */
  private static ImmutableSet<PackageValue.Key> getPackageKeysFromLabels(Set<Label> buildSettings) {
    ImmutableSet.Builder<PackageValue.Key> keyBuilder = new ImmutableSet.Builder<>();
    for (Label setting : buildSettings) {
      keyBuilder.add(PackageValue.key(setting.getPackageIdentifier()));
    }
    return keyBuilder.build();
  }

  /**
   * Given a preliminary set of alleged build setting labels and relevant packages, verify that the
   * given {@link Label}s actually correspond to build setting targets.
   *
   * <p>This method is meant to be run in a loop to handle aliased build settings. It also
   * explicitly bans configured 'actual' values for aliased build settings. Since build settings are
   * used to define configuration, there should be better ways to accomplish disparate
   * configurations than configured aliases. Also from a technical standpoint, it's unclear what
   * configuration is correct to use to resolve configured attributes.
   *
   * @param buildSettingPackages packages that include {@code buildSettingsToVerify}'s packages
   * @param buildSettingsToVerify alleged build setting labels
   * @return a set of "actual" labels of any build settings that are referenced by aliases (note -
   *     if the "actual" value of aliasA is aliasB, this method returns aliasB AKA we only follow
   *     one link in the alias chain per call of this method)
   */
  private static ImmutableSet<Label> verifyBuildSettingsAndGetAliases(
      Map<PackageValue.Key, PackageValue> buildSettingPackages, Set<Label> buildSettingsToVerify)
      throws TransitionException {
    ImmutableSet.Builder<Label> actualSettingBuilder = new ImmutableSet.Builder<>();
    for (Label allegedBuildSetting : buildSettingsToVerify) {
      Package buildSettingPackage =
          buildSettingPackages
              .get(PackageValue.key(allegedBuildSetting.getPackageIdentifier()))
              .getPackage();
      Preconditions.checkNotNull(
          buildSettingPackage, "Reading build setting for which we don't have a package");
      Target buildSettingTarget;
      try {
        buildSettingTarget = buildSettingPackage.getTarget(allegedBuildSetting.getName());
      } catch (NoSuchTargetException e) {
        throw new TransitionException(e);
      }
      if (buildSettingTarget.getAssociatedRule() == null) {
        throw new TransitionException(
            String.format(
                "attempting to transition on '%s' which is not a build setting",
                allegedBuildSetting));
      }
      if (buildSettingTarget.getAssociatedRule().getRuleClass().equals(ALIAS_RULE_NAME)) {
        Object actualValue =
            buildSettingTarget.getAssociatedRule().getAttr(ALIAS_ACTUAL_ATTRIBUTE_NAME);
        if (actualValue instanceof Label) {
          actualSettingBuilder.add((Label) actualValue);
          continue;
        } else if (actualValue instanceof SelectorList) {
          // configured "actual" value
          throw new TransitionException(
              String.format(
                  "attempting to transition on aliased build setting '%s', the actual value of"
                      + " which uses select(). Aliased build settings with configured actual values"
                      + " is not supported.",
                  allegedBuildSetting));
        } else {
          throw new IllegalStateException(
              String.format(
                  "Alias target '%s' with 'actual' attr value not equals to "
                      + "a label or a selectorlist",
                  allegedBuildSetting));
        }
      }
      if (!buildSettingTarget.getAssociatedRule().isBuildSetting()) {
        throw new TransitionException(
            String.format(
                "attempting to transition on '%s' which is not a build setting",
                allegedBuildSetting));
      }
    }
    return actualSettingBuilder.build();
  }

  /**
   * Given a {@link Label} that could be an {@link com.google.devtools.build.lib.rules.Alias} and a
   * set of packages, find the actual target that {@link Label} ultimately points to.
   *
   * <p>This method assumes that the packages of the entire {@link
   * com.google.devtools.build.lib.rules.Alias} chain (if {@code setting} is indeed an alias) are
   * included in {@code buildSettingPackages}
   *
   * <p>This checking is likely done in {@link #verifyBuildSettingsAndGetAliases}.
   */
  private static Target getActual(
      Map<PackageValue.Key, PackageValue> buildSettingPackages, Label setting) {
    Target target = getTarget(buildSettingPackages, setting);
    while (target.getAssociatedRule().getRuleClass().equals(ALIAS_RULE_NAME)) {
      target =
          getTarget(
              buildSettingPackages,
              (Label) target.getAssociatedRule().getAttr(ALIAS_ACTUAL_ATTRIBUTE_NAME));
    }
    return target;
  }

  /**
   * Return a target given its label and a set of package values we know to contain the target.
   *
   * <p>This method is essentially a wrapper around PackageValue.getTarget.
   *
   * @param buildSettingPackages packages that include {@code setting}'s package
   */
  private static Target getTarget(
      Map<PackageValue.Key, PackageValue> buildSettingPackages, Label setting) {
    Package buildSettingPackage =
        buildSettingPackages.get(PackageValue.key(setting.getPackageIdentifier())).getPackage();
    Preconditions.checkNotNull(
        buildSettingPackage, "Reading build setting for which we don't have a package");
    Target target;
    try {
      target = buildSettingPackage.getTarget(setting.getName());
    } catch (NoSuchTargetException e) {
      // This should never happen, see javadoc.
      throw new IllegalStateException(e);
    }
    return target;
  }

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