// Copyright (C) 2020 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.plugins.codeowners.backend;

import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.ImmutableMap.toImmutableMap;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static com.google.gerrit.plugins.codeowners.backend.CodeOwnersInternalServerErrorException.newInternalServerError;
import static java.util.Objects.requireNonNull;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Streams;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.Project;
import com.google.gerrit.metrics.Timer0;
import com.google.gerrit.plugins.codeowners.backend.config.CodeOwnersPluginConfiguration;
import com.google.gerrit.plugins.codeowners.metrics.CodeOwnerMetrics;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.AccountCache;
import com.google.gerrit.server.account.AccountControl;
import com.google.gerrit.server.account.AccountState;
import com.google.gerrit.server.account.externalids.ExternalId;
import com.google.gerrit.server.account.externalids.ExternalIds;
import com.google.gerrit.server.permissions.GlobalPermission;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Stream;

/**
 * Class to resolve {@link CodeOwnerReference}s to {@link CodeOwner}s.
 *
 * <p>Code owners are defined by {@link CodeOwnerReference}s (e.g. emails) that need to be resolved
 * to accounts. The accounts are wrapped in {@link CodeOwner}s so that we can support different kind
 * of code owners later (e.g. groups).
 *
 * <p>Code owners that cannot be resolved are filtered out:
 *
 * <ul>
 *   <li>Emails that have a non-allowed email domain (see config parameter {@code
 *       plugin.code-owners.allowedEmailDomain}).
 *   <li>Emails for which no account exists: If no account exists, we cannot return any account.
 *       It's fine to filter them out as it just means nobody can claim the ownership that was
 *       assigned for this email.
 *   <li>Emails for which multiple accounts exist: If an email is ambiguous it is treated the same
 *       way as if there was no account for the email. That's because we can't tell which account
 *       was meant to have the ownership. This behaviour is consistent with the behaviour in Gerrit
 *       core that also treats ambiguous identifiers as non-resolveable.
 * </ul>
 *
 * <p>Unless {@link CodeOwnerResolver#enforceVisibility} is {@code false} it is checked whether the
 * {@link #user} or the calling user (if {@link #user} is unset) can see the accounts of the code
 * owners and code owners whose accounts are not visible are filtered out.
 *
 * <p>In addition code owners that are referenced by a secondary email are filtered out if the
 * {@link #user} or the calling user (if {@link #user} is unset) cannot see the secondary email:
 *
 * <ul>
 *   <li>every user can see their own secondary emails
 *   <li>users with the {@code Modify Account} global capability can see the secondary emails of all
 *       accounts
 * </ul>
 *
 * <p>Resolved code owners are cached within this class so that each email needs to be resolved only
 * once. To take advantage of this caching callers should reuse {@link CodeOwnerResolver} instances
 * where possible.
 */
public class CodeOwnerResolver {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  @VisibleForTesting public static final String ALL_USERS_WILDCARD = "*";

  private final CodeOwnersPluginConfiguration codeOwnersPluginConfiguration;
  private final PermissionBackend permissionBackend;
  private final Provider<CurrentUser> currentUser;
  private final ExternalIds externalIds;
  private final AccountCache accountCache;
  private final AccountControl.Factory accountControlFactory;
  private final PathCodeOwners.Factory pathCodeOwnersFactory;
  private final CodeOwnerMetrics codeOwnerMetrics;
  private final UnresolvedImportFormatter unresolvedImportFormatter;
  private final TransientCodeOwnerCache transientCodeOwnerCache;

  // Enforce visibility by default.
  private boolean enforceVisibility = true;

  // The the user that should be used to check the account visibility (whether this user can see the
  // accounts of the code owners).
  // If unset, the current user is used.
  private IdentifiedUser user;

  @Inject
  CodeOwnerResolver(
      CodeOwnersPluginConfiguration codeOwnersPluginConfiguration,
      PermissionBackend permissionBackend,
      Provider<CurrentUser> currentUser,
      ExternalIds externalIds,
      AccountCache accountCache,
      AccountControl.Factory accountControlFactory,
      PathCodeOwners.Factory pathCodeOwnersFactory,
      CodeOwnerMetrics codeOwnerMetrics,
      UnresolvedImportFormatter unresolvedImportFormatter,
      TransientCodeOwnerCache transientCodeOwnerCache) {
    this.codeOwnersPluginConfiguration = codeOwnersPluginConfiguration;
    this.permissionBackend = permissionBackend;
    this.currentUser = currentUser;
    this.externalIds = externalIds;
    this.accountCache = accountCache;
    this.accountControlFactory = accountControlFactory;
    this.pathCodeOwnersFactory = pathCodeOwnersFactory;
    this.codeOwnerMetrics = codeOwnerMetrics;
    this.unresolvedImportFormatter = unresolvedImportFormatter;
    this.transientCodeOwnerCache = transientCodeOwnerCache;
  }

