// Copyright (C) 2019 The Android Open Source Project
//
// 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.gerrit.server.account;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static java.util.Comparator.comparing;
import static java.util.Objects.requireNonNull;
import static java.util.stream.Collectors.joining;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Streams;
import com.google.gerrit.entities.Account;
import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
import com.google.gerrit.index.Schema;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.externalids.ExternalId;
import com.google.gerrit.server.config.AnonymousCowardName;
import com.google.gerrit.server.permissions.GlobalPermission;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.query.account.InternalAccountQuery;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.TreeSet;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;
import org.eclipse.jgit.errors.ConfigInvalidException;

/**
 * Helper for resolving accounts given arbitrary user-provided input.
 *
 * <p>The {@code resolve*} methods each define a list of accepted formats for account resolution.
 * The algorithm for resolving accounts from a list of formats is as follows:
 *
 * <ol>
 *   <li>For each recognized format in the order listed in the method Javadoc, check whether the
 *       input matches that format.
 *   <li>If so, resolve accounts according to that format.
 *   <li>Filter out invisible and inactive accounts.
 *   <li>If the result list is non-empty, return.
 *   <li>If the format is listed above as being short-circuiting, return.
 *   <li>Otherwise, return to step 1 with the next format.
 * </ol>
 *
 * <p>The result never includes accounts that are not visible to the calling user. It also never
 * includes inactive accounts, with a small number of specific exceptions noted in method Javadoc.
 */
@Singleton
public class AccountResolver {
  public static class UnresolvableAccountException extends UnprocessableEntityException {
    private static final long serialVersionUID = 1L;
    private final Result result;

    @VisibleForTesting
    UnresolvableAccountException(Result result) {
      super(exceptionMessage(result));
      this.result = result;
    }

    public boolean isSelf() {
      return result.isSelf();
    }
  }

  public static String exceptionMessage(Result result) {
    checkArgument(result.asList().size() != 1);
    if (result.asList().isEmpty()) {
      if (result.isSelf()) {
        return "Resolving account '" + result.input() + "' requires login";
      }
      if (result.filteredInactive().isEmpty()) {
        return "Account '" + result.input() + "' not found";
      }
      return result.filteredInactive().stream()
          .map(a -> formatForException(result, a))
          .collect(
              joining(
                  "\n",
                  "Account '"
                      + result.input()
                      + "' only matches inactive accounts. To use an inactive account, retry with"
                      + " one of the following exact account IDs:\n",
                  ""));
    }

    return result.asList().stream()
        .map(a -> formatForException(result, a))
        .limit(3)
        .collect(
            joining(
                "\n", "Account '" + result.input() + "' is ambiguous (at most 3 shown):\n", ""));
  }

  private static String formatForException(Result result, AccountState state) {
    return state.account().id()
        + ": "
        + state.account().getNameEmail(result.accountResolver().anonymousCowardName);
  }

  public static boolean isSelf(String input) {
    return "self".equals(input) || "me".equals(input);
  }

  public class Result {
    private final String input;
    private final ImmutableList<AccountState> list;
    private final ImmutableList<AccountState> filteredInactive;
    private final CurrentUser searchedAsUser;

    @VisibleForTesting
    Result(
        String input,
        List<AccountState> list,
        List<AccountState> filteredInactive,
        CurrentUser searchedAsUser) {
      this.input = requireNonNull(input);
      this.list = canonicalize(list);
      this.filteredInactive = canonicalize(filteredInactive);
      this.searchedAsUser = requireNonNull(searchedAsUser);
    }

    private ImmutableList<AccountState> canonicalize(List<AccountState> list) {
      TreeSet<AccountState> set = new TreeSet<>(comparing(a -> a.account().id().get()));
      set.addAll(requireNonNull(list));
      return ImmutableList.copyOf(set);
    }

    public String input() {
      return input;
    }

    public boolean isSelf() {
      return AccountResolver.isSelf(input);
    }

    public ImmutableList<AccountState> asList() {
      return list;
    }

    public ImmutableSet<Account.Id> asNonEmptyIdSet() throws UnresolvableAccountException {
      if (list.isEmpty()) {
        throw new UnresolvableAccountException(this);
      }
      return asIdSet();
    }

    public ImmutableSet<Account.Id> asIdSet() {
      return list.stream().map(a -> a.account().id()).collect(toImmutableSet());
    }

    public AccountState asUnique() throws UnresolvableAccountException {
      ensureUnique();
      return list.get(0);
    }

