// Copyright (C) 2022 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.restapi.change;

import static com.google.common.base.MoreObjects.firstNonNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.gerrit.entities.Patch.PATCHSET_LEVEL;
import static com.google.gerrit.server.notedb.ReviewerStateInternal.REVIEWER;
import static java.util.Comparator.comparing;
import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toSet;

import com.google.auto.value.AutoValue;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Joiner;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableTable;
import com.google.common.collect.MultimapBuilder;
import com.google.common.collect.SortedSetMultimap;
import com.google.common.collect.Streams;
import com.google.common.collect.Table.Cell;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.Comment;
import com.google.gerrit.entities.HumanComment;
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.RobotComment;
import com.google.gerrit.extensions.api.changes.ReviewInput;
import com.google.gerrit.extensions.api.changes.ReviewInput.CommentInput;
import com.google.gerrit.extensions.api.changes.ReviewInput.DraftHandling;
import com.google.gerrit.extensions.api.changes.ReviewInput.RobotCommentInput;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
import com.google.gerrit.extensions.restapi.Url;
import com.google.gerrit.extensions.validators.CommentForValidation;
import com.google.gerrit.extensions.validators.CommentValidationContext;
import com.google.gerrit.extensions.validators.CommentValidationFailure;
import com.google.gerrit.extensions.validators.CommentValidator;
import com.google.gerrit.server.ChangeMessagesUtil;
import com.google.gerrit.server.CommentsUtil;
import com.google.gerrit.server.DraftCommentsReader;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.PatchSetUtil;
import com.google.gerrit.server.PublishCommentUtil;
import com.google.gerrit.server.approval.ApprovalCopier;
import com.google.gerrit.server.approval.ApprovalsUtil;
import com.google.gerrit.server.change.EmailReviewComments;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.extensions.events.CommentAdded;
import com.google.gerrit.server.logging.Metadata;
import com.google.gerrit.server.logging.TraceContext;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.notedb.ChangeUpdate;
import com.google.gerrit.server.plugincontext.PluginSetContext;
import com.google.gerrit.server.project.ProjectState;
import com.google.gerrit.server.restapi.change.PostReview.CommentSetEntry;
import com.google.gerrit.server.update.BatchUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
import com.google.gerrit.server.update.CommentsRejectedException;
import com.google.gerrit.server.update.PostUpdateContext;
import com.google.gerrit.server.util.LabelVote;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.eclipse.jgit.lib.Config;

public class PostReviewOp implements BatchUpdateOp {
  public interface Factory {
    PostReviewOp create(
        ProjectState projectState, PatchSet.Id psId, ReviewInput in, Account.Id reviewerId);
  }

  /**
   * Update of a copied label that has been performed on a follow-up patch set after a vote has been
   * applied on an outdated patch set (follow-up patch sets = all patch sets that are newer than the
   * outdated patch set on which the user voted).
   */
  @AutoValue
  abstract static class CopiedLabelUpdate {
    /**
     * Type of the update that has been performed for a copied vote on a follow-up patch set.
     *
     * <p>Whether the copied vote has been added
     *
     * <ul>
     *   <li>added to
     *   <li>updated on
     *   <li>removed from
     * </ul>
     *
     * a follow-up patch set.
     */
    enum Type {
      /** A copied vote was added. No copied vote existed for this label yet. */
      ADDED,

      /** An existing copied vote has been updated. */
      UPDATED,

      /** An existing copied vote has been removed. */
      REMOVED;
    }

    /** The ID of the (follow-up) patch set on which the copied label update has been performed. */
    abstract PatchSet.Id patchSetId();

    /**
     * The old copied label vote that has been updated or that has been removed.
     *
     * <p>Not set if {@link #type()} is {@link Type#ADDED}.
     */
    abstract Optional<LabelVote> oldLabelVote();

    /**
     * The type of the update that has been performed for the copied vote on the (follow-up) patch
     * set.
     */
    abstract Type type();

    /** Returns a string with the patch set number and if present the old label vote. */
    private String formatPatchSetWithOldLabelVote() {
      StringBuilder b = new StringBuilder();
      b.append(patchSetId().get());
      if (oldLabelVote().isPresent()) {
        b.append(" (was ").append(oldLabelVote().get().format()).append(")");
      }
      return b.toString();
    }

    private static CopiedLabelUpdate added(PatchSet.Id patchSetId) {
      return create(patchSetId, Optional.empty(), Type.ADDED);
    }

    private static CopiedLabelUpdate updated(PatchSet.Id patchSetId, LabelVote oldLabelVote) {
      return create(patchSetId, Optional.of(oldLabelVote), Type.UPDATED);
    }

    private static CopiedLabelUpdate removed(PatchSet.Id patchSetId, LabelVote oldLabelVote) {
      return create(patchSetId, Optional.of(oldLabelVote), Type.REMOVED);
    }

    private static CopiedLabelUpdate create(
        PatchSet.Id patchSetId, Optional<LabelVote> oldLabelVote, Type type) {
      return new AutoValue_PostReviewOp_CopiedLabelUpdate(patchSetId, oldLabelVote, type);
    }
  }

  @AutoValue
  public abstract static class Result {
    /**
     * Whether this {@code PostReviewOp} updated any vote on the current patch set.
     *
     * @return returns {@code true} if a) ReviewInput contained votes and b) ReviewInput was applied
     *     on the current patch set or any votes got copied to the current patch set.
     */
    abstract boolean updatedAnyVoteOnCurrentPatchSet();

    /**
     * Whether this {@code PostReviewOp} applied any negative vote on the current patch set.
     *
     * @return returns {@code true} if a) ReviewInput contained negative votes and b) ReviewInput
     *     was applied on the current patch set or any of the negative votes got copied to the
     *     current patch set.
     */
    abstract boolean updatedAnyNegativeVoteOnCurrentPatchSet();

    /**
     * Whether this {@code PostReviewOp} applied votes on an outdated patch set that were not copied
     * to the current patch set.
     *
     * @return returns {@code true} if a) ReviewInput contained votes, b) ReviewInput was applied on
     *     an outdated patch set and c) not all of the votes got copied to the current patch set
     */
    abstract boolean appliedVotesOnOutdatedPatchSetThatWereNotCopiedToCurrentPatchSet();

    /**
     * Whether this {@code PostReviewOp} posted a change message.
     *
     * @return returns {@code true} if ReviewInput contained a message.
     */
    abstract boolean postedChangeMessage();