  /**
   * Whether it should be enforced that the returned code owners are visible to the current user.
   *
   * @param enforceVisibility whether it should be enforced that the returned code owners are
   *     visible to the current user
   * @return the {@link CodeOwnerResolver} instance for chaining calls
   */
  public CodeOwnerResolver enforceVisibility(boolean enforceVisibility) {
    logger.atFine().log("enforceVisibility = %s", enforceVisibility);
    this.enforceVisibility = enforceVisibility;
    transientCodeOwnerCache.clear();
    return this;
  }

  /**
   * Sets the user that should be used to check the account visibility (whether this user can see
   * the accounts of the code owners).
   *
   * <p>This overrides the current user that would be used to check the account visibility if this
   * method was not called.
   *
   * <p>Using this method it's possible to resolve code owner references for accounts that are
   * visible to the given user, but not visible to the current user. Callers must use this method
   * with care to not expose the existence of non-visible accounts to the current user.
   *
   * @param user the user that should be used to check the account visibility (whether this user can
   *     see the accounts of the code owners)
   * @return the {@link CodeOwnerResolver} instance for chaining calls
   */
  public CodeOwnerResolver forUser(IdentifiedUser user) {
    logger.atFine().log("user = %s", user.getLoggableName());
    this.user = user;
    transientCodeOwnerCache.clear();
    return this;
  }

  /** Whether the given code owner reference can be resolved. */
  public boolean isResolvable(CodeOwnerReference codeOwnerReference) {
    CodeOwnerResolverResult result = resolve(ImmutableSet.of(codeOwnerReference));
    return !result.codeOwners().isEmpty() || result.ownedByAllUsers();
  }

  /**
   * Resolves the code owners from the given code owner config for the given path from {@link
   * CodeOwnerReference}s to a {@link CodeOwner}s.
   *
   * <p>If the code owner config has already been resolved to {@link PathCodeOwners}, prefer calling
   * {@link #resolvePathCodeOwners(PathCodeOwners)} instead, so that {@link PathCodeOwners} do not
   * need to be created again.
   *
   * <p>Non-resolvable code owners are filtered out.
   *
   * @param codeOwnerConfig the code owner config for which the local owners for the given path
   *     should be resolved
   * @param absolutePath path for which the code owners should be returned; the path must be
   *     absolute; can be the path of a file or folder; the path may or may not exist
   * @return the resolved code owners
   */
  public CodeOwnerResolverResult resolvePathCodeOwners(
      CodeOwnerConfig codeOwnerConfig, Path absolutePath) {
    requireNonNull(codeOwnerConfig, "codeOwnerConfig");
    requireNonNull(absolutePath, "absolutePath");
    checkState(absolutePath.isAbsolute(), "path %s must be absolute", absolutePath);
    return resolvePathCodeOwners(
        pathCodeOwnersFactory.createWithoutCache(codeOwnerConfig, absolutePath));
  }

  /**
   * Resolves the the given path code owners from {@link CodeOwnerReference}s to a {@link
   * CodeOwner}s.
   *
   * <p>Non-resolvable code owners are filtered out.
   *
   * @param pathCodeOwners the path code owners that should be resolved
   * @return the resolved code owners
   */
  public CodeOwnerResolverResult resolvePathCodeOwners(PathCodeOwners pathCodeOwners) {
    requireNonNull(pathCodeOwners, "pathCodeOwners");

    try (Timer0.Context ctx = codeOwnerMetrics.resolvePathCodeOwners.start()) {
      logger.atFine().log(
          "resolve path code owners (code owner config = %s, path = %s)",
          pathCodeOwners.getCodeOwnerConfig().key(), pathCodeOwners.getPath());
      OptionalResultWithMessages<PathCodeOwnersResult> pathCodeOwnersResult =
          pathCodeOwners.resolveCodeOwnerConfig();
      return resolve(
          pathCodeOwnersResult.get().getPathCodeOwners(),
          pathCodeOwnersResult.get().getAnnotations(),
          pathCodeOwnersResult.get().unresolvedImports(),
          pathCodeOwnersResult.messages());
    }
  }