    private void ensureUnique() throws UnresolvableAccountException {
      if (list.size() != 1) {
        throw new UnresolvableAccountException(this);
      }
    }

    private void ensureSelfIsUniqueIdentifiedUser() throws UnresolvableAccountException {
      ensureUnique();
      if (!searchedAsUser.isIdentifiedUser()) {
        throw new UnresolvableAccountException(this);
      }
    }

    public IdentifiedUser asUniqueUser() throws UnresolvableAccountException {
      if (isSelf()) {
        ensureSelfIsUniqueIdentifiedUser();
        // In the special case of "self", use the exact IdentifiedUser from the request context, to
        // preserve the peer address and any other per-request state.
        return searchedAsUser.asIdentifiedUser();
      }
      ensureUnique();
      return userFactory.create(asUnique());
    }

    public IdentifiedUser asUniqueUserOnBehalfOf(CurrentUser caller)
        throws UnresolvableAccountException {
      ensureUnique();
      if (isSelf()) {
        return searchedAsUser.asIdentifiedUser();
      }
      return userFactory.runAs(
          null, list.get(0).account().id(), requireNonNull(caller).getRealUser());
    }

    @VisibleForTesting
    ImmutableList<AccountState> filteredInactive() {
      return filteredInactive;
    }

    private AccountResolver accountResolver() {
      return AccountResolver.this;
    }
  }

  @VisibleForTesting
  interface Searcher<I> {
    default boolean callerShouldFilterOutInactiveCandidates() {
      return true;
    }

    default boolean callerMayAssumeCandidatesAreVisible() {
      return false;
    }

    /**
     * Searches can be done on behalf of either the current user or another provided user. The
     * results of some searchers, such as BySelf, are affected by the context user.
     */
    default boolean requiresContextUser() {
      return false;
    }

    Optional<I> tryParse(String input) throws IOException;

    /**
     * This method should be implemented for every searcher which doesn't require a context user.
     *
     * @param input to search for
     * @return stream of the matching accounts
     * @throws IOException by some subclasses
     * @throws ConfigInvalidException by some subclasses
     */
    default Stream<AccountState> search(I input) throws IOException, ConfigInvalidException {
      throw new IllegalStateException("search(I) default implementation should never be called.");
    }

    /**
     * This method should be implemented for every searcher which requires a context user.
     *
     * @param input to search for
     * @param asUser the context user for the search
     * @return stream of the matching accounts
     * @throws IOException by some subclasses
     * @throws ConfigInvalidException by some subclasses
     */
    default Stream<AccountState> search(I input, CurrentUser asUser)
        throws IOException, ConfigInvalidException {
      if (!requiresContextUser()) {
        return search(input);
      }
      throw new IllegalStateException(
          "The searcher requires a context user, but doesn't implement search(input, asUser).");
    }

    boolean shortCircuitIfNoResults();

    default Optional<Stream<AccountState>> trySearch(String input, CurrentUser asUser)
        throws IOException, ConfigInvalidException {
      Optional<I> parsed = tryParse(input);
      if (parsed.isEmpty()) {
        return Optional.empty();
      }
      return requiresContextUser()
          ? Optional.of(search(parsed.get(), asUser))
          : Optional.of(search(parsed.get()));
    }
  }

  @VisibleForTesting
  abstract static class StringSearcher implements Searcher<String> {
    @Override
    public final Optional<String> tryParse(String input) {
      return matches(input) ? Optional.of(input) : Optional.empty();
    }

    protected abstract boolean matches(String input);
  }

  private abstract class AccountIdSearcher implements Searcher<Account.Id> {
    @Override
    public final Stream<AccountState> search(Account.Id input) {
      return Streams.stream(accountCache.get(input));
    }
  }

  private static class BySelf extends StringSearcher {
    @Override
    public boolean callerShouldFilterOutInactiveCandidates() {
      return false;
    }

    @Override
    public boolean callerMayAssumeCandidatesAreVisible() {
      return true;
    }

    @Override
    public boolean requiresContextUser() {
      return true;
    }

    @Override
    protected boolean matches(String input) {
      return "self".equals(input) || "me".equals(input);
    }

    @Override
    public Stream<AccountState> search(String input, CurrentUser asUser) {
      if (!asUser.isIdentifiedUser()) {
        return Stream.empty();
      }
      return Stream.of(asUser.asIdentifiedUser().state());
    }

    @Override
    public boolean shortCircuitIfNoResults() {
      return true;
    }
  }

  private class ByExactAccountId extends AccountIdSearcher {
    @Override
    public boolean callerShouldFilterOutInactiveCandidates() {
      return false;
    }

