// Copyright (C) 2009 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.approval;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.collect.ImmutableListMultimap.toImmutableListMultimap;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static com.google.gerrit.server.notedb.ReviewerStateInternal.CC;
import static com.google.gerrit.server.notedb.ReviewerStateInternal.REVIEWER;
import static com.google.gerrit.server.project.ProjectCache.illegalState;
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.Function;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimaps;
import com.google.common.collect.Sets;
import com.google.common.flogger.FluentLogger;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.AttentionSetUpdate;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.LabelId;
import com.google.gerrit.entities.LabelType;
import com.google.gerrit.entities.LabelTypes;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.PatchSetApproval;
import com.google.gerrit.entities.PatchSetInfo;
import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.index.query.QueryParseException;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.ReviewerSet;
import com.google.gerrit.server.ReviewerStatusUpdate;
import com.google.gerrit.server.account.AccountCache;
import com.google.gerrit.server.change.LabelNormalizer;
import com.google.gerrit.server.config.AnonymousCowardName;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.notedb.ChangeUpdate;
import com.google.gerrit.server.notedb.ReviewerStateInternal;
import com.google.gerrit.server.permissions.ChangePermission;
import com.google.gerrit.server.permissions.LabelPermission;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.query.approval.ApprovalQueryBuilder;
import com.google.gerrit.server.query.approval.UserInPredicate;
import com.google.gerrit.server.update.RepoView;
import com.google.gerrit.server.util.AccountTemplateUtil;
import com.google.gerrit.server.util.LabelVote;
import com.google.gerrit.server.util.ManualRequestContext;
import com.google.gerrit.server.util.OneOffRequestContext;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.StringTokenizer;

/**
 * Utility functions to manipulate patchset approvals.
 *
 * <p>Approvals are overloaded, they represent both approvals and reviewers which should be CCed on
 * a change. To ensure that reviewers are not lost there must always be an approval on each patchset
 * for each reviewer, even if the reviewer hasn't actually given a score to the change. To mark the
 * "no score" case, a dummy approval, which may live in any of the available categories, with a
 * score of 0 is used.
 */
@Singleton
public class ApprovalsUtil {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  public static PatchSetApproval.Builder newApproval(
      PatchSet.Id psId, CurrentUser user, LabelId labelId, int value, Instant when) {
    PatchSetApproval.Builder b =
        PatchSetApproval.builder()
            .key(PatchSetApproval.key(psId, user.getAccountId(), labelId))
            .value(value)
            .granted(when);
    user.updateRealAccountId(b::realAccountId);
    return b;
  }

  private static Iterable<PatchSetApproval> filterApprovals(
      Iterable<PatchSetApproval> psas, Account.Id accountId) {
    return Iterables.filter(psas, a -> Objects.equals(a.accountId(), accountId));
  }

  private final AccountCache accountCache;
  private final String anonymousCowardName;
  private final ApprovalCopier approvalCopier;
  private final Provider<ApprovalQueryBuilder> approvalQueryBuilderProvider;
  private final PermissionBackend permissionBackend;
  private final ProjectCache projectCache;
  private final LabelNormalizer labelNormalizer;
  private final OneOffRequestContext requestContext;

  @VisibleForTesting
  @Inject
  public ApprovalsUtil(
      AccountCache accountCache,
      @AnonymousCowardName String anonymousCowardName,
      ApprovalCopier approvalCopier,
      Provider<ApprovalQueryBuilder> approvalQueryBuilderProvider,
      PermissionBackend permissionBackend,
      ProjectCache projectCache,
      LabelNormalizer labelNormalizer,
      OneOffRequestContext requestContext) {
    this.accountCache = accountCache;
    this.anonymousCowardName = anonymousCowardName;
    this.approvalCopier = approvalCopier;
    this.approvalQueryBuilderProvider = approvalQueryBuilderProvider;
    this.permissionBackend = permissionBackend;
    this.projectCache = projectCache;
    this.labelNormalizer = labelNormalizer;
    this.requestContext = requestContext;
  }

  /**
   * Get all reviewers for a change.
   *
   * @param notes change notes.
   * @return reviewers for the change.
   */
  public ReviewerSet getReviewers(ChangeNotes notes) {
    return notes.load().getReviewers();
  }

  /**
   * Get updates to reviewer set.
   *
   * @param notes change notes.
   * @return reviewer updates for the change.
   */
  public List<ReviewerStatusUpdate> getReviewerUpdates(ChangeNotes notes) {
    return notes.load().getReviewerUpdates();
  }