  /**
   * Resolves the global code owners for the given project.
   *
   * @param projectName the name of the project for which the global code owners should be resolved
   * @return the resolved global code owners of the given project
   */
  public CodeOwnerResolverResult resolveGlobalCodeOwners(Project.NameKey projectName) {
    return resolve(
        codeOwnersPluginConfiguration.getProjectConfig(projectName).getGlobalCodeOwners());
  }

  /**
   * Resolves the given {@link CodeOwnerReference}s to {@link CodeOwner}s.
   *
   * @param codeOwnerReferences the code owner references that should be resolved
   * @return the {@link CodeOwner} for the given code owner references
   */
  public CodeOwnerResolverResult resolve(Set<CodeOwnerReference> codeOwnerReferences) {
    return resolve(
        codeOwnerReferences,
        /* annotationsByCodeOwnerReference= */ ImmutableMultimap.of(),
        /* unresolvedImports= */ ImmutableList.of(),
        /* pathCodeOwnersMessages= */ ImmutableList.of());
  }

  /**
   * Resolves the given {@link CodeOwnerReference}s to {@link CodeOwner}s.
   *
   * <p>The accounts for the given {@link CodeOwnerReference}s are loaded from the account cache in
   * parallel (via {@link AccountCache#get(Set)}.
   *
   * @param codeOwnerReferences the code owner references that should be resolved
   * @param annotationsByCodeOwnerReference annotations by code owner reference
   * @param unresolvedImports list of unresolved imports
   * @param pathCodeOwnersMessages messages that were collected when resolving path code owners
   * @return the resolved code owner references as a {@link CodeOwnerResolverResult}
   */
  private CodeOwnerResolverResult resolve(
      Set<CodeOwnerReference> codeOwnerReferences,
      ImmutableMultimap<CodeOwnerReference, CodeOwnerAnnotation> annotationsByCodeOwnerReference,
      List<UnresolvedImport> unresolvedImports,
      ImmutableList<String> pathCodeOwnersMessages) {
    requireNonNull(codeOwnerReferences, "codeOwnerReferences");
    requireNonNull(unresolvedImports, "unresolvedImports");
    requireNonNull(pathCodeOwnersMessages, "pathCodeOwnersMessages");

    try (Timer0.Context ctx = codeOwnerMetrics.resolveCodeOwnerReferences.start()) {
      ImmutableList.Builder<String> messageBuilder = ImmutableList.builder();
      messageBuilder.addAll(pathCodeOwnersMessages);
      unresolvedImports.forEach(
          unresolvedImport ->
              messageBuilder.add(unresolvedImportFormatter.format(unresolvedImport)));

      AtomicBoolean ownedByAllUsers = new AtomicBoolean(false);
      AtomicBoolean hasUnresolvedCodeOwners = new AtomicBoolean(false);
      ImmutableMap<CodeOwner, ImmutableSet<CodeOwnerAnnotation>> codeOwnersWithAnnotations =
          resolve(
              messageBuilder,
              ownedByAllUsers,
              hasUnresolvedCodeOwners,
              codeOwnerReferences,
              annotationsByCodeOwnerReference);

      ImmutableMultimap.Builder<CodeOwner, CodeOwnerAnnotation> annotationsByCodeOwner =
          ImmutableMultimap.builder();
      codeOwnersWithAnnotations.forEach(
          (codeOwner, annotations) -> annotationsByCodeOwner.putAll(codeOwner, annotations));

      CodeOwnerResolverResult codeOwnerResolverResult =
          CodeOwnerResolverResult.create(
              codeOwnersWithAnnotations.keySet(),
              annotationsByCodeOwner.build(),
              ownedByAllUsers.get(),
              hasUnresolvedCodeOwners.get(),
              !unresolvedImports.isEmpty(),
              messageBuilder.build());
      logger.atFine().log("resolve result = %s", codeOwnerResolverResult);
      return codeOwnerResolverResult;
    }
  }

  /**
   * Resolves a {@link CodeOwnerReference} to a {@link CodeOwner}.
   *
   * <p>This method does not resolve {@link CodeOwnerReference}s that assign the code ownership to
   * all user by using {@link #ALL_USERS_WILDCARD} as email.
   *
   * @param codeOwnerReference the code owner reference that should be resolved
   * @return the {@link CodeOwner} for the code owner reference if it was resolved, otherwise {@link
   *     Optional#empty()}
   */
  public Optional<CodeOwner> resolve(CodeOwnerReference codeOwnerReference) {
    OptionalResultWithMessages<CodeOwner> resolveResult = resolveWithMessages(codeOwnerReference);
    logger.atFine().log("resolve result = %s", resolveResult);
    return resolveResult.result();
  }