    @Override
    public Optional<Account.Id> tryParse(String input) {
      return Account.Id.tryParse(input);
    }

    @Override
    public boolean shortCircuitIfNoResults() {
      return true;
    }
  }

  private class ByParenthesizedAccountId extends AccountIdSearcher {
    private final Pattern pattern = Pattern.compile("^.* \\(([1-9][0-9]*)\\)$");

    @Override
    public Optional<Account.Id> tryParse(String input) {
      Matcher m = pattern.matcher(input);
      return m.matches() ? Account.Id.tryParse(m.group(1)) : Optional.empty();
    }

    @Override
    public boolean shortCircuitIfNoResults() {
      return true;
    }
  }

  private class ByUsername extends StringSearcher {
    @Override
    public boolean matches(String input) {
      return ExternalId.isValidUsername(input);
    }

    @Override
    public Stream<AccountState> search(String input) {
      return Streams.stream(accountCache.getByUsername(input));
    }

    @Override
    public boolean shortCircuitIfNoResults() {
      return false;
    }
  }

  private class ByNameAndEmail extends StringSearcher {
    @Override
    protected boolean matches(String input) {
      int lt = input.indexOf('<');
      int gt = input.indexOf('>');
      return lt >= 0 && gt > lt && input.contains("@");
    }

    @Override
    public Stream<AccountState> search(String nameOrEmail) throws IOException {
      // TODO(dborowitz): This would probably work as a Searcher<Address>
      int lt = nameOrEmail.indexOf('<');
      int gt = nameOrEmail.indexOf('>');
      Set<Account.Id> ids = emails.getAccountFor(nameOrEmail.substring(lt + 1, gt));
      ImmutableList<AccountState> allMatches = toAccountStates(ids).collect(toImmutableList());
      if (allMatches.isEmpty() || allMatches.size() == 1) {
        return allMatches.stream();
      }

      // More than one match. If there are any that match the full name as well, return only that
      // subset. Otherwise, all are equally non-matching, so return the full set.
      if (lt == 0) {
        // No name was specified in the input string.
        return allMatches.stream();
      }
      String name = nameOrEmail.substring(0, lt - 1);
      ImmutableList<AccountState> nameMatches =
          allMatches.stream()
              .filter(a -> name.equals(a.account().fullName()))
              .collect(toImmutableList());
      return !nameMatches.isEmpty() ? nameMatches.stream() : allMatches.stream();
    }

    @Override
    public boolean shortCircuitIfNoResults() {
      return true;
    }
  }

  private class ByEmail extends StringSearcher {
    @Override
    protected boolean matches(String input) {
      return input.contains("@");
    }

    @Override
    public Stream<AccountState> search(String input) throws IOException {
      return toAccountStates(emails.getAccountFor(input));
    }

    @Override
    public boolean shortCircuitIfNoResults() {
      return true;
    }
  }

  private class FromRealm extends AccountIdSearcher {
    @Override
    public Optional<Account.Id> tryParse(String input) throws IOException {
      return Optional.ofNullable(realm.lookup(input));
    }

    @Override
    public boolean shortCircuitIfNoResults() {
      return false;
    }
  }

  private class ByFullName implements Searcher<AccountState> {
    boolean allowSkippingVisibilityCheck = true;

    ByFullName() {
      super();
    }

    ByFullName(boolean allowSkippingVisibilityCheck) {
      this();
      this.allowSkippingVisibilityCheck = allowSkippingVisibilityCheck;
    }

    @Override
    public boolean callerMayAssumeCandidatesAreVisible() {
      return allowSkippingVisibilityCheck;
    }

    @Override
    public Optional<AccountState> tryParse(String input) {
      List<AccountState> results =
          accountQueryProvider.get().enforceVisibility(true).byFullName(input);
      return results.size() == 1 ? Optional.of(results.get(0)) : Optional.empty();
    }

    @Override
    public Stream<AccountState> search(AccountState input) {
      return Stream.of(input);
    }

    @Override
    public boolean shortCircuitIfNoResults() {
      return false;
    }
  }

  private class ByDefaultSearch extends StringSearcher {
    boolean allowSkippingVisibilityCheck = true;

    ByDefaultSearch() {
      super();
    }

    ByDefaultSearch(boolean allowSkippingVisibilityCheck) {
      this();
      this.allowSkippingVisibilityCheck = allowSkippingVisibilityCheck;
    }

