// Copyright 2016 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.analysis;

import static com.google.common.base.Preconditions.checkArgument;

import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.packages.AdvertisedProviderSet;
import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.packages.Target;
import com.google.devtools.build.lib.skyframe.ConfiguredTargetAndData;

/** A provider that gives information about the aliases a rule was resolved through. */
@Immutable
public final class AliasProvider implements TransitiveInfoProvider {
  // We don't expect long alias chains, so it's better to have a list instead of a nested set
  private final ImmutableList<Label> aliasChain;

  private AliasProvider(ImmutableList<Label> aliasChain) {
    this.aliasChain = aliasChain;
  }

  /**
   * Creates an alias provider indicating that the given rule is an alias to {@code actual}.
   *
   * <p>The given rule must either explicitly advertise {@link AliasProvider} or advertise that it
   * {@linkplain AdvertisedProviderSet#canHaveAnyProvider() can have any provider}.
   */
  public static AliasProvider fromAliasRule(Rule rule, ConfiguredTarget actual) {
    checkArgument(mayBeAlias(rule), "%s does not advertise AliasProvider", rule);

    ImmutableList<Label> chain;
    AliasProvider dep = actual.getProvider(AliasProvider.class);
    if (dep == null) {
      chain = ImmutableList.of(rule.getLabel());
    } else {
      chain =
          ImmutableList.<Label>builderWithExpectedSize(dep.aliasChain.size() + 1)
              .add(rule.getLabel())
              .addAll(dep.aliasChain)
              .build();
    }
    return new AliasProvider(chain);
  }

  /**
   * Returns the label by which it was referred to in the BUILD file.
   *
   * <p>For non-alias rules, it's the label of the rule itself, for alias rules, it's the label of
   * the alias rule.
   */
  public static Label getDependencyLabel(TransitiveInfoCollection dep) {
    AliasProvider aliasProvider = dep.getProvider(AliasProvider.class);
    return aliasProvider != null ? aliasProvider.aliasChain.get(0) : dep.getLabel();
  }

  /**
   * Returns all labels by which it can be referred to in the BUILD file.
   *
   * <p>For non-alias rules, it's the label of the rule itself. For alias rules, they're the label
   * of the alias and the label of alias' target rule.
   */
  public static ImmutableList<Label> getDependencyLabels(TransitiveInfoCollection dep) {
    AliasProvider aliasProvider = dep.getProvider(AliasProvider.class);
    return aliasProvider != null
        ? ImmutableList.of(aliasProvider.aliasChain.get(0), dep.getLabel())
        : ImmutableList.of(dep.getLabel());
  }

  /**
   * Returns the list of aliases from top to bottom (i.e. the last alias depends on the actual
   * resolved target and the first alias is the one that was in the attribute of the rule currently
   * being analyzed)
   */
  public ImmutableList<Label> getAliasChain() {
    return aliasChain;
  }

  /** The way {@link #describeTargetWithAliases(ConfiguredTargetAndData, TargetMode) reports the
   * kind of a target. */
  public enum TargetMode {
    WITH_KIND,      // Specify the kind of the target
    WITHOUT_KIND,   // Only say "target"
  }

  /**
   * Prints a nice description of a target.
   *
   * Also adds the aliases it was reached through, if any.
   *
   * @param target the target to describe
   * @param targetMode how to express the kind of the target
   */
  public static String describeTargetWithAliases(
      ConfiguredTargetAndData target, TargetMode targetMode) {
    String kind = targetMode == TargetMode.WITH_KIND
        ? target.getTarget().getTargetKind() : "target";
    AliasProvider aliasProvider = target.getConfiguredTarget().getProvider(AliasProvider.class);
    if (aliasProvider == null) {
      return kind + " '" + target.getTarget().getLabel() + "'";
    }

    ImmutableList<Label> aliasChain = aliasProvider.aliasChain;
    StringBuilder result = new StringBuilder();
    result.append("alias '").append(aliasChain.get(0)).append("'");
    result
        .append(" referring to ")
        .append(kind)
        .append(" '")
        .append(target.getTarget().getLabel())
        .append("'");
    if (aliasChain.size() > 1) {
      result
          .append(" through '")
          .append(Joiner.on("' -> '").join(aliasChain.subList(1, aliasChain.size())))
          .append("'");
    }

    return result.toString();
  }

  /**
   * Returns {@code true} iff the given {@link TransitiveInfoCollection} has an {@link
   * AliasProvider}.
   */
  public static boolean isAlias(TransitiveInfoCollection dep) {
    return dep.getProvider(AliasProvider.class) != null;
  }

  /**
   * Returns {@code true} if the given target <em>may</em> contain an {@link AliasProvider} when
   * analyzed.
   *
   * <p>This method returns {@code true} for the {@code alias} rule as well as some other alias-like
   * rules such as {@code bind}.
   *
   * <p>Note that due to the presence of late-bound aliases, this may return {@code true} even if
   * {@link #isAlias} on the configured target returns {@code false}.
   */
  public static boolean mayBeAlias(Target target) {
    if (!(target instanceof Rule)) {
      return false;
    }
    Rule rule = (Rule) target;
    AdvertisedProviderSet providerSet = rule.getRuleClassObject().getAdvertisedProviders();
    return providerSet.canHaveAnyProvider()
        || providerSet.getBuiltinProviders().contains(AliasProvider.class);
  }
}