  /**
   * Resolves a {@link CodeOwnerReference} to a {@link CodeOwner}.
   *
   * <p>This method does not resolve {@link CodeOwnerReference}s that assign the code ownership to
   * all user by using {@link #ALL_USERS_WILDCARD} as email.
   *
   * <p>Debug messages are returned with the result.
   *
   * @param codeOwnerReference the code owner reference that should be resolved
   * @return the result of resolving the given code owner reference with debug messages
   */
  public OptionalResultWithMessages<CodeOwner> resolveWithMessages(
      CodeOwnerReference codeOwnerReference) {
    requireNonNull(codeOwnerReference, "codeOwnerReference");

    if (CodeOwnerResolver.ALL_USERS_WILDCARD.equals(codeOwnerReference.email())) {
      return OptionalResultWithMessages.createEmpty(
          String.format(
              "cannot resolve code owner email %s: no account with this email exists",
              CodeOwnerResolver.ALL_USERS_WILDCARD));
    }

    ImmutableList.Builder<String> messageBuilder = ImmutableList.builder();
    AtomicBoolean ownedByAllUsers = new AtomicBoolean(false);
    AtomicBoolean hasUnresolvedCodeOwners = new AtomicBoolean(false);
    ImmutableMap<CodeOwner, ImmutableSet<CodeOwnerAnnotation>> codeOwnersWithAnnotations =
        resolve(
            messageBuilder,
            ownedByAllUsers,
            hasUnresolvedCodeOwners,
            ImmutableSet.of(codeOwnerReference),
            /* annotations= */ ImmutableMultimap.of());
    ImmutableList<String> messages = messageBuilder.build();
    if (codeOwnersWithAnnotations.isEmpty()) {
      return OptionalResultWithMessages.createEmpty(messages);
    }
    return OptionalResultWithMessages.create(
        Iterables.getOnlyElement(codeOwnersWithAnnotations.keySet()), messages);
  }