    @Override
    public boolean callerMayAssumeCandidatesAreVisible() {
      return allowSkippingVisibilityCheck;
    }

    @Override
    public boolean requiresContextUser() {
      return true;
    }

    @Override
    protected boolean matches(String input) {
      return true;
    }

    @Override
    public Stream<AccountState> search(String input, CurrentUser asUser) {
      // At this point we have no clue. Just perform a whole bunch of suggestions and pray we come
      // up with a reasonable result list.
      // TODO(dborowitz): This doesn't match the documentation; consider whether it's possible to be
      // more strict here.
      boolean canSeeSecondaryEmails = false;
      try {
        if (permissionBackend.user(asUser).test(GlobalPermission.MODIFY_ACCOUNT)) {
          canSeeSecondaryEmails = true;
        }
      } catch (PermissionBackendException e) {
        // remains false
      }
      return accountQueryProvider.get().enforceVisibility(true)
          .byDefault(input, canSeeSecondaryEmails).stream();
    }

    @Override
    public boolean shortCircuitIfNoResults() {
      // In practice this doesn't matter since this is the last searcher in the list, but considered
      // on its own, it doesn't necessarily need to be terminal.
      return false;
    }
  }

  private final ImmutableList<Searcher<?>> nameOrEmailSearchers =
      ImmutableList.of(
          new ByNameAndEmail(),
          new ByEmail(),
          new FromRealm(),
          new ByFullName(),
          new ByDefaultSearch());

  private final ImmutableList<Searcher<?>> searchers =
      ImmutableList.<Searcher<?>>builder()
          .add(new BySelf())
          .add(new ByExactAccountId())
          .add(new ByParenthesizedAccountId())
          .add(new ByUsername())
          .addAll(nameOrEmailSearchers)
          .build();

  private final ImmutableList<Searcher<?>> forcedVisibilitySearchers =
      ImmutableList.of(
          new ByNameAndEmail(),
          new ByEmail(),
          new FromRealm(),
          new ByFullName(false),
          new ByDefaultSearch(false),
          new BySelf(),
          new ByExactAccountId(),
          new ByParenthesizedAccountId(),
          new ByUsername());

  private final AccountCache accountCache;
  private final AccountControl.Factory accountControlFactory;
  private final Emails emails;
  private final IdentifiedUser.GenericFactory userFactory;
  private final Provider<CurrentUser> self;
  private final Provider<InternalAccountQuery> accountQueryProvider;
  private final Realm realm;
  private final String anonymousCowardName;
  private final PermissionBackend permissionBackend;

  @Inject
  AccountResolver(
      AccountCache accountCache,
      Emails emails,
      AccountControl.Factory accountControlFactory,
      IdentifiedUser.GenericFactory userFactory,
      Provider<CurrentUser> self,
      Provider<InternalAccountQuery> accountQueryProvider,
      PermissionBackend permissionBackend,
      Realm realm,
      @AnonymousCowardName String anonymousCowardName) {
    this.accountCache = accountCache;
    this.emails = emails;
    this.accountControlFactory = accountControlFactory;
    this.userFactory = userFactory;
    this.self = self;
    this.accountQueryProvider = accountQueryProvider;
    this.permissionBackend = permissionBackend;
    this.realm = realm;
    this.anonymousCowardName = anonymousCowardName;
  }

  /**
   * Resolves all accounts matching the input string, visible to the current user.
   *
   * <p>The following input formats are recognized:
   *
   * <ul>
   *   <li>The strings {@code "self"} and {@code "me"}, if the current user is an {@link
   *       IdentifiedUser}. In this case, may return exactly one inactive account.
   *   <li>A bare account ID ({@code "18419"}). In this case, may return exactly one inactive
   *       account. This case short-circuits if the input matches.
   *   <li>An account ID in parentheses following a full name ({@code "Full Name (18419)"}). This
   *       case short-circuits if the input matches.
   *   <li>A username ({@code "username"}).
   *   <li>A full name and email address ({@code "Full Name <email@example>"}). This case
   *       short-circuits if the input matches.
   *   <li>An email address ({@code "email@example"}. This case short-circuits if the input matches.
   *   <li>An account name recognized by the configured {@link Realm#lookup(String)} Realm}.
   *   <li>A full name ({@code "Full Name"}).
   *   <li>As a fallback, a {@link
   *       com.google.gerrit.server.query.account.AccountPredicates#defaultPredicate(Schema,
   *       boolean, String) default search} against the account index.
   * </ul>
   *
   * @param input input string.
   * @return a result describing matching accounts. Never null even if the result set is empty.
   * @throws ConfigInvalidException if an error occurs.
   * @throws IOException if an error occurs.
   */
  public Result resolve(String input) throws ConfigInvalidException, IOException {
    return searchImpl(
        input, searchers, self.get(), this::currentUserCanSeePredicate, AccountResolver::isActive);
  }

