// 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.base.Strings;
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.collect.Streams;
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.approval.ApprovalCopier.ApprovalCopyResult;
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) {
    requireNonNull(approvalCopierResult, "approvalCopierResult");

    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()));
    }
    if (!approvalCopierResult.outdatedApprovals().isEmpty()) {
      if (!approvalCopierResult.copiedApprovals().isEmpty()) {
        message.append("\n");
      }
      message.append("Outdated Votes:\n");
      message.append(formatApprovalListWithCopyCondition(approvalCopierResult.outdatedApprovals()));
    }

    if (Streams.concat(
            approvalCopierResult.copiedApprovals().stream(),
            approvalCopierResult.outdatedApprovals().stream())
        .anyMatch(
            a ->
                !Strings.isNullOrEmpty(a.approvalCopyResult().copyEnforcement())
                    || !Strings.isNullOrEmpty(a.approvalCopyResult().copyRestriction()))) {
      message.append(
          "\n"
              + "\\* The label has `labelCopyEnforcement` or `labelCopyRestriction` configured."
              + " Only the most relevant condition that determined the outcome is shown.\n");
    }

    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> (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
   * @return bullet list with the formatted approvals
   */
  private String formatApprovalListWithCopyCondition(
      ImmutableSet<ApprovalCopier.Result.PatchSetApprovalData> approvalDatas) {
    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()) {
      Collection<ApprovalCopier.Result.PatchSetApprovalData> approvalsForSameLabel =
          approvalsByLabelEntry.getValue();

      // 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, a -> a.approvalCopyResult().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.approvalCopyResult().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))
            .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
   * @return the formatted approvals
   */
  private String formatApprovalsWithCopyCondition(
      Collection<ApprovalCopier.Result.PatchSetApprovalData>
          approvalsWithSameLabelAndSamePassingAndFailingAtoms) {
    // 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.approvalCopyResult().passingAtoms());
    checkThatPropertyIsTheSameForAllApprovals(
        approvalsWithSameLabelAndSamePassingAndFailingAtoms,
        "failing atoms",
        approvalData -> approvalData.approvalCopyResult().failingAtoms());

    ApprovalCopyResult copyResult =
        !approvalsWithSameLabelAndSamePassingAndFailingAtoms.isEmpty()
            ? approvalsWithSameLabelAndSamePassingAndFailingAtoms.stream()
                .findFirst()
                .get()
                .approvalCopyResult()
            : ApprovalCopyResult.createEvaluationSkipped();
    // In order to keep the message concise and understandable only show most relevant
    // copy condition and add an asterisk to show if forced conditions are present.
    String copyConditionName = "";
    String copyCondition = "";
    boolean showAsterisk =
        !Strings.isNullOrEmpty(copyResult.copyEnforcement())
            || !Strings.isNullOrEmpty(copyResult.copyRestriction());
    if (copyResult.canCopy() == copyResult.labelCopy()) {
      copyCondition = copyResult.labelCopyCondition();
      copyConditionName = "copy condition";
    } else if (!Strings.isNullOrEmpty(copyResult.copyEnforcement()) && copyResult.forcedCopy()) {
      copyCondition = copyResult.copyEnforcement();
      copyConditionName = "forced copy condition";
    } else if (!Strings.isNullOrEmpty(copyResult.copyRestriction()) && copyResult.forcedNonCopy()) {
      copyCondition = copyResult.copyRestriction();
      copyConditionName = "forced copy restriction";
    }

    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 %s%s: \"%s\")",
              copyConditionName, showAsterisk ? "\\*" : "", 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));
    }
    message.append(
        formatApprovalCopyResult(copyResult, copyConditionName, copyCondition, showAsterisk));
    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) {
    if (Strings.isNullOrEmpty(copyCondition)) {
      return "NEVER";
    }
    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();
  }

  /**
   * Formats the given copy condition as a Markdown string.
   *
   * <p>Passing atoms are formatted as bold.
   *
   * @param approvalCopyResult evaluation information for the copyCondition
   * @param copyConditionName name by which to refer to the copy condition string
   * @param copyCondition expression that was evaluated
   * @param showAsterisk if asterisk referring to forced copy conditions should be shown
   * @return the formatted copy condition as a Markdown string
   */
  private String formatApprovalCopyResult(
      ApprovalCopyResult approvalCopyResult,
      String copyConditionName,
      String copyCondition,
      boolean showAsterisk) {
    return String.format(
        " (%s%s: \"%s\")",
        copyConditionName,
        showAsterisk ? "\\*" : "",
        formatCopyConditionAsMarkdown(copyCondition, approvalCopyResult.passingAtoms()));
  }

  private boolean containsUserInPredicate(String copyCondition) throws QueryParseException {
    if (Strings.isNullOrEmpty(copyCondition)) {
      return false;
    }
    // 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();
  }
}