  /**
   * Resolves the given {@link CodeOwnerReference}s to {@link CodeOwner}s.
   *
   * <p>The accounts for the given {@link CodeOwnerReference}s are loaded from the account cache in
   * parallel (via {@link AccountCache#get(Set)}.
   *
   * @param messages a builder to which debug messages are added
   * @param ownedByAllUsers a flag that is set if any of the given {@link CodeOwnerReference}s
   *     assigns code ownership to all users
   * @param hasUnresolvedCodeOwners a flag that is set any of the given {@link CodeOwnerReference}s
   *     cannot be resolved
   * @param codeOwnerReferences the code owner references that should be resolved
   * @param annotations annotations by code owner reference
   * @return map that maps the resolved {@link CodeOwner}s to their annotations (note: we cannot
   *     return a {@code Multimap<CodeOwner, CodeOwnerAnnotation>} here since there may be code
   *     owners without annotations and Multimap doesn't store keys for which no values are stored)
   */
  private ImmutableMap<CodeOwner, ImmutableSet<CodeOwnerAnnotation>> resolve(
      ImmutableList.Builder<String> messages,
      AtomicBoolean ownedByAllUsers,
      AtomicBoolean hasUnresolvedCodeOwners,
      Set<CodeOwnerReference> codeOwnerReferences,
      ImmutableMultimap<CodeOwnerReference, CodeOwnerAnnotation> annotations) {
    requireNonNull(codeOwnerReferences, "codeOwnerReferences");

    ImmutableSet<String> emailsToResolve =
        codeOwnerReferences.stream()
            .map(CodeOwnerReference::email)
            .filter(filterOutAllUsersWildCard(ownedByAllUsers))
            .collect(toImmutableSet());

    ImmutableMap<String, Optional<CodeOwner>> cachedCodeOwnersByEmail =
        transientCodeOwnerCache.get(emailsToResolve);

    ImmutableSet<String> emailsToLookup =
        emailsToResolve.stream()
            .filter(email -> !cachedCodeOwnersByEmail.containsKey(email))
            .filter(filterOutEmailsWithNonAllowedDomains(messages))
            .collect(toImmutableSet());

    ImmutableMap<String, Collection<ExternalId>> externalIdsByEmail =
        lookupExternalIds(messages, emailsToLookup);

    Stream<Pair<String, AccountState>> accountsByEmail =
        lookupAccounts(messages, externalIdsByEmail)
            .map(removeInactiveAccounts(messages))
            .filter(filterOutEmailsWithoutAccounts(messages))
            .filter(filterOutAmbiguousEmails(messages))
            .map(mapToOnlyAccount(messages));

    if (enforceVisibility) {
      accountsByEmail =
          accountsByEmail
              .filter(filterOutEmailsOfNonVisibleAccounts(messages))
              .filter(filterOutNonVisibleSecondaryEmails(messages));
    } else {
      messages.add("code owner visibility is not checked");
    }

    ImmutableMap<String, CodeOwner> codeOwnersByEmail =
        accountsByEmail.map(mapToCodeOwner()).collect(toImmutableMap(Pair::key, Pair::value));

    if (codeOwnersByEmail.keySet().size() < emailsToResolve.size()) {
      hasUnresolvedCodeOwners.set(true);
    }

    Map<CodeOwner, Set<CodeOwnerAnnotation>> codeOwnersWithAnnotations = new HashMap<>();

    // Merge code owners that have been newly resolved with code owners which have been looked up
    // from cache and return them with their annotations.
    Stream<Pair<String, CodeOwner>> newlyResolvedCodeOwnersStream =
        codeOwnersByEmail.entrySet().stream().map(e -> Pair.of(e.getKey(), e.getValue()));
    Stream<Pair<String, CodeOwner>> cachedCodeOwnersStream =
        cachedCodeOwnersByEmail.entrySet().stream()
            .filter(e -> e.getValue().isPresent())
            .map(e -> Pair.of(e.getKey(), e.getValue().get()));
    Streams.concat(newlyResolvedCodeOwnersStream, cachedCodeOwnersStream)
        .forEach(
            p -> {
              ImmutableSet.Builder<CodeOwnerAnnotation> annotationBuilder = ImmutableSet.builder();

              annotationBuilder.addAll(annotations.get(CodeOwnerReference.create(p.key())));

              // annotations for the all users wildcard (aka '*') apply to all code owners
              annotationBuilder.addAll(
                  annotations.get(CodeOwnerReference.create(ALL_USERS_WILDCARD)));

              if (!codeOwnersWithAnnotations.containsKey(p.value())) {
                codeOwnersWithAnnotations.put(p.value(), new HashSet<>());
              }
              codeOwnersWithAnnotations.get(p.value()).addAll(annotationBuilder.build());
            });

    return codeOwnersWithAnnotations.entrySet().stream()
        .collect(toImmutableMap(Map.Entry::getKey, e -> ImmutableSet.copyOf(e.getValue())));
  }

  /**
   * Creates a predicate to filter out emails that are all users wild card (aka {@code *}).
   *
   * @param ownedByAllUsers flag that is set if any of the emails is the all users wild card (aka
   *     {@code *})
   */
  private Predicate<String> filterOutAllUsersWildCard(AtomicBoolean ownedByAllUsers) {
    return email -> {
      if (ALL_USERS_WILDCARD.equals(email)) {
        ownedByAllUsers.set(true);
        return false;
      }
      return true;
    };
  }

  /**
   * Creates a predicate to filter out emails that have a non-allowed email domain.
   *
   * <p>Which emails domains are allowed is controlled via the plugin configuration (see {@link
   * com.google.gerrit.plugins.codeowners.backend.config.CodeOwnersPluginGlobalConfigSnapshot#getAllowedEmailDomains()}
   *
   * @param messages builder to which debug messages are added
   */
  private Predicate<String> filterOutEmailsWithNonAllowedDomains(
      ImmutableList.Builder<String> messages) {
    return email -> {
      boolean isEmailDomainAllowed = isEmailDomainAllowed(messages, email);
      if (!isEmailDomainAllowed) {
        transientCodeOwnerCache.cacheNonResolvable(email);
      }
      return isEmailDomainAllowed;
    };
  }