  public List<PatchSetApproval> addReviewers(
      ChangeUpdate update,
      LabelTypes labelTypes,
      Change change,
      PatchSet ps,
      PatchSetInfo info,
      Iterable<Account.Id> wantReviewers,
      Collection<Account.Id> existingReviewers) {
    return addReviewers(
        update,
        labelTypes,
        change,
        ps.id(),
        info.getAuthor().getAccount(),
        info.getCommitter().getAccount(),
        wantReviewers,
        existingReviewers);
  }

  public List<PatchSetApproval> addReviewers(
      ChangeNotes notes,
      ChangeUpdate update,
      LabelTypes labelTypes,
      Change change,
      Iterable<Account.Id> wantReviewers) {
    PatchSet.Id psId = change.currentPatchSetId();
    Collection<Account.Id> existingReviewers;
    existingReviewers = notes.load().getReviewers().byState(REVIEWER);
    // Existing reviewers should include pending additions in the REVIEWER
    // state, taken from ChangeUpdate.
    existingReviewers = Lists.newArrayList(existingReviewers);
    for (Map.Entry<Account.Id, ReviewerStateInternal> entry : update.getReviewers().entrySet()) {
      if (entry.getValue() == REVIEWER) {
        existingReviewers.add(entry.getKey());
      }
    }
    return addReviewers(
        update, labelTypes, change, psId, null, null, wantReviewers, existingReviewers);
  }

  private List<PatchSetApproval> addReviewers(
      ChangeUpdate update,
      LabelTypes labelTypes,
      Change change,
      PatchSet.Id psId,
      Account.Id authorId,
      Account.Id committerId,
      Iterable<Account.Id> wantReviewers,
      Collection<Account.Id> existingReviewers) {
    List<LabelType> allTypes = labelTypes.getLabelTypes();
    if (allTypes.isEmpty()) {
      return ImmutableList.of();
    }

    Set<Account.Id> need = Sets.newLinkedHashSet(wantReviewers);
    if (authorId != null && canSee(update.getNotes(), authorId)) {
      need.add(authorId);
    }

    if (committerId != null && canSee(update.getNotes(), committerId)) {
      need.add(committerId);
    }
    need.remove(change.getOwner());
    need.removeAll(existingReviewers);
    if (need.isEmpty()) {
      return ImmutableList.of();
    }

    List<PatchSetApproval> cells = Lists.newArrayListWithCapacity(need.size());
    LabelId labelId = Iterables.getLast(allTypes).getLabelId();
    for (Account.Id account : need) {
      cells.add(
          PatchSetApproval.builder()
              .key(PatchSetApproval.key(psId, account, labelId))
              .value(0)
              .granted(update.getWhen())
              .build());
      update.putReviewer(account, REVIEWER);
    }
    return Collections.unmodifiableList(cells);
  }

  private boolean canSee(ChangeNotes notes, Account.Id accountId) {
    try {
      if (!projectCache
          .get(notes.getProjectName())
          .orElseThrow(illegalState(notes.getProjectName()))
          .statePermitsRead()) {
        return false;
      }
      return permissionBackend.absentUser(accountId).change(notes).test(ChangePermission.READ);
    } catch (PermissionBackendException e) {
      logger.atWarning().withCause(e).log(
          "Failed to check if account %d can see change %d",
          accountId.get(), notes.getChangeId().get());
      return false;
    }
  }

  /**
   * Adds accounts to a change as reviewers in the CC state.
   *
   * @param notes change notes.
   * @param update change update.
   * @param wantCCs accounts to CC.
   * @param keepExistingReviewers whether provided accounts that are already reviewer should be kept
   *     as reviewer or be downgraded to CC
   * @return whether a change was made.
   */
  public Collection<Account.Id> addCcs(
      ChangeNotes notes,
      ChangeUpdate update,
      Collection<Account.Id> wantCCs,
      boolean keepExistingReviewers) {
    return addCcs(update, wantCCs, notes.load().getReviewers(), keepExistingReviewers);
  }