  public Result resolve(String input, Predicate<AccountState> accountActivityPredicate)
      throws ConfigInvalidException, IOException {
    return searchImpl(
        input, searchers, self.get(), this::currentUserCanSeePredicate, accountActivityPredicate);
  }

  /**
   * Resolves all accounts matching the input string, visible to the provided user.
   *
   * <p>The following input formats are recognized:
   *
   * <ul>
   *   <li>The strings {@code "self"} and {@code "me"}, if the provided user is an {@link
   *       IdentifiedUser}. In this case, may return exactly one inactive account.
   *   <li>A bare account ID ({@code "18419"}). In this case, may return exactly one inactive
   *       account. This case short-circuits if the input matches.
   *   <li>An account ID in parentheses following a full name ({@code "Full Name (18419)"}). This
   *       case short-circuits if the input matches.
   *   <li>A username ({@code "username"}).
   *   <li>A full name and email address ({@code "Full Name <email@example>"}). This case
   *       short-circuits if the input matches.
   *   <li>An email address ({@code "email@example"}. This case short-circuits if the input matches.
   *   <li>An account name recognized by the configured {@link Realm#lookup(String)} Realm}.
   *   <li>A full name ({@code "Full Name"}).
   *   <li>As a fallback, a {@link
   *       com.google.gerrit.server.query.account.AccountPredicates#defaultPredicate(Schema,
   *       boolean, String) default search} against the account index.
   * </ul>
   *
   * @param asUser user to resolve the users by.
   * @param input input string.
   * @param forceVisibilityCheck whether to force all searchers to check for visibility.
   * @return a result describing matching accounts. Never null even if the result set is empty.
   * @throws ConfigInvalidException if an error occurs.
   * @throws IOException if an error occurs.
   */
  public Result resolveAsUser(CurrentUser asUser, String input, boolean forceVisibilityCheck)
      throws ConfigInvalidException, IOException {
    return resolveAsUser(asUser, input, AccountResolver::isActive, forceVisibilityCheck);
  }

  public Result resolveAsUser(
      CurrentUser asUser,
      String input,
      Predicate<AccountState> accountActivityPredicate,
      boolean forceVisibilityCheck)
      throws ConfigInvalidException, IOException {
    return searchImpl(
        input,
        forceVisibilityCheck ? forcedVisibilitySearchers : searchers,
        asUser,
        new ProvidedUserCanSeePredicate(asUser),
        accountActivityPredicate);
  }

  /**
   * As opposed to {@link #resolve}, the returned result includes all inactive accounts for the
   * input search.
   *
   * <p>This can be used to resolve Gerrit Account from email to its {@link
   * com.google.gerrit.entities.Account.Id}, to make sure that if {@link Account} with such email
   * exists in Gerrit (even inactive), user data (email address) won't be recorded as it is, but
   * instead will be stored as a link to the corresponding Gerrit Account.
   */
  public Result resolveIncludeInactive(String input) throws ConfigInvalidException, IOException {
    return searchImpl(
        input,
        searchers,
        self.get(),
        this::currentUserCanSeePredicate,
        AccountResolver::allVisible);
  }

  public Result resolveIncludeInactiveIgnoreVisibility(String input)
      throws ConfigInvalidException, IOException {
    return searchImpl(
        input, searchers, self.get(), this::allVisiblePredicate, AccountResolver::allVisible);
  }

  public Result resolveIgnoreVisibility(String input) throws ConfigInvalidException, IOException {
    return searchImpl(
        input, searchers, self.get(), this::allVisiblePredicate, AccountResolver::isActive);
  }