  /**
   * Whether the domain of the given email is allowed for code owners.
   *
   * <p>Which emails domains are allowed is controlled via the plugin configuration (see {@link
   * com.google.gerrit.plugins.codeowners.backend.config.CodeOwnersPluginGlobalConfigSnapshot#getAllowedEmailDomains()}
   *
   * <p>Debug messages are returned with the result.
   *
   * @param email the email for which the domain should be checked
   * @return a {@link OptionalResultWithMessages} that contains {@code true} if the domain of the
   *     given email is allowed for code owners, otherwise {@link OptionalResultWithMessages} that
   *     contains {@code false}
   */
  public OptionalResultWithMessages<Boolean> isEmailDomainAllowed(String email) {
    ImmutableList.Builder<String> messages = ImmutableList.builder();
    boolean isEmailDomainAllowed = isEmailDomainAllowed(messages, email);
    return OptionalResultWithMessages.create(isEmailDomainAllowed, messages.build());
  }

  /**
   * Whether the domain of the given email is allowed for code owners.
   *
   * <p>Which emails domains are allowed is controlled via the plugin configuration (see {@link
   * com.google.gerrit.plugins.codeowners.backend.config.CodeOwnersPluginGlobalConfigSnapshot#getAllowedEmailDomains()}
   *
   * @param messages builder to which debug messages are added
   * @param email the email for which the domain should be checked
   * @return {@code true} if the domain of the given email is allowed for code owners, otherwise
   *     {@code false}
   */
  private boolean isEmailDomainAllowed(ImmutableList.Builder<String> messages, String email) {
    requireNonNull(messages, "messages");
    requireNonNull(email, "email");

    ImmutableSet<String> allowedEmailDomains =
        codeOwnersPluginConfiguration.getGlobalConfig().getAllowedEmailDomains();
    if (allowedEmailDomains.isEmpty()) {
      messages.add("all domains are allowed");
      return true;
    }

    if (email.equals(ALL_USERS_WILDCARD)) {
      messages.add("all users wildcard is allowed");
      return true;
    }

    int emailAtIndex = email.lastIndexOf('@');
    if (emailAtIndex >= 0 && emailAtIndex < email.length() - 1) {
      String emailDomain = email.substring(emailAtIndex + 1);
      boolean isEmailDomainAllowed = allowedEmailDomains.contains(emailDomain);
      messages.add(
          String.format(
              "domain %s of email %s is %s",
              emailDomain, email, isEmailDomainAllowed ? "allowed" : "not allowed"));
      return isEmailDomainAllowed;
    }

    messages.add(String.format("email %s has no domain", email));
    return false;
  }

  /**
   * Looks up the external IDs for the given emails.
   *
   * <p>Looks up all emails from the external ID cache at once, which is more efficient than looking
   * up external IDs for emails one by one (see {@link ExternalIds#byEmails(String...)}).
   *
   * @param messages builder to which debug messages are added
   * @param emails the emails for which the external IDs should be looked up
   * @return external IDs per email
   */
  private ImmutableMap<String, Collection<ExternalId>> lookupExternalIds(
      ImmutableList.Builder<String> messages, ImmutableSet<String> emails) {
    try {
      ImmutableMap<String, Collection<ExternalId>> extIdsByEmail =
          externalIds.byEmails(emails.toArray(new String[0])).asMap();
      emails.stream()
          .filter(email -> !extIdsByEmail.containsKey(email))
          .forEach(
              email -> {
                transientCodeOwnerCache.cacheNonResolvable(email);
                messages.add(
                    String.format(
                        "cannot resolve code owner email %s: no account with this email exists",
                        email));
              });
      return extIdsByEmail;
    } catch (IOException e) {
      throw newInternalServerError(
          String.format("cannot resolve code owner emails: %s", emails), e);
    }
  }

  /**
   * Looks up the accounts for the given external IDs.
   *
   * <p>Looks up all accounts from the account cache at once, which is more efficient than looking
   * up accounts one by one (see {@link AccountCache#get(Set)}).
   *
   * @param messages builder to which debug messages are added
   * @param externalIdsByEmail external IDs for which the accounts should be looked up
   * @return account states per email
   */
  private Stream<Pair<String, Collection<AccountState>>> lookupAccounts(
      ImmutableList.Builder<String> messages,
      ImmutableMap<String, Collection<ExternalId>> externalIdsByEmail) {
    ImmutableSet<Account.Id> accountIds =
        externalIdsByEmail.values().stream()
            .flatMap(Collection::stream)
            .map(ExternalId::accountId)
            .collect(toImmutableSet());
    Map<Account.Id, AccountState> accounts = accountCache.get(accountIds);
    return externalIdsByEmail.entrySet().stream()
        .map(
            e ->
                Pair.of(
                    e.getKey(),
                    e.getValue().stream()
                        .map(
                            extId -> {
                              Account.Id accountId = extId.accountId();
                              AccountState accountState = accounts.get(accountId);
                              if (accountState == null) {
                                messages.add(
                                    String.format(
                                        "cannot resolve account %s for email %s: account does not"
                                            + " exists",
                                        accountId, e.getKey()));
                              }
                              return accountState;
                            })
                        .filter(Objects::nonNull)
                        .collect(toImmutableSet())));
  }