  private Set<Account.Id> addCcs(
      ChangeUpdate update,
      Collection<Account.Id> wantCCs,
      ReviewerSet existingReviewers,
      boolean keepExistingReviewers) {
    Set<Account.Id> need = new LinkedHashSet<>(wantCCs);
    need.removeAll(existingReviewers.byState(CC));
    if (keepExistingReviewers) {
      need.removeAll(existingReviewers.byState(REVIEWER));
    }
    need.removeAll(update.getReviewers().keySet());
    for (Account.Id account : need) {
      update.putReviewer(account, CC);
    }
    return need;
  }

  /**
   * Adds approvals to ChangeUpdate for a new patch set, and writes to NoteDb.
   *
   * @param update change update.
   * @param labelTypes label types for the containing project.
   * @param ps patch set being approved.
   * @param user user adding approvals.
   * @param approvals approvals to add.
   */
  @CanIgnoreReturnValue
  public Iterable<PatchSetApproval> addApprovalsForNewPatchSet(
      ChangeUpdate update,
      LabelTypes labelTypes,
      PatchSet ps,
      CurrentUser user,
      Map<String, Short> approvals)
      throws RestApiException, PermissionBackendException {
    Account.Id accountId = user.getAccountId();
    checkArgument(
        accountId.equals(ps.uploader()),
        "expected user %s to match patch set uploader %s",
        accountId,
        ps.uploader());
    if (approvals.isEmpty()) {
      return ImmutableList.of();
    }
    checkApprovals(approvals, permissionBackend.user(user).change(update.getNotes()));
    List<PatchSetApproval> cells = new ArrayList<>(approvals.size());
    Instant ts = update.getWhen();
    for (Map.Entry<String, Short> vote : approvals.entrySet()) {
      Optional<LabelType> lt = labelTypes.byLabel(vote.getKey());
      if (!lt.isPresent()) {
        throw new BadRequestException(
            String.format("label \"%s\" is not a configured label", vote.getKey()));
      }
      cells.add(newApproval(ps.id(), user, lt.get().getLabelId(), vote.getValue(), ts).build());
    }
    for (PatchSetApproval psa : cells) {
      update.putApproval(psa.label(), psa.value());
    }
    return cells;
  }

  public static void checkLabel(LabelTypes labelTypes, String name, Short value)
      throws BadRequestException {
    Optional<LabelType> label = labelTypes.byLabel(name);
    if (!label.isPresent()) {
      throw new BadRequestException(String.format("label \"%s\" is not a configured label", name));
    }
    if (label.get().getValue(value) == null) {
      throw new BadRequestException(
          String.format("label \"%s\": %d is not a valid value", name, value));
    }
  }

  private static void checkApprovals(
      Map<String, Short> approvals, PermissionBackend.ForChange forChange)
      throws AuthException, PermissionBackendException {
    for (Map.Entry<String, Short> vote : approvals.entrySet()) {
      String name = vote.getKey();
      Short value = vote.getValue();
      if (!forChange.test(new LabelPermission.WithValue(name, value))) {
        throw new AuthException(
            String.format("applying label \"%s\": %d is restricted", name, value));
      }
    }
  }

  public ListMultimap<PatchSet.Id, PatchSetApproval> byChangeExcludingCopiedApprovals(
      ChangeNotes notes) {
    return notes.load().getApprovals().onlyNonCopied();
  }

  public ListMultimap<PatchSet.Id, PatchSetApproval> byChangeIncludingCopiedApprovals(
      ChangeNotes notes) {
    return notes.load().getApprovals().all();
  }

  /**
   * Copies approvals to a new patch set.
   *
   * <p>Computes the approvals of the prior patch set that should be copied to the new patch set and
   * stores them in NoteDb.
   *
   * <p>For outdated approvals (approvals on the prior patch set which are outdated by the new patch
   * set and hence not copied) the approvers are added to the attention set since they need to
   * re-review the change and renew their approvals.
   *
   * @param notes the change notes
   * @param patchSet the newly created patch set
   * @param repoView repo view
   * @param changeUpdate changeUpdate that is used to persist the copied approvals and update the
   *     attention set
   * @return the result of the approval copying
   */
  public ApprovalCopier.Result copyApprovalsToNewPatchSet(
      ChangeNotes notes, PatchSet patchSet, RepoView repoView, ChangeUpdate changeUpdate) {
    ApprovalCopier.Result approvalCopierResult =
        approvalCopier.forPatchSet(notes, patchSet, repoView);
    approvalCopierResult
        .copiedApprovals()
        .forEach(approvalData -> changeUpdate.putCopiedApproval(approvalData.patchSetApproval()));

    if (!notes.getChange().isWorkInProgress()) {
      // The attention set should not be updated when the change is work-in-progress.
      addAttentionSetUpdatesForOutdatedApprovals(
          changeUpdate,
          approvalCopierResult.outdatedApprovals().stream()
              .map(ApprovalCopier.Result.PatchSetApprovalData::patchSetApproval)
              .collect(toImmutableSet()));
    }

    return approvalCopierResult;
  }

