// 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.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.analysis.TransitiveInfoProvider;
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec.VisibleForSerialization;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.util.Objects;
import java.util.function.Function;
import java.util.function.Predicate;
import javax.annotation.Nullable;

/**
 * Represents a constraint on a set of providers required by a dependency (of a rule or an aspect).
 *
 * <p>Currently we support three kinds of constraints:
 *
 * <ul>
 *   <li>accept any dependency.
 *   <li>accept no dependency (used for aspects-on-aspects to indicate that an aspect never wants to
 *       see any other aspect applied to a target.
 *   <li>accept a dependency that provides all providers from one of several sets of providers. It
 *       just so happens that in all current usages these sets are either all builtin providers or
 *       all Starlark providers, so this is the only use case this class currently supports.
 * </ul>
 */
@Immutable
public final class RequiredProviders {
  /** A constraint: either ANY, NONE, or RESTRICTED */
  private final Constraint constraint;
  /**
   * Sets of builtin providers. If non-empty, {@link #constraint} is {@link Constraint#RESTRICTED}
   */
  private final ImmutableList<ImmutableSet<Class<? extends TransitiveInfoProvider>>>
      builtinProviders;
  /**
   * Sets of builtin providers. If non-empty, {@link #constraint} is {@link Constraint#RESTRICTED}
   */
  private final ImmutableList<ImmutableSet<StarlarkProviderIdentifier>> starlarkProviders;

  public String getDescription() {
    return constraint.getDescription(this);
  }

  @Override
  public String toString() {
    return getDescription();
  }

  /**
   * Returns the list of sets of acceptable Starlark providers for a restricted constraint, or an
   * empty list for an "any" or "none" constraint.
   *
   * <p>This method is intended for documentation generation. Do not use it for evaluating whether
   * provider constraints are satisfied: it does not distinguish between {@code acceptsAny} and
   * {@code acceptsNone}, and it does not export built-in TransitiveInfoProvider constraints.
   */
  public ImmutableList<ImmutableSet<StarlarkProviderIdentifier>> getStarlarkProviders() {
    return starlarkProviders;
  }

  /** Represents one of the constraints as desctibed in {@link RequiredProviders} */
  @VisibleForSerialization
  enum Constraint {
    /** Accept any dependency */
    ANY {
      @Override
      public boolean satisfies(
          AdvertisedProviderSet advertisedProviderSet,
          RequiredProviders requiredProviders,
          Builder missing) {
        return true;
      }

      @Override
      public boolean satisfies(
          Predicate<Class<? extends TransitiveInfoProvider>> hasBuiltinProvider,
          Predicate<StarlarkProviderIdentifier> hasStarlarkProvider,
          RequiredProviders requiredProviders,
          Builder missingProviders) {
        return true;
      }

      @Override
      Builder copyAsBuilder(RequiredProviders providers) {
        return acceptAnyBuilder();
      }

      @Override
      public String getDescription(RequiredProviders providers) {
        return "no providers required";
      }
    },
    /** Accept no dependency */
    NONE {
      @Override
      public boolean satisfies(
          AdvertisedProviderSet advertisedProviderSet,
          RequiredProviders requiredProviders,
          Builder missing) {
        return false;
      }

      @Override
      public boolean satisfies(
          Predicate<Class<? extends TransitiveInfoProvider>> hasBuiltinProvider,
          Predicate<StarlarkProviderIdentifier> hasStarlarkProvider,
          RequiredProviders requiredProviders,
          Builder missingProviders) {
        return false;
      }

      @Override
      Builder copyAsBuilder(RequiredProviders providers) {
        return acceptNoneBuilder();
      }

      @Override
      public String getDescription(RequiredProviders providers) {
        return "no providers accepted";
      }
    },