  /**
   * Creates a map function that removes inactive accounts from a {@code Pair<String,
   * Collection<AccountState>>}.
   *
   * <p>The pair which is provided as input to the function maps an email to a collection of account
   * states.
   *
   * @param messages builder to which debug messages are added
   */
  private Function<Pair<String, Collection<AccountState>>, Pair<String, Collection<AccountState>>>
      removeInactiveAccounts(ImmutableList.Builder<String> messages) {
    return e -> Pair.of(e.key(), removeInactiveAccounts(messages, e.key(), e.value()));
  }

  /**
   * Removes inactive accounts from the given collection of account states.
   *
   * @param messages builder to which debug messages are added
   * @param email email to which the accounts belong
   * @param accountStates the set of account states from which inactive accounts should be removed
   * @return the account states that belong to active accounts
   */
  private ImmutableSet<AccountState> removeInactiveAccounts(
      ImmutableList.Builder<String> messages,
      String email,
      Collection<AccountState> accountStates) {
    return accountStates.stream()
        .filter(
            accountState -> {
              if (!accountState.account().isActive()) {
                messages.add(
                    String.format(
                        "ignoring inactive account %s for email %s",
                        accountState.account().id(), email));
                return false;
              }
              return true;
            })
        .collect(toImmutableSet());
  }

  /**
   * Creates a predicate to filter out emails without accounts.
   *
   * <p>The pair which is provided as input to the predicate maps an email to a collection of
   * account states. If the collection of account states is empty, the email is filtered out.
   *
   * @param messages builder to which debug messages are added
   */
  private Predicate<Pair<String, Collection<AccountState>>> filterOutEmailsWithoutAccounts(
      ImmutableList.Builder<String> messages) {
    return e -> {
      if (e.value().isEmpty()) {
        String email = e.key();
        transientCodeOwnerCache.cacheNonResolvable(email);
        messages.add(
            String.format(
                "cannot resolve code owner email %s: no active account with this email found",
                email));
        return false;
      }
      return true;
    };
  }

  /**
   * Creates a predicate to filter out ambiguous emails (emails that belong to multiple accounts).
   *
   * <p>The pair which is provided as input to the predicate maps an email to a collection of
   * account states. If the collection of account states contains more than 1 entry, the email is
   * filtered out.
   *
   * @param messages builder to which debug messages are added
   */
  private Predicate<Pair<String, Collection<AccountState>>> filterOutAmbiguousEmails(
      ImmutableList.Builder<String> messages) {
    return e -> {
      if (e.value().size() > 1) {
        String email = e.key();
        transientCodeOwnerCache.cacheNonResolvable(email);
        messages.add(
            String.format("cannot resolve code owner email %s: email is ambiguous", email));
        return false;
      }
      return true;
    };
  }

  /**
   * Creates a map function that maps a {@code Pair<String, Collection<AccountState>>} to a {@code
   * Pair<String, AccountState>}.
   *
   * <p>The pair which is provided as input to the function maps an email to a collection of account
   * states, which must contain exactly one entry. As output the function returns a pair that maps
   * the email to the only account state.
   *
   * @param messages builder to which debug messages are added
   */
  private Function<Pair<String, Collection<AccountState>>, Pair<String, AccountState>>
      mapToOnlyAccount(ImmutableList.Builder<String> messages) {
    return e -> {
      String email = e.key();
      AccountState accountState = Iterables.getOnlyElement(e.value());
      messages.add(
          String.format("resolved email %s to account %s", email, accountState.account().id()));
      return Pair.of(email, accountState);
    };
  }

  /**
   * Creates a predicate to filter out emails that belong to non-visible accounts.
   *
   * @param messages builder to which debug messages are added
   */
  private Predicate<Pair<String, AccountState>> filterOutEmailsOfNonVisibleAccounts(
      ImmutableList.Builder<String> messages) {
    return e -> {
      String email = e.key();
      AccountState accountState = e.value();
      if (!canSee(accountState)) {
        transientCodeOwnerCache.cacheNonResolvable(email);
        messages.add(
            String.format(
                "cannot resolve code owner email %s: account %s is not visible to user %s",
                email,
                accountState.account().id(),
                user != null ? user.getLoggableName() : currentUser.get().getLoggableName()));
        return false;
      }

      return true;
    };
  }

