// 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.common.Nullable;
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;

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

    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);
      }
    }

    public IdentifiedUser asUniqueUser() throws UnresolvableAccountException {
      ensureUnique();
      if (isSelf()) {
        // 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 self.get().asIdentifiedUser();
      }
      return userFactory.create(asUnique());
    }

    public IdentifiedUser asUniqueUserOnBehalfOf(CurrentUser caller)
        throws UnresolvableAccountException {
      ensureUnique();
      if (isSelf()) {
        // TODO(dborowitz): This preserves old behavior, but it seems wrong to discard the caller.
        return self.get().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;
    }

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

    Stream<AccountState> search(I input) throws IOException, ConfigInvalidException;

    boolean shortCircuitIfNoResults();

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

  @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 class BySelf extends StringSearcher {
    @Override
    public boolean callerShouldFilterOutInactiveCandidates() {
      return false;
    }

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

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

    @Override
    public Stream<AccountState> search(String input) {
      CurrentUser user = self.get();
      if (!user.isIdentifiedUser()) {
        return Stream.empty();
      }
      return Stream.of(user.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> {
    @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 {
    @Override
    public boolean callerMayAssumeCandidatesAreVisible() {
      return allowSkippingVisibilityCheck;
    }

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

    @Override
    public Stream<AccountState> search(String input) {
      // 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(self.get()).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 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;
  private @Nullable IdentifiedUser asUser;
  private boolean allowSkippingVisibilityCheck = true;

  @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;
  }

  /**
   * Set an account to resolve the users by. If not set, {@link CurrentUser} is used.
   *
   * <p>This affects visibility checks.
   *
   * @param asUser the user to resolve the other users with.
   * @return this
   */
  public AccountResolver resolveAsUser(IdentifiedUser asUser) {
    this.asUser = asUser;
    return this;
  }

  public AccountResolver forceVisibilityCheck(boolean forceVisibilityCheck) {
    allowSkippingVisibilityCheck = !forceVisibilityCheck;
    return this;
  }

  /**
   * 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, this::canSeePredicate, AccountResolver::isActive);
  }

  public Result resolve(String input, Predicate<AccountState> accountActivityPredicate)
      throws ConfigInvalidException, IOException {
    return searchImpl(input, searchers, this::canSeePredicate, 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, this::canSeePredicate, AccountResolver::allVisible);
  }

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

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

  public Result resolveIgnoreVisibility(
      String input, Predicate<AccountState> accountActivityPredicate)
      throws ConfigInvalidException, IOException {
    return searchImpl(input, searchers, this::allVisiblePredicate, accountActivityPredicate);
  }

  /**
   * 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, this::canSeePredicate, 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()),
        this::canSeePredicate,
        AccountResolver::isActive);
  }

  private Predicate<AccountState> canSeePredicate() {
    return this::canSee;
  }

  private boolean canSee(AccountState accountState) {
    if (asUser != null) {
      return accountControlFactory.get(asUser).canSee(accountState);
    }
    return accountControlFactory.get().canSee(accountState);
  }

  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,
      Supplier<Predicate<AccountState>> visibilitySupplier,
      Predicate<AccountState> accountActivityPredicate)
      throws ConfigInvalidException, IOException {
    visibilitySupplier = Suppliers.memoize(visibilitySupplier::get);
    List<AccountState> inactive = new ArrayList<>();

    for (Searcher<?> searcher : searchers) {
      Optional<Stream<AccountState>> maybeResults = searcher.trySearch(input);
      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);
      }
      if (searcher.shortCircuitIfNoResults()) {
        // For a short-circuiting searcher, return results even if empty.
        return !inactive.isEmpty() ? emptyResult(input, inactive) : createResult(input, list);
      }
    }
    return emptyResult(input, inactive);
  }

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

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

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