    static Result create(
        boolean updatedAnyVoteOnCurrentPatchSet,
        boolean updatedAnyNegativeVoteOnCurrentPatchSet,
        boolean appliedVotesOnOutdatedPatchSetThatWereNotCopiedToCurrentPatchSet,
        boolean postedChangeMessage) {
      return new AutoValue_PostReviewOp_Result(
          updatedAnyVoteOnCurrentPatchSet,
          updatedAnyNegativeVoteOnCurrentPatchSet,
          appliedVotesOnOutdatedPatchSetThatWereNotCopiedToCurrentPatchSet,
          postedChangeMessage);
    }
  }

  @VisibleForTesting
  public static final String START_REVIEW_MESSAGE = "This change is ready for review.";

  private final ApprovalCopier approvalCopier;
  private final ApprovalsUtil approvalsUtil;
  private final ChangeMessagesUtil cmUtil;
  private final CommentsUtil commentsUtil;
  private final DraftCommentsReader draftCommentsReader;
  private final PublishCommentUtil publishCommentUtil;
  private final PatchSetUtil psUtil;
  private final EmailReviewComments.Factory email;
  private final CommentAdded commentAdded;
  private final PluginSetContext<CommentValidator> commentValidators;
  private final PluginSetContext<OnPostReview> onPostReviews;

  private final ProjectState projectState;
  private final PatchSet.Id psId;
  private final ReviewInput in;
  private final Account.Id reviewerId;
  private final boolean publishPatchSetLevelComment;

  private IdentifiedUser user;
  private ChangeNotes notes;
  private PatchSet ps;
  private String mailMessage;
  private List<Comment> comments = new ArrayList<>();
  private List<LabelVote> labelDelta = new ArrayList<>();
  private SortedSetMultimap<LabelVote, CopiedLabelUpdate> labelUpdatesOnFollowUpPatchSets =
      MultimapBuilder.hashKeys().treeSetValues(comparing(CopiedLabelUpdate::patchSetId)).build();
  private Map<String, Short> approvals = new HashMap<>();
  private Map<String, Short> oldApprovals = new HashMap<>();

  private Result result;

  @Inject
  PostReviewOp(
      @GerritServerConfig Config gerritConfig,
      ApprovalCopier approvalCopier,
      ApprovalsUtil approvalsUtil,
      ChangeMessagesUtil cmUtil,
      CommentsUtil commentsUtil,
      DraftCommentsReader draftCommentsReader,
      PublishCommentUtil publishCommentUtil,
      PatchSetUtil psUtil,
      EmailReviewComments.Factory email,
      CommentAdded commentAdded,
      PluginSetContext<CommentValidator> commentValidators,
      PluginSetContext<OnPostReview> onPostReviews,
      @Assisted ProjectState projectState,
      @Assisted PatchSet.Id psId,
      @Assisted ReviewInput in,
      @Assisted Account.Id reviewerId) {
    this.approvalCopier = approvalCopier;
    this.approvalsUtil = approvalsUtil;
    this.publishCommentUtil = publishCommentUtil;
    this.psUtil = psUtil;
    this.cmUtil = cmUtil;
    this.commentsUtil = commentsUtil;
    this.draftCommentsReader = draftCommentsReader;
    this.email = email;
    this.commentAdded = commentAdded;
    this.commentValidators = commentValidators;
    this.onPostReviews = onPostReviews;
    this.publishPatchSetLevelComment =
        gerritConfig.getBoolean("event", "comment-added", "publishPatchSetLevelComment", true);

    this.projectState = projectState;
    this.psId = psId;
    this.in = in;
    this.reviewerId = reviewerId;
  }

  @Override
  public boolean updateChange(ChangeContext ctx)
      throws ResourceConflictException, UnprocessableEntityException, IOException,
          CommentsRejectedException {
    user = ctx.getIdentifiedUser();
    notes = ctx.getNotes();
    ps = psUtil.get(ctx.getNotes(), psId);
    List<RobotComment> newRobotComments =
        in.robotComments == null ? ImmutableList.of() : getNewRobotComments(ctx);
    boolean dirty = false;
    try (TraceContext.TraceTimer ignored = newTimer("insertComments")) {
      dirty |= insertComments(ctx, newRobotComments);
    }
    try (TraceContext.TraceTimer ignored = newTimer("insertRobotComments")) {
      dirty |= insertRobotComments(ctx, newRobotComments);
    }
    try (TraceContext.TraceTimer ignored = newTimer("updateLabels")) {
      dirty |= updateLabels(projectState, ctx);
    }
    try (TraceContext.TraceTimer ignored = newTimer("updateCopiedApprovals")) {
      dirty |= updateCopiedApprovalsOnFollowUpPatchSets(ctx);
    }
    try (TraceContext.TraceTimer ignored = newTimer("insertMessage")) {
      dirty |= insertMessage(ctx);
    }

    result =
        Result.create(
            updatedAnyVoteOnCurrentPatchSet(),
            updatedAnyNegativeVoteOnCurrentPatchSet(),
            appliedVotesOnOutdatedPatchSetThatWereNotCopiedToCurrentPatchSet(),
            postedChangeMessage());

    return dirty;
  }

  @Override
  public void postUpdate(PostUpdateContext ctx) {
    if (mailMessage == null) {
      return;
    }
    email
        .create(ctx, ps, notes.getMetaId(), mailMessage, comments, in.message, labelDelta)
        .sendAsync();
    String comment = mailMessage;
    if (publishPatchSetLevelComment) {
      // TODO(davido): Remove this workaround when patch set level comments are exposed in comment
      // added event. For backwards compatibility, patchset level comment has a higher priority
      // than change message and should be used as comment in comment added event.
      String patchSetLevelComment =
          comments.stream()
              .filter(c -> c.key.filename.equals(PATCHSET_LEVEL))
              .map(c -> Strings.nullToEmpty(c.message))
              .collect(Collectors.joining("\n"))
              .trim();
      if (!patchSetLevelComment.isEmpty()) {
        comment = String.format("Patch Set %s:\n\n%s", psId.get(), patchSetLevelComment);
      }
    }
    commentAdded.fire(
        ctx.getChangeData(notes),
        ps,
        user.state(),
        comment,
        approvals,
        oldApprovals,
        ctx.getWhen());
  }