  private void addAttentionSetUpdatesForOutdatedApprovals(
      ChangeUpdate changeUpdate, ImmutableSet<PatchSetApproval> outdatedApprovals) {
    Set<AttentionSetUpdate> updates = new HashSet<>();

    ListMultimap<Account.Id, PatchSetApproval> outdatedApprovalsByUser = ArrayListMultimap.create();
    outdatedApprovals.forEach(psa -> outdatedApprovalsByUser.put(psa.accountId(), psa));
    for (Map.Entry<Account.Id, Collection<PatchSetApproval>> e :
        outdatedApprovalsByUser.asMap().entrySet()) {
      Account.Id approverId = e.getKey();
      Collection<PatchSetApproval> outdatedUserApprovals = e.getValue();

      String message;
      if (outdatedUserApprovals.size() == 1) {
        PatchSetApproval outdatedUserApproval = Iterables.getOnlyElement(outdatedUserApprovals);
        message =
            String.format(
                "Vote got outdated and was removed: %s",
                LabelVote.create(outdatedUserApproval.label(), outdatedUserApproval.value())
                    .format());
      } else {
        message =
            String.format(
                "Votes got outdated and were removed: %s",
                outdatedUserApprovals.stream()
                    .map(
                        outdatedUserApproval ->
                            LabelVote.create(
                                    outdatedUserApproval.label(), outdatedUserApproval.value())
                                .format())
                    .sorted()
                    .collect(joining(", ")));
      }

      updates.add(
          AttentionSetUpdate.createForWrite(approverId, AttentionSetUpdate.Operation.ADD, message));
    }
    changeUpdate.addToPlannedAttentionSetUpdates(updates);
  }

  public Optional<String> formatApprovalCopierResult(
      ApprovalCopier.Result approvalCopierResult, LabelTypes labelTypes) {
    requireNonNull(approvalCopierResult, "approvalCopierResult");
    requireNonNull(labelTypes, "labelTypes");

    if (approvalCopierResult.copiedApprovals().isEmpty()
        && approvalCopierResult.outdatedApprovals().isEmpty()) {
      return Optional.empty();
    }

    StringBuilder message = new StringBuilder();

    if (!approvalCopierResult.copiedApprovals().isEmpty()) {
      message.append("Copied Votes:\n");
      message.append(
          formatApprovalListWithCopyCondition(approvalCopierResult.copiedApprovals(), labelTypes));
    }
    if (!approvalCopierResult.outdatedApprovals().isEmpty()) {
      if (!approvalCopierResult.copiedApprovals().isEmpty()) {
        message.append("\n");
      }
      message.append("Outdated Votes:\n");
      message.append(
          formatApprovalListWithCopyCondition(
              approvalCopierResult.outdatedApprovals(), labelTypes));
    }

    return Optional.of(message.toString());
  }

