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

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.util.Fingerprint;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.util.ArrayList;
import java.util.Objects;

/**
 * Captures the set of providers rules and aspects can advertise. It is either of:
 *
 * <ul>
 *   <li>a set of builtin and Starlark providers
 *   <li>"can have any provider" set that alias rules have.
 * </ul>
 *
 * <p>Built-in providers should in theory only contain subclasses of {@link
 * com.google.devtools.build.lib.analysis.TransitiveInfoProvider}, but our current dependency
 * structure does not allow a reference to that class here.
 */
@Immutable
public final class AdvertisedProviderSet {
  private final boolean canHaveAnyProvider;
  private final ImmutableSet<Class<?>> builtinProviders;
  private final ImmutableSet<StarlarkProviderIdentifier> starlarkProviders;

  private AdvertisedProviderSet(
      boolean canHaveAnyProvider,
      ImmutableSet<Class<?>> builtinProviders,
      ImmutableSet<StarlarkProviderIdentifier> starlarkProviders) {
    this.canHaveAnyProvider = canHaveAnyProvider;
    this.builtinProviders = builtinProviders;
    this.starlarkProviders = starlarkProviders;
  }

  public static final AdvertisedProviderSet ANY =
      new AdvertisedProviderSet(true, ImmutableSet.of(), ImmutableSet.of());
  public static final AdvertisedProviderSet EMPTY =
      new AdvertisedProviderSet(false, ImmutableSet.of(), ImmutableSet.of());

  public static AdvertisedProviderSet create(
      ImmutableSet<Class<?>> builtinProviders,
      ImmutableSet<StarlarkProviderIdentifier> starlarkProviders) {
    if (builtinProviders.isEmpty() && starlarkProviders.isEmpty()) {
      return EMPTY;
    }
    return new AdvertisedProviderSet(false, builtinProviders, starlarkProviders);
  }

  @Override
  public int hashCode() {
    return Objects.hash(canHaveAnyProvider, builtinProviders, starlarkProviders);
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj) {
      return true;
    }

    if (!(obj instanceof AdvertisedProviderSet)) {
      return false;
    }

    AdvertisedProviderSet that = (AdvertisedProviderSet) obj;
    return this.canHaveAnyProvider == that.canHaveAnyProvider
        && Objects.equals(this.builtinProviders, that.builtinProviders)
        && Objects.equals(this.starlarkProviders, that.starlarkProviders);
  }

  @Override
  public String toString() {
    if (canHaveAnyProvider()) {
      return "Any Provider";
    }
    return String.format(
        "allowed built-in providers=%s, allowed Starlark providers=%s",
        builtinProviders, starlarkProviders);
  }

  /** Checks whether the rule can have any provider.
   *
   *  Used for alias rules.
   */
  public boolean canHaveAnyProvider() {
    return canHaveAnyProvider;
  }

  /** Get all advertised built-in providers. */
  public ImmutableSet<Class<?>> getBuiltinProviders() {
    return builtinProviders;
  }

  /** Get all advertised Starlark providers. */
  public ImmutableSet<StarlarkProviderIdentifier> getStarlarkProviders() {
    return starlarkProviders;
  }

  /**
   * Adds the fingerprints of this {@link AdvertisedProviderSet} into {@code fp}.
   *
   * <p>Fingerprints of {@link AdvertisedProviderSet} must have the following properties:
   *
   * <ul>
   *   <li>If {@code aps1.equals(aps2)} then {@code aps1} and {@code aps2} have the same
   *       fingerprint.
   *   <li>If {@code !aps1.equals(aps2)} then {@code aps1} and {@code aps2} don't have the same
   *       fingerprint (except for unintentional digest collisions).
   * </ul>
   *
   * <p>In other words, this method is a proxy for {@link #equals}. These properties *do not* need
   * to be maintained across Blaze versions (e.g. there's no need to worry about historical
   * serialized fingerprints).
   */
  public void fingerprint(Fingerprint fp) {
    fp.addBoolean(canHaveAnyProvider);
    // #builtinProviders and #starlarkProviders are ordered according to the calls to the builder
    // methods, and that order is assumed to be deterministic.
    builtinProviders.forEach(clazz -> fp.addString(clazz.getCanonicalName()));
    starlarkProviders.forEach(starlarkProvider -> starlarkProvider.fingerprint(fp));
  }

  public static Builder builder() {
    return new Builder();
  }

  /**
   * Returns {@code true} if this provider set can have any provider, or if it advertises the
   * specific Starlark provider requested.
   */
  public boolean advertises(StarlarkProviderIdentifier starlarkProvider) {
    if (canHaveAnyProvider()) {
      return true;
    }
    return starlarkProviders.contains(starlarkProvider);
  }

  /** Builder for {@link AdvertisedProviderSet} */
  public static class Builder {
    private boolean canHaveAnyProvider;
    private final ArrayList<Class<?>> builtinProviders;
    private final ArrayList<StarlarkProviderIdentifier> starlarkProviders;

    private Builder() {
      builtinProviders = new ArrayList<>();
      starlarkProviders = new ArrayList<>();
    }

    /** Advertise all providers inherited from a parent rule. */
    @CanIgnoreReturnValue
    public Builder addParent(AdvertisedProviderSet parentSet) {
      Preconditions.checkState(!canHaveAnyProvider, "Alias rules inherit from no other rules");
      Preconditions.checkState(!parentSet.canHaveAnyProvider(),
          "Cannot inherit from alias rules");
      builtinProviders.addAll(parentSet.getBuiltinProviders());
      starlarkProviders.addAll(parentSet.getStarlarkProviders());
      return this;
    }

    @CanIgnoreReturnValue
    public Builder addBuiltin(Class<?> builtinProvider) {
      this.builtinProviders.add(builtinProvider);
      return this;
    }

    public void canHaveAnyProvider() {
      Preconditions.checkState(builtinProviders.isEmpty() && starlarkProviders.isEmpty());
      this.canHaveAnyProvider = true;
    }

    public AdvertisedProviderSet build() {
      if (canHaveAnyProvider) {
        Preconditions.checkState(builtinProviders.isEmpty() && starlarkProviders.isEmpty());
        return ANY;
      }
      return AdvertisedProviderSet.create(
          ImmutableSet.copyOf(builtinProviders), ImmutableSet.copyOf(starlarkProviders));
    }

    @CanIgnoreReturnValue
    public Builder addStarlark(String providerName) {
      starlarkProviders.add(StarlarkProviderIdentifier.forLegacy(providerName));
      return this;
    }

    @CanIgnoreReturnValue
    public Builder addStarlark(StarlarkProviderIdentifier id) {
      starlarkProviders.add(id);
      return this;
    }
  }
}