  /**
   * Publishes draft and input comments. Input comments are those passed as input in the request
   * body.
   *
   * @param ctx context for performing the change update.
   * @param newRobotComments robot comments. Used only for validation in this method.
   * @return true if any input comments where published.
   */
  private boolean insertComments(ChangeContext ctx, List<RobotComment> newRobotComments)
      throws CommentsRejectedException {
    Map<String, List<CommentInput>> inputComments = in.comments;
    if (inputComments == null) {
      inputComments = Collections.emptyMap();
    }

    // Use HashMap to avoid warnings when calling remove() in resolveInputCommentsAndDrafts().
    Map<String, HumanComment> drafts = new HashMap<>();

    if (!inputComments.isEmpty() || in.drafts != DraftHandling.KEEP) {
      drafts =
          in.drafts == DraftHandling.PUBLISH_ALL_REVISIONS
              ? changeDrafts(ctx)
              : patchSetDrafts(ctx);
    }

    // Existing published comments
    Set<CommentSetEntry> existingComments =
        in.omitDuplicateComments ? readExistingComments(ctx) : Collections.emptySet();

    // Input comments should be deduplicated from existing drafts
    List<HumanComment> inputCommentsToPublish =
        resolveInputCommentsAndDrafts(inputComments, existingComments, drafts, ctx);

    switch (in.drafts) {
      case PUBLISH:
      case PUBLISH_ALL_REVISIONS:
        Collection<HumanComment> filteredDrafts =
            in.draftIdsToPublish == null
                ? drafts.values()
                : drafts.values().stream()
                    .filter(draft -> in.draftIdsToPublish.contains(draft.key.uuid))
                    .collect(Collectors.toList());

        validateComments(
            ctx,
            Streams.concat(
                drafts.values().stream(),
                inputCommentsToPublish.stream(),
                newRobotComments.stream()));
        publishCommentUtil.publish(ctx, ctx.getUpdate(psId), filteredDrafts, in.tag);
        comments.addAll(drafts.values());
        break;
      case KEEP:
        validateComments(
            ctx, Streams.concat(inputCommentsToPublish.stream(), newRobotComments.stream()));
        break;
    }
    commentsUtil.putHumanComments(
        ctx.getUpdate(psId), HumanComment.Status.PUBLISHED, inputCommentsToPublish);
    comments.addAll(inputCommentsToPublish);
    return !inputCommentsToPublish.isEmpty();
  }

  /**
   * Returns the subset of {@code inputComments} that should be added to the change.
   *
   * <p>If the matching comment (with the same id) already exists in {@code existingComments} then
   * the comment is filtered out. This assumes that the comment has been already published earlier.
   *
   * <p>If the matching comment is found in {@code drafts}, then it's removed from drafts and the
   * comment is kept in the output. This assumes that the comment in the input is the newer version
   * of the previously existing draft.
   *
   * @param inputComments new comments provided as {@link CommentInput} entries in the API.
   * @param existingComments existing published comments in the database.
   * @param drafts existing draft comments in the database. This map can be modified.
   */
  private List<HumanComment> resolveInputCommentsAndDrafts(
      Map<String, List<CommentInput>> inputComments,
      Set<CommentSetEntry> existingComments,
      Map<String, HumanComment> drafts,
      ChangeContext ctx) {
    List<HumanComment> inputCommentsToPublish = new ArrayList<>();
    for (Map.Entry<String, List<CommentInput>> entry : inputComments.entrySet()) {
      String path = entry.getKey();
      for (CommentInput inputComment : entry.getValue()) {
        HumanComment comment = drafts.remove(Url.decode(inputComment.id));
        if (comment == null) {
          String parent = Url.decode(inputComment.inReplyTo);
          comment =
              commentsUtil.newHumanComment(
                  ctx.getNotes(),
                  ctx.getUser(),
                  ctx.getWhen(),
                  path,
                  psId,
                  inputComment.side(),
                  inputComment.message,
                  inputComment.unresolved,
                  parent,
                  CommentsUtil.createFixSuggestionsFromInput(inputComment.fixSuggestions));
        } else {
          // In ChangeUpdate#putDraftComment() the draft with the same ID will be deleted.
          comment.writtenOn = Timestamp.from(ctx.getWhen());
          comment.side = inputComment.side();
          comment.message = inputComment.message;
          comment.unresolved = inputComment.unresolved;
        }

        commentsUtil.setCommentCommitId(comment, ctx.getChange(), ps);
        comment.setLineNbrAndRange(inputComment.line, inputComment.range);
        comment.tag = in.tag;

        if (existingComments.contains(CommentSetEntry.create(comment))) {
          continue;
        }
        inputCommentsToPublish.add(comment);
      }
    }
    return inputCommentsToPublish;
  }

  /**
   * Validates all comments and the change message in a single call to fulfill the interface
   * contract of {@link CommentValidator#validateComments(CommentValidationContext, ImmutableList)}.
   */
  private void validateComments(ChangeContext ctx, Stream<? extends Comment> comments)
      throws CommentsRejectedException {
    CommentValidationContext commentValidationCtx =
        CommentValidationContext.create(
            ctx.getChange().getChangeId(),
            ctx.getChange().getProject().get(),
            ctx.getChange().getDest().branch());
    String changeMessage = Strings.nullToEmpty(in.message).trim();
    ImmutableList<CommentForValidation> draftsForValidation =
        Stream.concat(
                comments.map(
                    comment ->
                        CommentForValidation.create(
                            comment instanceof RobotComment
                                ? CommentForValidation.CommentSource.ROBOT
                                : CommentForValidation.CommentSource.HUMAN,
                            comment.lineNbr > 0
                                ? CommentForValidation.CommentType.INLINE_COMMENT
                                : CommentForValidation.CommentType.FILE_COMMENT,
                            comment.message,
                            comment.getApproximateSize())),
                Stream.of(
                    CommentForValidation.create(
                        CommentForValidation.CommentSource.HUMAN,
                        CommentForValidation.CommentType.CHANGE_MESSAGE,
                        changeMessage,
                        changeMessage.length())))
            .collect(toImmutableList());
    ImmutableList<CommentValidationFailure> draftValidationFailures =
        PublishCommentUtil.findInvalidComments(
            commentValidationCtx, commentValidators, draftsForValidation);
    if (!draftValidationFailures.isEmpty()) {
      throw new CommentsRejectedException(draftValidationFailures);
    }
  }