  /**
   * Formats the given approvals as a bullet list, each approval with the corresponding copy
   * condition if available.
   *
   * <p>E.g.:
   *
   * <pre>
   * * Code-Review+1, Code-Review+2 (copy condition: "is:MIN")
   * * Verified+1 (copy condition: "is:MIN")
   * </pre>
   *
   * <p>Entries in the list can have the following formats:
   *
   * <ul>
   *   <li>{@code <comma-separated-list-of-approvals-for-the-same-label> (copy condition:
   *       "<copy-condition-without-UserInPredicate>")} (if a copy condition without UserInPredicate
   *       is present), e.g.: {@code Code-Review+1, Code-Review+2 (copy condition: "is:MIN")}
   *   <li>{@code <approval> by <comma-separated-list-of-approvers> (copy condition:
   *       "<copy-condition-with-UserInPredicate>")} (if a copy condition with UserInPredicate is
   *       present), e.g. {@code Code-Review+1 by <GERRIT_ACCOUNT_1000000>, <GERRIT_ACCOUNT_1000001>
   *       (copy condition: "approverin:7d9e2d5b561e75230e4463ae757ac5d6ff715d85")}
   *   <li>{@code <comma-separated-list-of-approval-for-the-same-label>} (if no copy condition is
   *       present), e.g.: {@code Code-Review+1, Code-Review+2}
   *   <li>{@code <comma-separated-list-of-approval-for-the-same-label> (label type is missing)} (if
   *       the label type is missing), e.g.: {@code Code-Review+1, Code-Review+2 (label type is
   *       missing)}
   *   <li>{@code <comma-separated-list-of-approval-for-the-same-label> (non-parseable copy
   *       condition: "<non-parseable copy-condition>")} (if a non-parseable copy condition is
   *       present), e.g.: {@code Code-Review+1, Code-Review+2 (non-parseable copy condition:
   *       "is:FOO")}
   * </ul>
   *
   * @param approvalDatas the approvals that should be formatted, with approval meta data
   * @param labelTypes the label types
   * @return bullet list with the formatted approvals
   */
  private String formatApprovalListWithCopyCondition(
      ImmutableSet<ApprovalCopier.Result.PatchSetApprovalData> approvalDatas,
      LabelTypes labelTypes) {
    StringBuilder message = new StringBuilder();

    // sort approvals by label vote so that we list them in a deterministic order
    ImmutableList<ApprovalCopier.Result.PatchSetApprovalData> approvalsSortedByLabelVote =
        approvalDatas.stream()
            .sorted(
                comparing(
                    approvalData ->
                        LabelVote.create(
                                approvalData.patchSetApproval().label(),
                                approvalData.patchSetApproval().value())
                            .format()))
            .collect(toImmutableList());

    ImmutableListMultimap<String, ApprovalCopier.Result.PatchSetApprovalData> approvalsByLabel =
        Multimaps.index(
            approvalsSortedByLabelVote, approvalData -> approvalData.patchSetApproval().label());

    for (Map.Entry<String, Collection<ApprovalCopier.Result.PatchSetApprovalData>>
        approvalsByLabelEntry : approvalsByLabel.asMap().entrySet()) {
      String label = approvalsByLabelEntry.getKey();
      Collection<ApprovalCopier.Result.PatchSetApprovalData> approvalsForSameLabel =
          approvalsByLabelEntry.getValue();

      if (!labelTypes.byLabel(label).isPresent()) {
        message
            .append("* ")
            .append(formatApprovalsAsLabelVotesList(approvalsForSameLabel))
            .append(" (label type is missing)\n");
        continue;
      }

      LabelType labelType = labelTypes.byLabel(label).get();
      if (!labelType.getCopyCondition().isPresent()) {
        message
            .append("* ")
            .append(formatApprovalsAsLabelVotesList(approvalsForSameLabel))
            .append("\n");
        continue;
      }

      // Group the approvals that have the same label by the passing atoms. If approvals have the
      // same label, but have different passing atoms, we need to list them in separate lines
      // (because in each line we will highlight different passing atoms that matched). Approvals
      // with the same label and the same passing atoms are formatted as a single line.
      ImmutableListMultimap<ImmutableSet<String>, ApprovalCopier.Result.PatchSetApprovalData>
          approvalsForSameLabelByPassingAndFailingAtoms =
              Multimaps.index(
                  approvalsForSameLabel, ApprovalCopier.Result.PatchSetApprovalData::passingAtoms);

      // Approvals with the same label that have the same passing atoms should have the same failing
      // atoms (since the label is the same they have the same copy condition).
      approvalsForSameLabelByPassingAndFailingAtoms
          .asMap()
          .values()
          .forEach(
              approvalsForSameLabelAndSamePassingAtoms ->
                  checkThatPropertyIsTheSameForAllApprovals(
                      approvalsForSameLabelAndSamePassingAtoms,
                      "failing atoms",
                      approvalData -> approvalData.failingAtoms()));

      // The order in which we add lines for approvals with the same label but different passing
      // atoms needs to be deterministic for tests. Just sort them by the string representation of
      // the passing atoms.
      for (Collection<ApprovalCopier.Result.PatchSetApprovalData>
          approvalsForSameLabelWithSamePassingAndFailingAtoms :
              approvalsForSameLabelByPassingAndFailingAtoms.asMap().entrySet().stream()
                  .sorted(
                      comparing(
                          (Map.Entry<
                                      ImmutableSet<String>,
                                      Collection<ApprovalCopier.Result.PatchSetApprovalData>>
                                  e) -> e.getKey().toString()))
                  .map(Map.Entry::getValue)
                  .collect(toImmutableList())) {
        message
            .append("* ")
            .append(
                formatApprovalsWithCopyCondition(
                    approvalsForSameLabelWithSamePassingAndFailingAtoms,
                    labelType.getCopyCondition().get()))
            .append("\n");
      }
    }

    return message.toString();
  }