  /**
   * Resolves all accounts matching the input string by name or email.
   *
   * <p>The following input formats are recognized:
   *
   * <ul>
   *   <li>A full name and email address ({@code "Full Name <email@example>"}). This case
   *       short-circuits if the input matches.
   *   <li>An email address ({@code "email@example"}. This case short-circuits if the input matches.
   *   <li>An account name recognized by the configured {@link Realm#lookup(String)} Realm}.
   *   <li>A full name ({@code "Full Name"}).
   *   <li>As a fallback, a {@link
   *       com.google.gerrit.server.query.account.AccountPredicates#defaultPredicate(Schema,
   *       boolean, String) default search} against the account index.
   * </ul>
   *
   * @param input input string.
   * @return a result describing matching accounts. Never null even if the result set is empty.
   * @throws ConfigInvalidException if an error occurs.
   * @throws IOException if an error occurs.
   * @deprecated for use only by MailUtil for parsing commit footers; that class needs to be
   *     reevaluated.
   */
  @Deprecated
  public Result resolveByNameOrEmail(String input) throws ConfigInvalidException, IOException {
    return searchImpl(
        input,
        nameOrEmailSearchers,
        self.get(),
        this::currentUserCanSeePredicate,
        AccountResolver::isActive);
  }

  /**
   * Same as {@link #resolveByNameOrEmail(String)}, but with exact matching for the full name, email
   * and full name.
   *
   * @param input input string.
   * @return a result describing matching accounts. Never null even if the result set is empty.
   * @throws ConfigInvalidException if an error occurs.
   * @throws IOException if an error occurs.
   * @deprecated for use only by MailUtil for parsing commit footers; that class needs to be
   *     reevaluated.
   */
  @Deprecated
  public Result resolveByExactNameOrEmail(String input) throws ConfigInvalidException, IOException {
    return searchImpl(
        input,
        ImmutableList.of(new ByNameAndEmail(), new ByEmail(), new ByFullName(), new ByUsername()),
        self.get(),
        this::currentUserCanSeePredicate,
        AccountResolver::isActive);
  }

  private Predicate<AccountState> currentUserCanSeePredicate() {
    return accountControlFactory.get()::canSee;
  }

  private class ProvidedUserCanSeePredicate implements Supplier<Predicate<AccountState>> {
    CurrentUser asUser;

    ProvidedUserCanSeePredicate(CurrentUser asUser) {
      this.asUser = asUser;
    }

    @Override
    public Predicate<AccountState> get() {
      return accountControlFactory.get(asUser.asIdentifiedUser())::canSee;
    }
  }

  private Predicate<AccountState> allVisiblePredicate() {
    return AccountResolver::allVisible;
  }

  /** @param accountState account state for which the visibility should be checked */
  private static boolean allVisible(AccountState accountState) {
    return true;
  }

  private static boolean isActive(AccountState accountState) {
    return accountState.account().isActive();
  }

  @VisibleForTesting
  Result searchImpl(
      String input,
      ImmutableList<Searcher<?>> searchers,
      CurrentUser asUser,
      Supplier<Predicate<AccountState>> visibilitySupplier,
      Predicate<AccountState> accountActivityPredicate)
      throws ConfigInvalidException, IOException {
    requireNonNull(asUser);
    visibilitySupplier = Suppliers.memoize(visibilitySupplier::get);
    List<AccountState> inactive = new ArrayList<>();

    for (Searcher<?> searcher : searchers) {
      Optional<Stream<AccountState>> maybeResults = searcher.trySearch(input, asUser);
      if (!maybeResults.isPresent()) {
        continue;
      }
      Stream<AccountState> results = maybeResults.get();

      if (!searcher.callerMayAssumeCandidatesAreVisible()) {
        results = results.filter(visibilitySupplier.get());
      }

      List<AccountState> list;
      if (searcher.callerShouldFilterOutInactiveCandidates()) {
        // Keep track of all inactive candidates discovered by any searchers. If we end up short-
        // circuiting, the inactive list will be discarded.
        List<AccountState> active = new ArrayList<>();
        results.forEach(a -> (accountActivityPredicate.test(a) ? active : inactive).add(a));
        list = active;
      } else {
        list = results.collect(toImmutableList());
      }

      if (!list.isEmpty()) {
        return createResult(input, list, asUser);
      }
      if (searcher.shortCircuitIfNoResults()) {
        // For a short-circuiting searcher, return results even if empty.
        return !inactive.isEmpty()
            ? emptyResult(input, inactive, asUser)
            : createResult(input, list, asUser);
      }
    }
    return emptyResult(input, inactive, asUser);
  }

  private Result createResult(String input, List<AccountState> list, CurrentUser searchedAsUser) {
    return new Result(input, list, ImmutableList.of(), searchedAsUser);
  }

  private Result emptyResult(
      String input, List<AccountState> inactive, CurrentUser searchedAsUser) {
    return new Result(input, ImmutableList.of(), inactive, searchedAsUser);
  }

  private Stream<AccountState> toAccountStates(Set<Account.Id> ids) {
    return accountCache.get(ids).values().stream();
  }
}