    /** Accept a dependency that has all providers from one of the sets. */
    RESTRICTED {
      @Override
      public boolean satisfies(
          final AdvertisedProviderSet advertisedProviderSet,
          RequiredProviders requiredProviders,
          Builder missing) {
        if (advertisedProviderSet.canHaveAnyProvider()) {
          return true;
        }
        return satisfies(
            advertisedProviderSet.getBuiltinProviders()::contains,
            advertisedProviderSet.getStarlarkProviders()::contains,
            requiredProviders,
            missing);
      }

      @Override
      boolean satisfies(
          Predicate<Class<? extends TransitiveInfoProvider>> hasBuiltinProvider,
          Predicate<StarlarkProviderIdentifier> hasStarlarkProvider,
          RequiredProviders requiredProviders,
          Builder missingProviders) {
        for (ImmutableSet<Class<? extends TransitiveInfoProvider>> builtinProviderSet :
            requiredProviders.builtinProviders) {
          if (builtinProviderSet.stream().allMatch(hasBuiltinProvider)) {
            return true;
          }

          // Collect missing providers
          if (missingProviders != null) {
            missingProviders.addBuiltinSet(
                builtinProviderSet.stream()
                    .filter(hasBuiltinProvider.negate())
                    .collect(ImmutableSet.toImmutableSet()));
          }
        }

        for (ImmutableSet<StarlarkProviderIdentifier> starlarkProviderSet :
            requiredProviders.starlarkProviders) {
          if (starlarkProviderSet.stream().allMatch(hasStarlarkProvider)) {
            return true;
          }
          // Collect missing providers
          if (missingProviders != null) {
            missingProviders.addStarlarkSet(
                starlarkProviderSet.stream()
                    .filter(hasStarlarkProvider.negate())
                    .collect(ImmutableSet.toImmutableSet()));
          }
        }
        return false;
      }

      @Override
      Builder copyAsBuilder(RequiredProviders providers) {
        Builder result = acceptAnyBuilder();
        for (ImmutableSet<Class<? extends TransitiveInfoProvider>> builtinProviderSet :
            providers.builtinProviders) {
          result.addBuiltinSet(builtinProviderSet);
        }
        for (ImmutableSet<StarlarkProviderIdentifier> starlarkProviderSet :
            providers.starlarkProviders) {
          result.addStarlarkSet(starlarkProviderSet);
        }
        return result;
      }

      @Override
      public String getDescription(RequiredProviders providers) {
        StringBuilder result = new StringBuilder();
        describe(result, providers.builtinProviders, Class::getSimpleName);
        describe(result, providers.starlarkProviders, id -> "'" + id.toString() + "'");
        return result.toString();
      }
    };

    /** Checks if {@code advertisedProviderSet} satisfies these {@code RequiredProviders} */
    protected abstract boolean satisfies(
        AdvertisedProviderSet advertisedProviderSet,
        RequiredProviders requiredProviders,
        Builder missing);

    /**
     * Checks if a set of providers encoded by predicates {@code hasBuiltinProvider} and {@code
     * hasStarlarkProvider} satisfies these {@code RequiredProviders}
     */
    abstract boolean satisfies(
        Predicate<Class<? extends TransitiveInfoProvider>> hasBuiltinProvider,
        Predicate<StarlarkProviderIdentifier> hasStarlarkProvider,
        RequiredProviders requiredProviders,
        @Nullable Builder missingProviders);

    abstract Builder copyAsBuilder(RequiredProviders providers);

    /** Returns a string describing the providers that can be presented to the user. */
    abstract String getDescription(RequiredProviders providers);
  }

  /** Checks if {@code advertisedProviderSet} satisfies this {@code RequiredProviders} instance. */
  public boolean isSatisfiedBy(AdvertisedProviderSet advertisedProviderSet) {
    return constraint.satisfies(advertisedProviderSet, this, null);
  }

  /**
   * Checks if a set of providers encoded by predicates {@code hasBuiltinProvider} and {@code
   * hasStarlarkProvider} satisfies this {@code RequiredProviders} instance.
   */
  public boolean isSatisfiedBy(
      Predicate<Class<? extends TransitiveInfoProvider>> hasBuiltinProvider,
      Predicate<StarlarkProviderIdentifier> hasStarlarkProvider) {
    return constraint.satisfies(hasBuiltinProvider, hasStarlarkProvider, this, null);
  }

  /**
   * Returns providers that are missing. If none are missing, returns {@code RequiredProviders} that
   * accept anything.
   */
  public RequiredProviders getMissing(
      Predicate<Class<? extends TransitiveInfoProvider>> hasBuiltinProvider,
      Predicate<StarlarkProviderIdentifier> hasStarlarkProvider) {
    Builder builder = acceptAnyBuilder();
    if (constraint.satisfies(hasBuiltinProvider, hasStarlarkProvider, this, builder)) {
      // Ignore all collected missing providers.
      return acceptAnyBuilder().build();
    }
    return builder.build();
  }

  /**
   * Returns providers that are missing. If none are missing, returns {@code RequiredProviders} that
   * accept anything.
   */
  public RequiredProviders getMissing(AdvertisedProviderSet set) {
    Builder builder = acceptAnyBuilder();
    if (constraint.satisfies(set, this, builder)) {
      // Ignore all collected missing providers.
      return acceptAnyBuilder().build();
    }
    return builder.build();
  }