  /**
   * Formats the given approvals with the given copy condition.
   *
   * <p>The given approvals must have the same label and the same passing and failing atoms.
   *
   * <p>E.g.: {Code-Review+1, Code-Review+2 (copy condition: "is:MIN")}
   *
   * <p>The following format may be returned:
   *
   * <ul>
   *   <li>{@code <comma-separated-list-of-approvals-for-the-same-label> (copy condition:
   *       "<copy-condition-without-UserInPredicate>")} (if a copy condition without UserInPredicate
   *       is present), e.g.: {@code Code-Review+1, Code-Review+2 (copy condition: "is:MIN")}
   *   <li>{@code <approval> by <comma-separated-list-of-approvers> (copy condition:
   *       "<copy-condition-with-UserInPredicate>")} (if a copy condition with UserInPredicate is
   *       present), e.g. {@code Code-Review+1 by <GERRIT_ACCOUNT_1000000>, <GERRIT_ACCOUNT_1000001>
   *       (copy condition: "approverin:7d9e2d5b561e75230e4463ae757ac5d6ff715d85")}
   *   <li>{@code <comma-separated-list-of-approval-for-the-same-label> (non-parseable copy
   *       condition: "<non-parseable copy-condition>")} (if a non-parseable copy condition is
   *       present), e.g.: {@code Code-Review+1, Code-Review+2 (non-parseable copy condition:
   *       "is:FOO")}
   * </ul>
   *
   * @param approvalsWithSameLabelAndSamePassingAndFailingAtoms the approvals that should be
   *     formatted, must be for the same label
   * @param copyCondition the copy condition of the label
   * @return the formatted approvals
   */
  private String formatApprovalsWithCopyCondition(
      Collection<ApprovalCopier.Result.PatchSetApprovalData>
          approvalsWithSameLabelAndSamePassingAndFailingAtoms,
      String copyCondition) {
    // Check that all given approvals have the same label and the same passing and failing atoms.
    checkThatPropertyIsTheSameForAllApprovals(
        approvalsWithSameLabelAndSamePassingAndFailingAtoms,
        "label",
        approvalData -> approvalData.patchSetApproval().label());
    checkThatPropertyIsTheSameForAllApprovals(
        approvalsWithSameLabelAndSamePassingAndFailingAtoms,
        "passing atoms",
        approvalData -> approvalData.passingAtoms());
    checkThatPropertyIsTheSameForAllApprovals(
        approvalsWithSameLabelAndSamePassingAndFailingAtoms,
        "failing atoms",
        approvalData -> approvalData.failingAtoms());

    StringBuilder message = new StringBuilder();

    boolean containsUserInPredicate;
    try {
      containsUserInPredicate = containsUserInPredicate(copyCondition);
    } catch (QueryParseException e) {
      logger.atWarning().withCause(e).log("Non-parsable query condition");
      message.append(
          formatApprovalsAsLabelVotesList(approvalsWithSameLabelAndSamePassingAndFailingAtoms));
      message.append(String.format(" (non-parseable copy condition: \"%s\")", copyCondition));
      return message.toString();
    }

    if (containsUserInPredicate) {
      // If a UserInPredicate is used (e.g. 'approverin:<group>' or 'uploaderin:<group>') we need to
      // include the approvers into the change message since they are relevant for the matching. For
      // example it can happen that the same approval of different users is copied for the one user
      // but not for the other user (since the one user is a member of the approverin group and the
      // other user isn't).
      //
      // Example:
      // * label Foo has the copy condition 'is:ANY approverin:123'
      // * group 123 contains UserA as member, but not UserB
      // * a change has the following approvals: Foo+1 by UserA and Foo+1 by UserB
      //
      // In this case Foo+1 by UserA is copied because UserA is a member of group 123 and the copy
      // condition matches, while Foo+1 by UserB is not copied because UserB is not a member of
      // group 123 and the copy condition doesn't match.
      //
      // So it can happen that the same approval Foo+1, but by different users, is copied and
      // outdated at the same time. To allow users to understand that the copying depends on who did
      // the approval, the approvers must be included into the change message.

      // sort the approvals by their approvers name-email so that the approvers always appear in a
      // deterministic order
      ImmutableList<ApprovalCopier.Result.PatchSetApprovalData>
          approvalsSortedByLabelVoteAndApprover =
              approvalsWithSameLabelAndSamePassingAndFailingAtoms.stream()
                  .sorted(
                      comparing(
                              (ApprovalCopier.Result.PatchSetApprovalData approvalData) ->
                                  LabelVote.create(
                                          approvalData.patchSetApproval().label(),
                                          approvalData.patchSetApproval().value())
                                      .format())
                          .thenComparing(
                              approvalData ->
                                  accountCache
                                      .getEvenIfMissing(approvalData.patchSetApproval().accountId())
                                      .account()
                                      .getNameEmail(anonymousCowardName)))
                  .collect(toImmutableList());

      ImmutableListMultimap<LabelVote, Account.Id> approversByLabelVote =
          Multimaps.index(
                  approvalsSortedByLabelVoteAndApprover,
                  approvalData ->
                      LabelVote.create(
                          approvalData.patchSetApproval().label(),
                          approvalData.patchSetApproval().value()))
              .entries().stream()
              .collect(
                  toImmutableListMultimap(
                      e -> e.getKey(), e -> e.getValue().patchSetApproval().accountId()));
      message.append(
          approversByLabelVote.asMap().entrySet().stream()
              .map(
                  approversByLabelVoteEntry ->
                      formatLabelVoteWithApprovers(
                          approversByLabelVoteEntry.getKey(), approversByLabelVoteEntry.getValue()))
              .collect(joining(", ")));
    } else {
      // copy condition doesn't contain a UserInPredicate
      message.append(
          formatApprovalsAsLabelVotesList(approvalsWithSameLabelAndSamePassingAndFailingAtoms));
    }
    ImmutableSet<String> passingAtoms =
        !approvalsWithSameLabelAndSamePassingAndFailingAtoms.isEmpty()
            ? approvalsWithSameLabelAndSamePassingAndFailingAtoms.iterator().next().passingAtoms()
            : ImmutableSet.of();
    message.append(
        String.format(
            " (copy condition: \"%s\")",
            formatCopyConditionAsMarkdown(copyCondition, passingAtoms)));
    return message.toString();
  }