  private boolean insertRobotComments(ChangeContext ctx, List<RobotComment> newRobotComments) {
    if (in.robotComments == null) {
      return false;
    }
    commentsUtil.putRobotComments(ctx.getUpdate(psId), newRobotComments);
    comments.addAll(newRobotComments);
    return !newRobotComments.isEmpty();
  }

  private List<RobotComment> getNewRobotComments(ChangeContext ctx) {
    List<RobotComment> toAdd = new ArrayList<>(in.robotComments.size());

    Set<CommentSetEntry> existingIds =
        in.omitDuplicateComments ? readExistingRobotComments(ctx) : Collections.emptySet();

    for (Map.Entry<String, List<RobotCommentInput>> ent : in.robotComments.entrySet()) {
      String path = ent.getKey();
      for (RobotCommentInput c : ent.getValue()) {
        RobotComment e = createRobotCommentFromInput(ctx, path, c);
        if (existingIds.contains(CommentSetEntry.create(e))) {
          continue;
        }
        toAdd.add(e);
      }
    }
    return toAdd;
  }

  private RobotComment createRobotCommentFromInput(
      ChangeContext ctx, String path, RobotCommentInput robotCommentInput) {
    RobotComment robotComment =
        commentsUtil.newRobotComment(
            ctx,
            path,
            psId,
            robotCommentInput.side(),
            robotCommentInput.message,
            robotCommentInput.robotId,
            robotCommentInput.robotRunId);
    robotComment.parentUuid = Url.decode(robotCommentInput.inReplyTo);
    robotComment.url = robotCommentInput.url;
    robotComment.properties = robotCommentInput.properties;
    robotComment.setLineNbrAndRange(robotCommentInput.line, robotCommentInput.range);
    robotComment.tag = in.tag;
    commentsUtil.setCommentCommitId(robotComment, ctx.getChange(), ps);
    robotComment.fixSuggestions =
        CommentsUtil.createFixSuggestionsFromInput(robotCommentInput.fixSuggestions);
    return robotComment;
  }

  private Set<CommentSetEntry> readExistingComments(ChangeContext ctx) {
    return commentsUtil.publishedHumanCommentsByChange(ctx.getNotes()).stream()
        .map(CommentSetEntry::create)
        .collect(toSet());
  }

  private Set<CommentSetEntry> readExistingRobotComments(ChangeContext ctx) {
    return commentsUtil.robotCommentsByChange(ctx.getNotes()).stream()
        .map(CommentSetEntry::create)
        .collect(toSet());
  }

  private Map<String, HumanComment> changeDrafts(ChangeContext ctx) {
    return draftCommentsReader.getDraftsByChangeAndDraftAuthor(ctx.getNotes(), user.getAccountId())
        .stream()
        .collect(Collectors.toMap(c -> c.key.uuid, c -> c));
  }

  private Map<String, HumanComment> patchSetDrafts(ChangeContext ctx) {
    return draftCommentsReader
        .getDraftsByPatchSetAndDraftAuthor(ctx.getNotes(), psId, user.getAccountId()).stream()
        .collect(Collectors.toMap(c -> c.key.uuid, c -> c));
  }

  private Map<String, Short> approvalsByKey(Collection<PatchSetApproval> patchsetApprovals) {
    Map<String, Short> labels = new HashMap<>();
    for (PatchSetApproval psa : patchsetApprovals) {
      labels.put(psa.label(), psa.value());
    }
    return labels;
  }

  private Map<String, Short> getAllApprovals(
      LabelTypes labelTypes, Map<String, Short> current, Map<String, Short> input) {
    Map<String, Short> allApprovals = new HashMap<>();
    for (LabelType lt : labelTypes.getLabelTypes()) {
      allApprovals.put(lt.getName(), (short) 0);
    }
    // set approvals to existing votes
    if (current != null) {
      allApprovals.putAll(current);
    }
    // set approvals to new votes
    if (input != null) {
      allApprovals.putAll(input);
    }
    return allApprovals;
  }

  private Map<String, Short> getPreviousApprovals(
      Map<String, Short> allApprovals, Map<String, Short> current) {
    Map<String, Short> previous = new HashMap<>();
    for (Map.Entry<String, Short> approval : allApprovals.entrySet()) {
      // assume vote is 0 if there is no vote
      if (!current.containsKey(approval.getKey())) {
        previous.put(approval.getKey(), (short) 0);
      } else {
        previous.put(approval.getKey(), current.get(approval.getKey()));
      }
    }
    return previous;
  }

  private boolean isReviewer(ChangeContext ctx) {
    return approvalsUtil
        .getReviewers(ctx.getNotes())
        .byState(REVIEWER)
        .contains(ctx.getAccountId());
  }