  /** Whether the given account can be seen. */
  private boolean canSee(AccountState accountState) {
    AccountControl accountControl =
        user != null ? accountControlFactory.get(user) : accountControlFactory.get();
    return accountControl.canSee(accountState);
  }

  /**
   * Creates a predicate to filter out non-visible secondary emails.
   *
   * <p>A secondary email is only visible if
   *
   * <ul>
   *   <li>it is owned by the {@link #user} or the calling user (if {@link #user} is unset)
   *   <li>if the {@link #user} or the calling user (if {@link #user} is unset) has the {@code
   *       Modify Account} global capability
   * </ul>
   *
   * @param messages builder to which debug messages are added
   */
  private Predicate<Pair<String, AccountState>> filterOutNonVisibleSecondaryEmails(
      ImmutableList.Builder<String> messages) {
    return e -> {
      String email = e.key();
      AccountState accountState = e.value();
      if (email.equals(accountState.account().preferredEmail())) {
        // the email is a primary email of the account
        messages.add(
            String.format(
                "account %s is visible to user %s",
                accountState.account().id(),
                user != null ? user.getLoggableName() : currentUser.get().getLoggableName()));
        return true;
      }

      if (user != null) {
        if (user.hasEmailAddress(email)) {
          messages.add(
              String.format(
                  "email %s is visible to user %s: email is a secondary email that is owned by this"
                      + " user",
                  email, user.getLoggableName()));
          return true;
        }
      } else if (currentUser.get().isIdentifiedUser()
          && currentUser.get().asIdentifiedUser().hasEmailAddress(email)) {
        // it's a secondary email of the calling user, users can always see their own secondary
        // emails
        messages.add(
            String.format(
                "email %s is visible to the calling user %s: email is a secondary email that is"
                    + " owned by this user",
                email, currentUser.get().getLoggableName()));
        return true;
      }

      // the email is a secondary email of another account, check if the user can see secondary
      // emails
      try {
        if (user != null) {
          if (!permissionBackend.user(user).test(GlobalPermission.MODIFY_ACCOUNT)) {
            transientCodeOwnerCache.cacheNonResolvable(email);
            messages.add(
                String.format(
                    "cannot resolve code owner email %s: account %s is referenced by secondary email"
                        + " but user %s cannot see secondary emails",
                    email, accountState.account().id(), user.getLoggableName()));
            return false;
          }
          messages.add(
              String.format(
                  "resolved code owner email %s: account %s is referenced by secondary email"
                      + " and user %s can see secondary emails",
                  email, accountState.account().id(), user.getLoggableName()));
          return true;
        } else if (!permissionBackend.currentUser().test(GlobalPermission.MODIFY_ACCOUNT)) {
          transientCodeOwnerCache.cacheNonResolvable(email);
          messages.add(
              String.format(
                  "cannot resolve code owner email %s: account %s is referenced by secondary email"
                      + " but the calling user %s cannot see secondary emails",
                  email, accountState.account().id(), currentUser.get().getLoggableName()));
          return false;
        } else {
          messages.add(
              String.format(
                  "resolved code owner email %s: account %s is referenced by secondary email"
                      + " and the calling user %s can see secondary emails",
                  email, accountState.account().id(), currentUser.get().getLoggableName()));
          return true;
        }
      } catch (PermissionBackendException ex) {
        throw newInternalServerError(
            String.format(
                "failed to test the %s global capability", GlobalPermission.MODIFY_ACCOUNT),
            ex);
      }
    };
  }

  /**
   * Creates a map function that maps a {@code Pair<String, AccountState>} to a code owner.
   *
   * <p>The pair which is provided as input to the function maps an email to an account states.
   */
  private Function<Pair<String, AccountState>, Pair<String, CodeOwner>> mapToCodeOwner() {
    return e -> {
      String email = e.key();
      CodeOwner codeOwner = CodeOwner.create(e.value().account().id());
      transientCodeOwnerCache.cache(email, codeOwner);
      return Pair.of(email, codeOwner);
    };
  }

  /** Returns the counters for resolutions and cache reads of code owners. */
  public TransientCodeOwnerCache.Counters getCodeOwnerCounters() {
    return transientCodeOwnerCache.getCounters();
  }
}