  /** Checks that all given approvals have the same value for a given property. */
  private void checkThatPropertyIsTheSameForAllApprovals(
      Collection<ApprovalCopier.Result.PatchSetApprovalData> approvals,
      String propertyName,
      Function<ApprovalCopier.Result.PatchSetApprovalData, ?> propertyExtractor) {
    if (approvals.isEmpty()) {
      return;
    }

    Object propertyOfFirstEntry = propertyExtractor.apply(approvals.iterator().next());
    approvals.forEach(
        approvalData ->
            checkState(
                propertyExtractor.apply(approvalData).equals(propertyOfFirstEntry),
                "property %s of approval %s does not match, expected value: %s",
                propertyName,
                approvalData,
                propertyOfFirstEntry));
  }

  /**
   * Formats the given copy condition as a Markdown string.
   *
   * <p>Passing atoms are formatted as bold.
   *
   * @param copyCondition the copy condition that should be formatted
   * @param passingAtoms atoms of the copy conditions which are passing/matching
   * @return the formatted copy condition as a Markdown string
   */
  private String formatCopyConditionAsMarkdown(
      String copyCondition, ImmutableSet<String> passingAtoms) {
    StringBuilder formattedCopyCondition = new StringBuilder();
    StringTokenizer tokenizer = new StringTokenizer(copyCondition, " ()", /* returnDelims= */ true);
    while (tokenizer.hasMoreTokens()) {
      String token = tokenizer.nextToken();
      if (passingAtoms.contains(token)) {
        formattedCopyCondition.append("**" + token.replace("*", "\\*") + "**");
      } else {
        formattedCopyCondition.append(token);
      }
    }
    return formattedCopyCondition.toString();
  }

  private boolean containsUserInPredicate(String copyCondition) throws QueryParseException {
    // Use a request context to run checks as an internal user with expanded visibility. This is
    // so that the output of the copy condition does not depend on who is running the current
    // request (e.g. a group used in this query might not be visible to the person sending this
    // request).
    try (ManualRequestContext ignored = requestContext.open()) {
      return approvalQueryBuilderProvider.get().parse(copyCondition).getFlattenedPredicateList()
          .stream()
          .anyMatch(UserInPredicate.class::isInstance);
    }
  }