  private boolean updateLabels(ProjectState projectState, ChangeContext ctx)
      throws ResourceConflictException {
    Map<String, Short> inLabels = firstNonNull(in.labels, Collections.emptyMap());

    // If no labels were modified and change is closed, abort early.
    // This avoids trying to record a modified label caused by a user
    // losing access to a label after the change was submitted.
    if (inLabels.isEmpty() && ctx.getChange().isClosed()) {
      return false;
    }

    List<PatchSetApproval> del = new ArrayList<>();
    List<PatchSetApproval> ups = new ArrayList<>();
    Map<String, PatchSetApproval> current = scanLabels(projectState, ctx, del);
    LabelTypes labelTypes = projectState.getLabelTypes(ctx.getNotes());
    Map<String, Short> allApprovals =
        getAllApprovals(labelTypes, approvalsByKey(current.values()), inLabels);
    Map<String, Short> previous =
        getPreviousApprovals(allApprovals, approvalsByKey(current.values()));

    ChangeUpdate update = ctx.getUpdate(psId);
    for (Map.Entry<String, Short> ent : allApprovals.entrySet()) {
      String name = ent.getKey();
      LabelType lt =
          labelTypes
              .byLabel(name)
              .orElseThrow(() -> new IllegalStateException("no label config for " + name));

      PatchSetApproval c = current.remove(lt.getName());
      String normName = lt.getName();
      approvals.put(normName, (short) 0);
      if (ent.getValue() == null || ent.getValue() == 0) {
        // User requested delete of this label.
        oldApprovals.put(normName, null);
        if (c != null) {
          if (c.value() != 0) {
            addLabelDelta(normName, (short) 0);
            oldApprovals.put(normName, previous.get(normName));
          }
          del.add(c);
          update.putApproval(normName, (short) 0);
        }
        // Only allow voting again if the values are different, if the real account differs or if
        // the vote is copied over from a past patch-set.
      } else if (c != null
          && (c.value() != ent.getValue()
              || !c.realAccountId().equals(reviewerId)
              || (inLabels.containsKey(c.label()) && isApprovalCopiedOver(c, ctx.getNotes())))) {
        PatchSetApproval.Builder b =
            c.toBuilder()
                .value(ent.getValue())
                .granted(ctx.getWhen())
                .tag(Optional.ofNullable(in.tag));
        ctx.getUser().updateRealAccountId(b::realAccountId);
        c = b.build();
        ups.add(c);
        addLabelDelta(normName, c.value());
        oldApprovals.put(normName, previous.get(normName));
        approvals.put(normName, c.value());
        update.putApproval(normName, ent.getValue());
      } else if (c != null && c.value() == ent.getValue()) {
        current.put(normName, c);
        oldApprovals.put(normName, null);
        approvals.put(normName, c.value());
      } else if (c == null) {
        c =
            ApprovalsUtil.newApproval(psId, user, lt.getLabelId(), ent.getValue(), ctx.getWhen())
                .tag(Optional.ofNullable(in.tag))
                .granted(ctx.getWhen())
                .build();
        ups.add(c);
        addLabelDelta(normName, c.value());
        oldApprovals.put(normName, previous.get(normName));
        approvals.put(normName, c.value());
        update.putApproval(normName, ent.getValue());

        // Votes may be applied on outdated patch sets, using a ChangeUpdate that was created for
        // the outdated patch set. Reviewers however cannot be added on outdated patch sets, but
        // only on the change. This means reviewers should always be added using a ChangeUpdate
        // that was created for the current patch set.
        // This is important so that updates on the current patch set that are done by other ops
        // within the same BatchUpdate after this PostReviewOp was executed can see the reviewer
        // updates. E.g. the AddToAttentionSetOp, that updates the attention set on the current
        // patch set, needs to see newly added reviewers, as otherwise attention set updates for
        // these reviewers are dropped (ChangeUpdate#updateAttentionSet drops attention set updates
        // for users that are not active on the change, i.e. for users that are neither change
        // owner, uploader nor reviewer).
        ctx.getUpdate(notes.getChange().currentPatchSetId())
            .putReviewer(user.getAccountId(), REVIEWER);
      }
    }

    validatePostSubmitLabels(ctx, labelTypes, previous, ups, del);

    // Return early if user is not a reviewer and not posting any labels.
    // This allows us to preserve their CC status.
    if (current.isEmpty() && del.isEmpty() && ups.isEmpty() && !isReviewer(ctx)) {
      return false;
    }

    return !del.isEmpty() || !ups.isEmpty();
  }

  /** Approval is copied over if it doesn't exist in the approvals of the current patch-set. */
  private boolean isApprovalCopiedOver(PatchSetApproval patchSetApproval, ChangeNotes changeNotes) {
    return !changeNotes.getApprovals().onlyNonCopied()
        .get(changeNotes.getChange().currentPatchSetId()).stream()
        .anyMatch(p -> p.equals(patchSetApproval));
  }

  private void validatePostSubmitLabels(
      ChangeContext ctx,
      LabelTypes labelTypes,
      Map<String, Short> previous,
      List<PatchSetApproval> ups,
      List<PatchSetApproval> del)
      throws ResourceConflictException {
    if (ctx.getChange().isNew()) {
      return; // Not closed, nothing to validate.
    } else if (del.isEmpty() && ups.isEmpty()) {
      return; // No new votes.
    } else if (!ctx.getChange().isMerged()) {
      throw new ResourceConflictException("change is closed");
    }

    // Disallow reducing votes on any labels post-submit. This assumes the
    // high values were broadly necessary to submit, so reducing them would
    // make it possible to take a merged change and make it no longer
    // submittable.
    List<PatchSetApproval> reduced = new ArrayList<>(ups.size() + del.size());
    List<String> disallowed = new ArrayList<>(labelTypes.getLabelTypes().size());

    for (PatchSetApproval psa : del) {
      LabelType lt =
          labelTypes
              .byLabel(psa.label())
              .orElseThrow(() -> new IllegalStateException("no label config for " + psa.label()));
      String normName = lt.getName();
      if (!lt.isAllowPostSubmit()) {
        disallowed.add(normName);
      }
      Short prev = previous.get(normName);
      if (prev != null && prev != 0) {
        reduced.add(psa);
      }
    }

    for (PatchSetApproval psa : ups) {
      LabelType lt =
          labelTypes
              .byLabel(psa.label())
              .orElseThrow(() -> new IllegalStateException("no label config for " + psa.label()));
      String normName = lt.getName();
      if (!lt.isAllowPostSubmit()) {
        disallowed.add(normName);
      }
      Short prev = previous.get(normName);
      if (prev == null) {
        continue;
      }
      if (prev > psa.value()) {
        reduced.add(psa);
      }
      // No need to set postSubmit bit, which is set automatically when parsing from NoteDb.
    }

    if (!disallowed.isEmpty()) {
      throw new ResourceConflictException(
          "Voting on labels disallowed after submit: "
              + disallowed.stream().distinct().sorted().collect(joining(", ")));
    }
    if (!reduced.isEmpty()) {
      throw new ResourceConflictException(
          "Cannot reduce vote on labels for closed change: "
              + reduced.stream()
                  .map(PatchSetApproval::label)
                  .distinct()
                  .sorted()
                  .collect(joining(", ")));
    }
  }

  private Map<String, PatchSetApproval> scanLabels(
      ProjectState projectState, ChangeContext ctx, List<PatchSetApproval> del) {
    LabelTypes labelTypes = projectState.getLabelTypes(ctx.getNotes());
    Map<String, PatchSetApproval> current = new HashMap<>();

    for (PatchSetApproval a :
        approvalsUtil.byPatchSetUser(ctx.getNotes(), psId, user.getAccountId())) {
      if (a.isLegacySubmit()) {
        continue;
      }

      Optional<LabelType> lt = labelTypes.byLabel(a.labelId());
      if (lt.isPresent()) {
        current.put(lt.get().getName(), a);
      } else {
        del.add(a);
      }
    }
    return current;
  }

