// 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.concurrent.ThreadSafety.Immutable;
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).
 *
 * Currently we support three kinds of constraints:
 * <ul>
 *   <li>accept any dependency.</li>
 *   <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>
 *   <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
 *       native providers or all Skylark providers, so this is the only use case this
 *       class currently supports.
 *   </li>
 * </ul>
 */
@Immutable
public final class RequiredProviders {
  /** A constraint: either ANY, NONE, or RESTRICTED */
  private final Constraint constraint;
  /**
   * Sets of native providers.
   * If non-empty, {@link #constraint} is {@link Constraint#RESTRICTED}
   */
  private final ImmutableList<ImmutableSet<Class<?>>> nativeProviders;
  /**
   * Sets of native providers.
   * If non-empty, {@link #constraint} is {@link Constraint#RESTRICTED}
   */
  private final ImmutableList<ImmutableSet<SkylarkProviderIdentifier>> skylarkProviders;

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

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

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

      @Override
      public boolean satisfies(
          Predicate<Class<?>> hasNativeProvider,
          Predicate<SkylarkProviderIdentifier> hasSkylarkProvider,
          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<?>> hasNativeProvider,
          Predicate<SkylarkProviderIdentifier> hasSkylarkProvider,
          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.getNativeProviders()::contains,
            advertisedProviderSet.getSkylarkProviders()::contains,
            requiredProviders,
            missing);
      }

      @Override
      public boolean satisfies(
          Predicate<Class<?>> hasNativeProvider,
          Predicate<SkylarkProviderIdentifier> hasSkylarkProvider,
          RequiredProviders requiredProviders,
          Builder missingProviders) {
        for (ImmutableSet<Class<?>> nativeProviderSet : requiredProviders.nativeProviders) {
          if (nativeProviderSet.stream().allMatch(hasNativeProvider)) {
            return true;
          }

          // Collect missing providers
          if (missingProviders != null) {
            missingProviders.addNativeSet(
                nativeProviderSet
                    .stream()
                    .filter(hasNativeProvider.negate())
                    .collect(ImmutableSet.toImmutableSet()));
          }
        }

        for (ImmutableSet<SkylarkProviderIdentifier> skylarkProviderSet
            : requiredProviders.skylarkProviders) {
          if (skylarkProviderSet.stream().allMatch(hasSkylarkProvider)) {
            return true;
          }
          // Collect missing providers
          if (missingProviders != null) {
            missingProviders.addSkylarkSet(
                skylarkProviderSet
                    .stream()
                    .filter(hasSkylarkProvider.negate())
                    .collect(ImmutableSet.toImmutableSet()));
          }
        }
        return false;
      }

      @Override
      Builder copyAsBuilder(RequiredProviders providers) {
        Builder result = acceptAnyBuilder();
        for (ImmutableSet<Class<?>> nativeProviderSet : providers.nativeProviders) {
          result.addNativeSet(nativeProviderSet);
        }
        for (ImmutableSet<SkylarkProviderIdentifier> skylarkProviderSet :
            providers.skylarkProviders) {
          result.addSkylarkSet(skylarkProviderSet);
        }
        return result;
      }

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

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

    /**
     * Checks if a set of providers encoded by predicates {@code hasNativeProviders} and {@code
     * hasSkylarkProvider} satisfies these {@code RequiredProviders}
     */
    abstract boolean satisfies(
        Predicate<Class<?>> hasNativeProvider,
        Predicate<SkylarkProviderIdentifier> hasSkylarkProvider,
        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 hasNativeProviders}
   * and {@code hasSkylarkProvider} satisfies this {@code RequiredProviders} instance.
   */
  public boolean isSatisfiedBy(
      Predicate<Class<?>> hasNativeProvider,
      Predicate<SkylarkProviderIdentifier> hasSkylarkProvider) {
    return constraint.satisfies(hasNativeProvider, hasSkylarkProvider, this, null);
  }

  /**
   * Returns providers that are missing. If none are missing, returns {@code RequiredProviders} that
   * accept anything.
   */
  public RequiredProviders getMissing(
      Predicate<Class<?>> hasNativeProvider,
      Predicate<SkylarkProviderIdentifier> hasSkylarkProvider) {
    Builder builder = acceptAnyBuilder();
    if (constraint.satisfies(hasNativeProvider, hasSkylarkProvider, 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);
  }


  private RequiredProviders(
      Constraint constraint,
      ImmutableList<ImmutableSet<Class<?>>> nativeProviders,
      ImmutableList<ImmutableSet<SkylarkProviderIdentifier>> skylarkProviders) {
    this.constraint = constraint;

    Preconditions.checkState(constraint.equals(Constraint.RESTRICTED)
        || (nativeProviders.isEmpty() && skylarkProviders.isEmpty())
    );

    this.nativeProviders = nativeProviders;
    this.skylarkProviders = skylarkProviders;
  }

  /** 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) ? "]" : "");
    }
  }

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

  /**
   * 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<?>>> nativeProviders;
    private final ImmutableList.Builder<ImmutableSet<SkylarkProviderIdentifier>> skylarkProviders;
    private Constraint constraint;

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

    /**
     * Add an alternative set of Skylark providers.
     *
     * If all of these providers are present in the dependency, the dependency satisfies
     * {@link RequiredProviders}.
     */
    public Builder addSkylarkSet(ImmutableSet<SkylarkProviderIdentifier> skylarkProviderSet) {
      constraint = Constraint.RESTRICTED;
      Preconditions.checkState(!skylarkProviderSet.isEmpty());
      this.skylarkProviders.add(skylarkProviderSet);
      return this;
    }

    /**
     * Add an alternative set of native providers.
     *
     * If all of these providers are present in the dependency, the dependency satisfies
     * {@link RequiredProviders}.
     */
    public Builder addNativeSet(ImmutableSet<Class<?>> nativeProviderSet) {
      constraint = Constraint.RESTRICTED;
      Preconditions.checkState(!nativeProviderSet.isEmpty());
      this.nativeProviders.add(nativeProviderSet);
      return this;
    }

    public RequiredProviders build() {
      return new RequiredProviders(constraint, nativeProviders.build(), skylarkProviders.build());
    }
  }
}