  /** Returns true if this {@code RequiredProviders} instance accept any set of providers. */
  public boolean acceptsAny() {
    return constraint.equals(Constraint.ANY);
  }

  @VisibleForSerialization
  RequiredProviders(
      Constraint constraint,
      ImmutableList<ImmutableSet<Class<? extends TransitiveInfoProvider>>> builtinProviders,
      ImmutableList<ImmutableSet<StarlarkProviderIdentifier>> starlarkProviders) {
    this.constraint = constraint;

    Preconditions.checkState(
        constraint.equals(Constraint.RESTRICTED)
            || (builtinProviders.isEmpty() && starlarkProviders.isEmpty()));

    this.builtinProviders = builtinProviders;
    this.starlarkProviders = starlarkProviders;
  }

  /** Helper method to describe lists of sets of things. */
  private static <T> void describe(
      StringBuilder result,
      ImmutableList<ImmutableSet<T>> listOfSets,
      Function<T, String> describeOne) {
    Joiner joiner = Joiner.on(", ");
    for (ImmutableSet<T> ids : listOfSets) {
      if (result.length() > 0) {
        result.append(" or ");
      }
      result.append((ids.size() > 1) ? "[" : "");
      joiner.appendTo(result, ids.stream().map(describeOne).iterator());
      result.append((ids.size() > 1) ? "]" : "");
    }
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (o == null || getClass() != o.getClass()) {
      return false;
    }
    RequiredProviders that = (RequiredProviders) o;
    return constraint == that.constraint
        && Objects.equals(builtinProviders, that.builtinProviders)
        && Objects.equals(starlarkProviders, that.starlarkProviders);
  }

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

  /**
   * A builder for {@link RequiredProviders} that accepts any dependency
   * unless restriction provider sets are added.
   */
  public static Builder acceptAnyBuilder() {
    return new Builder(false);
  }

  /**
   * Mutates the given {@link AspectDefinition.Builder}, adding in the required providers specified
   * by this {@link RequiredProviders}.
   *
   * <p>We use this indirection for the sake of encapsulating the internal representation of {@link
   * RequiredProviders}.
   */
  void addToAspectDefinitionBuilder(AspectDefinition.Builder aspectDefinitionBuilder) {
    aspectDefinitionBuilder.requireProviderSets(builtinProviders);
    aspectDefinitionBuilder.requireStarlarkProviderSets(starlarkProviders);
  }

  /**
   * A builder for {@link RequiredProviders} that accepts no dependency
   * unless restriction provider sets are added.
   */
  public static Builder acceptNoneBuilder() {
    return new Builder(true);
  }

  /** Returns a Builder initialized to the same value as this {@code RequiredProvider} */
  public Builder copyAsBuilder() {
    return constraint.copyAsBuilder(this);
  }

  /** A builder for {@link RequiredProviders} */
  public static class Builder {
    private final ImmutableList.Builder<ImmutableSet<Class<? extends TransitiveInfoProvider>>>
        builtinProviders;
    private final ImmutableList.Builder<ImmutableSet<StarlarkProviderIdentifier>> starlarkProviders;
    private Constraint constraint;

    private Builder(boolean acceptNone) {
      constraint = acceptNone ? Constraint.NONE : Constraint.ANY;
      builtinProviders = ImmutableList.builder();
      starlarkProviders = ImmutableList.builder();
    }

    /**
     * Add an alternative set of Starlark providers.
     *
     * <p>If all of these providers are present in the dependency, the dependency satisfies {@link
     * RequiredProviders}.
     */
    @CanIgnoreReturnValue
    public Builder addStarlarkSet(ImmutableSet<StarlarkProviderIdentifier> starlarkProviderSet) {
      constraint = Constraint.RESTRICTED;
      Preconditions.checkState(!starlarkProviderSet.isEmpty());
      this.starlarkProviders.add(starlarkProviderSet);
      return this;
    }

    /**
     * Add an alternative set of builtin providers.
     *
     * <p>If all of these providers are present in the dependency, the dependency satisfies {@link
     * RequiredProviders}.
     */
    @CanIgnoreReturnValue
    public Builder addBuiltinSet(
        ImmutableSet<Class<? extends TransitiveInfoProvider>> builtinProviderSet) {
      constraint = Constraint.RESTRICTED;
      Preconditions.checkState(!builtinProviderSet.isEmpty());
      this.builtinProviders.add(builtinProviderSet);
      return this;
    }

    public RequiredProviders build() {
      return new RequiredProviders(constraint, builtinProviders.build(), starlarkProviders.build());
    }
  }
}