  /**
   * Copies approvals that have been newly applied on outdated patch sets to the follow-up patch
   * sets if they are copyable and no non-copied approvals prevent the copying.
   *
   * <p>Must be invoked after the new approvals on outdated patch sets have been applied (e.g. after
   * {@link #updateLabels(ProjectState, ChangeContext)}.
   *
   * @param ctx the change context
   * @return {@code true} if an update was done, otherwise {@code false}
   */
  private boolean updateCopiedApprovalsOnFollowUpPatchSets(ChangeContext ctx) throws IOException {
    if (ctx.getNotes().getCurrentPatchSet().id().equals(psId)) {
      // the updated patch set is the current patch, there a no follow-up patch set to which new
      // approvals could be copied
      return false;
    }

    // compute follow-up patch sets (sorted by patch set ID)
    ImmutableList<PatchSet.Id> followUpPatchSets =
        ctx.getNotes().getPatchSets().keySet().stream()
            .filter(patchSetId -> patchSetId.get() > psId.get())
            .collect(toImmutableList());

    boolean dirty = false;
    ImmutableTable<String, Account.Id, Optional<PatchSetApproval>> newApprovals =
        ctx.getUpdate(psId).getApprovals();
    for (Cell<String, Account.Id, Optional<PatchSetApproval>> cell : newApprovals.cellSet()) {
      PatchSetApproval psaOrig = cell.getValue().get();

      if (isRemoval(cell)) {
        if (removeCopies(ctx, followUpPatchSets, psaOrig)) {
          dirty = true;
        }
        continue;
      }

      PatchSet patchSet = psUtil.get(ctx.getNotes(), psId);

      // Target patch sets to which the approval is copyable.
      ImmutableList<PatchSet.Id> targetPatchSets =
          approvalCopier.forApproval(
              ctx.getNotes(), patchSet, psaOrig.accountId(), psaOrig.label(), psaOrig.value());

      // Iterate over all follow-up patch sets, in patch set order.
      for (PatchSet.Id followUpPatchSetId : followUpPatchSets) {
        if (hasOverrideOf(ctx, followUpPatchSetId, psaOrig.key())) {
          // a non-copied approval exists that overrides any copied approval
          // -> do not copy the approval to this patch set nor to any follow-up patch sets
          break;
        }

        if (targetPatchSets.contains(followUpPatchSetId)) {
          // The approval is copyable to the new patch set.

          if (hasCopyOfWithValue(ctx, followUpPatchSetId, psaOrig)) {
            // a copy approval with the exact value already exists
            continue;
          }

          // add/update the copied approval on the target patch set
          Optional<PatchSetApproval> copiedPsa = getCopyOf(ctx, followUpPatchSetId, psaOrig.key());
          PatchSetApproval copiedPatchSetApproval = psaOrig.copyWithPatchSet(followUpPatchSetId);
          ctx.getUpdate(followUpPatchSetId).putCopiedApproval(copiedPatchSetApproval);
          labelUpdatesOnFollowUpPatchSets.put(
              LabelVote.createFrom(psaOrig),
              copiedPsa.isPresent()
                  ? CopiedLabelUpdate.updated(
                      followUpPatchSetId, LabelVote.createFrom(copiedPsa.get()))
                  : CopiedLabelUpdate.added(followUpPatchSetId));
          dirty = true;
        } else {
          // The approval is not copyable to the new patch set.
          Optional<PatchSetApproval> copiedPsa = getCopyOf(ctx, followUpPatchSetId, psaOrig.key());
          if (copiedPsa.isPresent()) {
            // a copy approval exists and should be removed
            removeCopy(ctx, psaOrig, copiedPsa.get());
            dirty = true;
          }
        }
      }
    }

    return dirty;
  }

  /**
   * Whether the given cell entry from the approval table represents the removal of an approval.
   *
   * @param cell cell entry from the approval table
   * @return {@code true} if the approval is not set or the approval has {@code 0} as the value,
   *     otherwise {@code false}
   */
  private boolean isRemoval(Cell<String, Account.Id, Optional<PatchSetApproval>> cell) {
    return cell.getValue().isEmpty() || cell.getValue().get().value() == 0;
  }

  /**
   * Removes copies of the given approval from all follow-up patch sets.
   *
   * @param ctx the change context
   * @param followUpPatchSets the follow-up patch sets of the patch set on which the review is
   *     posted
   * @param psaOrig the original patch set approval for which copies should be removed from all
   *     follow-up patch sets
   * @return whether any copy approval has been removed
   */
  private boolean removeCopies(
      ChangeContext ctx, ImmutableList<PatchSet.Id> followUpPatchSets, PatchSetApproval psaOrig) {
    boolean dirty = false;
    for (PatchSet.Id followUpPatchSet : followUpPatchSets) {
      Optional<PatchSetApproval> copiedPsa = getCopyOf(ctx, followUpPatchSet, psaOrig.key());
      if (copiedPsa.isPresent()) {
        removeCopy(ctx, psaOrig, copiedPsa.get());
      } else {
        // Do not remove copy from this follow-up patch sets and also not from any further follow-up
        // patch sets (if the further follow-up patch sets have copies they are copies of a
        // non-copied approval on this follow-up patch set and hence those should not be removed).
        break;
      }
    }
    return dirty;
  }

  /**
   * Removes the copy approval with the given key from the given patch set.
   *
   * @param ctx the change context
   * @param psaOrig the original patch set approval for which copies should be removed from the
   *     given patch set
   * @param copiedPsa the copied patch set approval that should be removed
   */
  private void removeCopy(ChangeContext ctx, PatchSetApproval psaOrig, PatchSetApproval copiedPsa) {
    ctx.getUpdate(copiedPsa.patchSetId())
        .removeCopiedApprovalFor(
            ctx.getIdentifiedUser().getRealUser().isIdentifiedUser()
                ? ctx.getIdentifiedUser().getRealUser().getAccountId()
                : null,
            copiedPsa.accountId(),
            copiedPsa.labelId().get());
    labelUpdatesOnFollowUpPatchSets.put(
        LabelVote.createFrom(psaOrig),
        CopiedLabelUpdate.removed(copiedPsa.patchSetId(), LabelVote.createFrom(copiedPsa)));
  }

