// 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 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 native and skylark providers
 *   <li>"can have any provider" set that alias rules have.
 * </ul>
 *
 * <p>Native 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<?>> nativeProviders;
  private final ImmutableSet<SkylarkProviderIdentifier> skylarkProviders;

  private AdvertisedProviderSet(boolean canHaveAnyProvider,
      ImmutableSet<Class<?>> nativeProviders,
      ImmutableSet<SkylarkProviderIdentifier> skylarkProviders) {
    this.canHaveAnyProvider = canHaveAnyProvider;
    this.nativeProviders = nativeProviders;
    this.skylarkProviders = skylarkProviders;
  }

  public static final AdvertisedProviderSet ANY =
      new AdvertisedProviderSet(true,
          ImmutableSet.<Class<?>>of(),
          ImmutableSet.<SkylarkProviderIdentifier>of());
  public static final AdvertisedProviderSet EMPTY =
      new AdvertisedProviderSet(false,
          ImmutableSet.<Class<?>>of(),
          ImmutableSet.<SkylarkProviderIdentifier>of());

  public static AdvertisedProviderSet create(
      ImmutableSet<Class<?>> nativeProviders,
      ImmutableSet<SkylarkProviderIdentifier> skylarkProviders) {
    if (nativeProviders.isEmpty() && skylarkProviders.isEmpty()) {
      return EMPTY;
    }
    return new AdvertisedProviderSet(false, nativeProviders, skylarkProviders);
  }

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

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

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

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

  @Override
  public String toString() {
    if (canHaveAnyProvider()) {
      return "Any Provider";
    }
    return String.format(
        "allowed native providers=%s, allowed Starlark providers=%s",
        getNativeProviders(), getSkylarkProviders());
  }

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

  /**
   * Get all advertised native providers.
   */
  public ImmutableSet<Class<?>> getNativeProviders() {
    return nativeProviders;
  }

  /**
   * Get all advertised Skylark providers.
   */
  public ImmutableSet<SkylarkProviderIdentifier> getSkylarkProviders() {
    return skylarkProviders;
  }

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

  /**
   * Returns {@code true} if this provider set can have any provider, or if it advertises the
   * specific native provider requested.
   */
  public boolean advertises(Class<?> nativeProviderClass) {
    if (canHaveAnyProvider()) {
      return true;
    }
    return nativeProviders.contains(nativeProviderClass);
  }

  /**
   * Returns {@code true} if this provider set can have any provider, or if it advertises the
   * specific skylark provider requested.
   */
  public boolean advertises(SkylarkProviderIdentifier skylarkProvider) {
    if (canHaveAnyProvider()) {
      return true;
    }
    return skylarkProviders.contains(skylarkProvider);
  }

  /** Builder for {@link AdvertisedProviderSet} */
  public static class Builder {
    private boolean canHaveAnyProvider;
    private final ArrayList<Class<?>> nativeProviders;
    private final ArrayList<SkylarkProviderIdentifier> skylarkProviders;
    private Builder() {
      nativeProviders = new ArrayList<>();
      skylarkProviders = new ArrayList<>();
    }

    /**
     * Advertise all providers inherited from a parent rule.
     */
    public Builder addParent(AdvertisedProviderSet parentSet) {
      Preconditions.checkState(!canHaveAnyProvider, "Alias rules inherit from no other rules");
      Preconditions.checkState(!parentSet.canHaveAnyProvider(),
          "Cannot inherit from alias rules");
      nativeProviders.addAll(parentSet.getNativeProviders());
      skylarkProviders.addAll(parentSet.getSkylarkProviders());
      return this;
    }

    public Builder addNative(Class<?> nativeProvider) {
      this.nativeProviders.add(nativeProvider);
      return this;
    }

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

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

    public Builder addSkylark(String providerName) {
      skylarkProviders.add(SkylarkProviderIdentifier.forLegacy(providerName));
      return this;
    }

    public Builder addSkylark(SkylarkProviderIdentifier id) {
      skylarkProviders.add(id);
      return this;
    }

    public Builder addSkylark(Provider.Key id) {
      skylarkProviders.add(SkylarkProviderIdentifier.forKey(id));
      return this;
    }
  }
}