  /**
   * Formats the given approvals as a comma-separated list of label votes.
   *
   * <p>E.g.: {@code Code-Review+1, CodeReview+2}
   *
   * @param sortedApprovalsForSameLabel the approvals that should be formatted as a comma-separated
   *     list of label votes, must be sorted
   * @return the given approvals as a comma-separated list of label votes
   */
  private String formatApprovalsAsLabelVotesList(
      Collection<ApprovalCopier.Result.PatchSetApprovalData> sortedApprovalsForSameLabel) {
    return sortedApprovalsForSameLabel.stream()
        .map(ApprovalCopier.Result.PatchSetApprovalData::patchSetApproval)
        .map(psa -> LabelVote.create(psa.label(), psa.value()))
        .distinct()
        .map(LabelVote::format)
        .collect(joining(", "));
  }

  /**
   * Formats the given label vote with a comma-separated list of the given approvers.
   *
   * <p>E.g.: {@code Code-Review+1 by <user1-placeholder>, <user2-placeholder>}
   *
   * @param labelVote the label vote that should be formatted with a comma-separated list of the
   *     given approver
   * @param sortedApprovers the approvers that should be formatted as a comma-separated list for the
   *     given label vote
   * @return the given label vote with a comma-separated list of the given approvers
   */
  private String formatLabelVoteWithApprovers(
      LabelVote labelVote, Collection<Account.Id> sortedApprovers) {
    return new StringBuilder()
        .append(labelVote.format())
        .append(" by ")
        .append(
            sortedApprovers.stream()
                .map(AccountTemplateUtil::getAccountTemplate)
                .collect(joining(", ")))
        .toString();
  }

  /**
   * Gets {@link PatchSetApproval}s for a specified patch-set. The result includes copied votes but
   * does not include deleted labels.
   *
   * @param notes changenotes of the change.
   * @param psId patch-set id for the change and patch-set we want to get approvals.
   * @return all approvals for the specified patch-set, including copied votes, not including
   *     deleted labels.
   */
  public Iterable<PatchSetApproval> byPatchSet(ChangeNotes notes, PatchSet.Id psId) {
    ImmutableList<PatchSetApproval> approvalsNotNormalized =
        notes.load().getApprovals().all().get(psId);
    return labelNormalizer.normalize(notes, approvalsNotNormalized).getNormalized();
  }

  public Iterable<PatchSetApproval> byPatchSetUser(
      ChangeNotes notes, PatchSet.Id psId, Account.Id accountId) {
    return filterApprovals(byPatchSet(notes, psId), accountId);
  }

  @Nullable
  public PatchSetApproval getSubmitter(ChangeNotes notes, PatchSet.Id c) {
    if (c == null) {
      return null;
    }
    try {
      // Submit approval is never copied.
      return getSubmitter(c, byChangeExcludingCopiedApprovals(notes).get(c));
    } catch (StorageException e) {
      return null;
    }
  }

  @Nullable
  public static PatchSetApproval getSubmitter(PatchSet.Id c, Iterable<PatchSetApproval> approvals) {
    if (c == null) {
      return null;
    }
    PatchSetApproval submitter = null;
    for (PatchSetApproval a : approvals) {
      if (a.patchSetId().equals(c) && a.value() > 0 && a.isLegacySubmit()) {
        if (submitter == null || a.granted().compareTo(submitter.granted()) > 0) {
          submitter = a;
        }
      }
    }
    return submitter;
  }

  public static String renderMessageWithApprovals(
      int patchSetId, Map<String, Short> n, Map<String, PatchSetApproval> c) {
    StringBuilder msgs = new StringBuilder("Uploaded patch set " + patchSetId);
    if (!n.isEmpty()) {
      boolean first = true;
      for (Map.Entry<String, Short> e : n.entrySet()) {
        if (c.containsKey(e.getKey()) && c.get(e.getKey()).value() == e.getValue()) {
          continue;
        }
        if (first) {
          msgs.append(":");
          first = false;
        }
        msgs.append(" ").append(LabelVote.create(e.getKey(), e.getValue()).format());
      }
    }
    return msgs.toString();
  }
}