  /**
   * Retrieves the copy of the given approval from the given patch set if it exists.
   *
   * @param ctx the change context
   * @param patchSetId the ID of the patch from which it the copied approval should be returned
   * @param psaKey the key of the patch set approval for which the copied approval should be
   *     returned
   * @return the copy of the given approval from the given patch set if it exists
   */
  private Optional<PatchSetApproval> getCopyOf(
      ChangeContext ctx, PatchSet.Id patchSetId, PatchSetApproval.Key psaKey) {
    return ctx.getNotes().getApprovals().onlyCopied().get(patchSetId).stream()
        .filter(psa -> areAccountAndLabelTheSame(psa.key(), psaKey))
        .findAny();
  }

  /**
   * Whether the given patch set has a copy approval with the given key and value.
   *
   * @param ctx the change context
   * @param patchSetId the ID of the patch for which it should be checked whether it has a copy
   *     approval with the given key and value
   * @param psaOrig the original patch set approval
   */
  private boolean hasCopyOfWithValue(
      ChangeContext ctx, PatchSet.Id patchSetId, PatchSetApproval psaOrig) {
    return ctx.getNotes().getApprovals().onlyCopied().get(patchSetId).stream()
        .anyMatch(
            psa ->
                areAccountAndLabelTheSame(psa.key(), psaOrig.key())
                    && psa.value() == psaOrig.value());
  }

  /**
   * Whether the given patch set has a normal approval with the given key that overrides copy
   * approvals with that key.
   *
   * @param ctx the change context
   * @param patchSetId the ID of the patch for which it should be checked whether it has a normal
   *     approval with the given key that overrides copy approvals with that key
   * @param psaKey the key of the patch set approval
   */
  private boolean hasOverrideOf(
      ChangeContext ctx, PatchSet.Id patchSetId, PatchSetApproval.Key psaKey) {
    return ctx.getNotes().getApprovals().onlyNonCopied().get(patchSetId).stream()
        .anyMatch(psa -> areAccountAndLabelTheSame(psa.key(), psaKey));
  }

  private boolean areAccountAndLabelTheSame(
      PatchSetApproval.Key psaKey1, PatchSetApproval.Key psaKey2) {
    return psaKey1.accountId().equals(psaKey2.accountId())
        && psaKey1.labelId().equals(psaKey2.labelId());
  }

  private boolean insertMessage(ChangeContext ctx) {
    String msg = Strings.nullToEmpty(in.message).trim();

    StringBuilder buf = new StringBuilder();
    for (String formattedLabelVote :
        labelDelta.stream().map(LabelVote::format).sorted().collect(toImmutableList())) {
      buf.append(" ").append(formattedLabelVote);
    }
    if (!labelUpdatesOnFollowUpPatchSets.isEmpty()) {
      buf.append("\n\nCopied votes on follow-up patch sets have been updated:");
      for (Map.Entry<LabelVote, Collection<CopiedLabelUpdate>> e :
          labelUpdatesOnFollowUpPatchSets.asMap().entrySet().stream()
              .sorted(Map.Entry.comparingByKey(comparing(LabelVote::label)))
              .collect(toImmutableList())) {
        Optional<String> copyCondition =
            projectState
                .getLabelTypes(ctx.getNotes())
                .byLabel(e.getKey().label())
                .map(LabelType::getCopyCondition)
                .map(Optional::get);
        buf.append(formatVotesCopiedToFollowUpPatchSets(e.getKey(), e.getValue(), copyCondition));
      }
    }
    if (comments.size() == 1) {
      buf.append("\n\n(1 comment)");
    } else if (comments.size() > 1) {
      buf.append(String.format("\n\n(%d comments)", comments.size()));
    }
    if (!msg.isEmpty()) {
      // Message was already validated when validating comments, since validators need to see
      // everything in a single call.
      buf.append("\n\n").append(msg);
    } else if (in.ready) {
      buf.append("\n\n" + START_REVIEW_MESSAGE);
    }

    List<String> pluginMessages = new ArrayList<>();
    onPostReviews.runEach(
        onPostReview ->
            onPostReview
                .getChangeMessageAddOn(
                    ctx.getWhen(), user, ctx.getNotes(), ps, oldApprovals, approvals)
                .ifPresent(
                    pluginMessage ->
                        pluginMessages.add(
                            !pluginMessage.endsWith("\n") ? pluginMessage + "\n" : pluginMessage)));
    if (!pluginMessages.isEmpty()) {
      buf.append("\n\n");
      buf.append(Joiner.on("\n").join(pluginMessages));
    }

    if (buf.length() == 0) {
      return false;
    }

    mailMessage =
        cmUtil.setChangeMessage(ctx.getUpdate(psId), "Patch Set " + psId.get() + ":" + buf, in.tag);
    return true;
  }

  /**
   * Given a label vote that has been applied on an outdated patch set, this method formats the
   * updates to the copied labels on the follow-up patch sets that have been performed for that
   * label vote.
   *
   * <p>If label votes have been copied to follow-up patch sets the formatted message is
   * "<label-vote> has been copied to patch sets: 3, 4 (copy condition: "<copy-condition>").".
   *
   * <p>If existing copied votes on follow-up patch sets have been updated, the old copied votes are
   * included into the message: "<label-vote> has been copied to patch sets: 3 (was
   * <old-label-vote>), 4 (was <old-label-vote>) (copy condition: "<copy-condition>").".
   *
   * <p>If existing copied votes on follow-up patch sets have been removed (because the new vote is
   * not copyable) the message is: "Copied <label> vote has been removed from patch set 3 (was
   * <old-label-vote>), 4 (was <old-label-vote>) (copy condition: "<copy-condition>").".
   *
   * <p>If copied votes have been both added/updated and removed, 2 messages are returned.
   *
   * <p>Each returned message is formatted as a list item (prefixed with '* ').
   *
   * <p>Passing atoms in copy conditions are not highlighted. This is because the passing atoms can
   * be different for different follow-up patch sets (e.g. 'changekind:TRIVIAL_REBASE OR
   * changekind:NO_CODE_CHANGE' can have 'changekind:TRIVIAL_REBASE' passing for one follow-up patch
   * set and 'changekind:NO_CODE_CHANGE' passing for another follow-up patch set). Including the
   * copy condition once per follow-up patch set with differently highlighted passing atoms would
   * make the message unreadable. Hence we don't highlight passing atoms here.
   *
   * @param labelVote the label vote that has been applied on an outdated patch set
   * @param followUpPatchSetUpdates updates to copied votes on follow-up patch sets that have been
   *     done by copying the label vote on the outdated patch set to follow-up patch sets
   * @param copyCondition the copy condition of the label for which a vote was applied on an
   *     outdated patch set
   * @return formatted string to be included into a change message
   */
  private String formatVotesCopiedToFollowUpPatchSets(
      LabelVote labelVote,
      Collection<CopiedLabelUpdate> followUpPatchSetUpdates,
      Optional<String> copyCondition) {
    StringBuilder b = new StringBuilder();

    // Add line for added/updated copied approvals.
    ImmutableList<CopiedLabelUpdate> additionsAndUpdates =
        followUpPatchSetUpdates.stream()
            .filter(
                copiedLabelUpdate ->
                    copiedLabelUpdate.type() == CopiedLabelUpdate.Type.ADDED
                        || copiedLabelUpdate.type() == CopiedLabelUpdate.Type.UPDATED)
            .collect(toImmutableList());
    if (!additionsAndUpdates.isEmpty()) {
      b.append("\n* ");
      b.append(labelVote.format());
      b.append(" has been copied to patch set ");
      b.append(
          additionsAndUpdates.stream()
              .map(CopiedLabelUpdate::formatPatchSetWithOldLabelVote)
              .collect(joining(", ")));
      copyCondition.ifPresent(cc -> b.append(" (copy condition: \"" + cc + "\")"));
      b.append(".");
    }

    // Add line for removed copied approvals.
    ImmutableList<CopiedLabelUpdate> removals =
        followUpPatchSetUpdates.stream()
            .filter(copiedLabelUpdate -> copiedLabelUpdate.type() == CopiedLabelUpdate.Type.REMOVED)
            .collect(toImmutableList());
    if (!removals.isEmpty()) {
      b.append("\n* Copied ");
      b.append(labelVote.label());
      b.append(" vote has been removed from patch set ");
      b.append(
          removals.stream()
              .map(CopiedLabelUpdate::formatPatchSetWithOldLabelVote)
              .collect(joining(", ")));
      b.append(" since the new ");
      b.append(labelVote.value() != 0 ? labelVote.format() : labelVote.formatWithEquals());
      b.append(" vote is not copyable");
      copyCondition.ifPresent(cc -> b.append(" (copy condition: \"" + cc + "\")"));
      b.append(".");
    }
    return b.toString();
  }

  private void addLabelDelta(String name, short value) {
    labelDelta.add(LabelVote.create(name, value));
  }

  /**
   * Gets the result of running this {@code PostReviewOp}.
   *
   * <p>Must only be invoked after this {@code PostReviewOp} has been executed with {@link
   * com.google.gerrit.server.update.BatchUpdate}.
   *
   * @throws IllegalStateException thrown if invoked before this {@code PostReviewOp} has been
   *     executed
   */
  public Result getResult() {
    checkState(result != null, "cannot retrieve result, change update has not been executed yet");
    return result;
  }

  /**
   * Whether this {@code PostReviewOp} updated any vote on the current patch set.
   *
   * <p>Must only be invoked after this {@code PostReviewOp} has been executed with {@link
   * com.google.gerrit.server.update.BatchUpdate}.
   *
   * @return returns {@code true} if a) ReviewInput contained votes and b) ReviewInput was applied
   *     on the current patch set or any votes got copied to the current patch set.
   */
  private boolean updatedAnyVoteOnCurrentPatchSet() {
    return in.labels != null
        && !in.labels.isEmpty()
        && (notes.getCurrentPatchSet().id().equals(psId)
            || labelUpdatesOnFollowUpPatchSets.values().stream()
                .anyMatch(
                    copiedLabelUpdate ->
                        copiedLabelUpdate.patchSetId().equals(notes.getCurrentPatchSet().id())));
  }

  /**
   * Whether this {@code PostReviewOp} applied any negative vote on the current patch set.
   *
   * <p>Must only be invoked after this {@code PostReviewOp} has been executed with {@link
   * com.google.gerrit.server.update.BatchUpdate}.
   *
   * @return returns {@code true} if a) ReviewInput contained negative votes and b) ReviewInput was
   *     applied on the current patch set or any of the negative votes got copied to the current
   *     patch set.
   */
  private boolean updatedAnyNegativeVoteOnCurrentPatchSet() {
    return in.labels != null
        && in.labels.values().stream().anyMatch(vote -> vote < 0)
        && (notes.getCurrentPatchSet().id().equals(psId)
            || labelUpdatesOnFollowUpPatchSets.entries().stream()
                .filter(e -> e.getKey().value() < 0)
                .anyMatch(e -> e.getValue().patchSetId().equals(notes.getCurrentPatchSet().id())));
  }

  /**
   * Whether this {@code PostReviewOp} applied votes on an outdated patch set that were not copied
   * to the current patch set.
   *
   * <p>Must only be invoked after this {@code PostReviewOp} has been executed with {@link
   * com.google.gerrit.server.update.BatchUpdate}.
   *
   * @return returns {@code true} if a) ReviewInput contained votes, b) ReviewInput was applied on
   *     an outdated patch set and c) not all of the votes got copied to the current patch set
   */
  private boolean appliedVotesOnOutdatedPatchSetThatWereNotCopiedToCurrentPatchSet() {
    if (in.labels == null || notes.getCurrentPatchSet().id().equals(psId)) {
      return false;
    }

    for (Map.Entry<String, Short> labelEntry : in.labels.entrySet()) {
      if (labelUpdatesOnFollowUpPatchSets
          .get(LabelVote.create(labelEntry.getKey(), labelEntry.getValue())).stream()
          .anyMatch(
              copiedLabelUpdate ->
                  copiedLabelUpdate.patchSetId().equals(notes.getCurrentPatchSet().id()))) {
        continue;
      }

      // vote was not copied to current patch set
      return true;
    }

    return false;
  }

  /**
   * Whether this {@code PostReviewOp} posted a change message.
   *
   * @return returns {@code true} if ReviewInput contained a message.
   */
  private boolean postedChangeMessage() {
    return !Strings.isNullOrEmpty(in.message);
  }

  private TraceContext.TraceTimer newTimer(String method) {
    return TraceContext.newTimer(getClass().getSimpleName() + "#" + method, Metadata.empty());
  }
}
