// 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.toMap;
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.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.restapi.BadRequestException;
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.gerrit.server.util.MarkdownImagesUtil;
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 MarkdownImagesUtil markdownImagesUtil;

  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,
      MarkdownImagesUtil markdownImagesUtil,
      @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.markdownImagesUtil = markdownImagesUtil;

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

  @Override
  public boolean updateChange(ChangeContext ctx)
      throws ResourceConflictException,
          UnprocessableEntityException,
          IOException,
          CommentsRejectedException,
          BadRequestException {
    user = ctx.getIdentifiedUser();
    notes = ctx.getNotes();
    ps = psUtil.get(ctx.getNotes(), psId);
    boolean dirty = false;
    try (TraceContext.TraceTimer ignored = newTimer("insertComments")) {
      dirty |= insertComments(ctx);
    }
    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.
   * @return true if any input comments where published.
   */
  private boolean insertComments(ChangeContext ctx)
      throws BadRequestException, 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> savedDraftsForAllRevisions = new HashMap<>();
    Map<String, HumanComment> savedDraftsToPublish = new HashMap<>();

    if (!inputComments.isEmpty() || in.drafts != DraftHandling.KEEP) {
      savedDraftsForAllRevisions = changeDrafts(ctx);
      savedDraftsToPublish = filterCurrentPatchsetIfNeeded(savedDraftsForAllRevisions);
    }

    // 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, savedDraftsToPublish, ctx);

    switch (in.drafts) {
      case PUBLISH, PUBLISH_ALL_REVISIONS -> {
        validateSavedDraftIds(savedDraftsForAllRevisions);
        Collection<HumanComment> filteredDrafts =
            in.draftIdsToPublish == null
                ? savedDraftsToPublish.values()
                : savedDraftsToPublish.values().stream()
                    .filter(draft -> in.draftIdsToPublish.contains(draft.key.uuid))
                    .collect(Collectors.toList());
        validateComments(
            ctx,
            Streams.concat(
                savedDraftsToPublish.values().stream(), inputCommentsToPublish.stream()));
        publishCommentUtil.publish(ctx, ctx.getUpdate(psId), filteredDrafts, in.tag);
        comments.addAll(savedDraftsToPublish.values());
      }
      case KEEP -> validateComments(ctx, inputCommentsToPublish.stream());
    }
    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 = markdownImagesUtil.stripImages(Strings.nullToEmpty(in.message).trim());
    ImmutableList<CommentForValidation> draftsForValidation =
        Stream.concat(
                comments.map(
                    comment -> {
                      String strippedMessage = markdownImagesUtil.stripImages(comment.message);
                      int size =
                          comment.getApproximateSize()
                              - comment.message.length()
                              + strippedMessage.length();
                      return CommentForValidation.create(
                          CommentForValidation.CommentSource.HUMAN,
                          comment.lineNbr > 0
                              ? CommentForValidation.CommentType.INLINE_COMMENT
                              : CommentForValidation.CommentType.FILE_COMMENT,
                          strippedMessage,
                          size);
                    }),
                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 void validateSavedDraftIds(Map<String, HumanComment> savedDraftsByUuid)
      throws BadRequestException {
    if (in.draftIdsToPublish == null) {
      return;
    }
    List<String> nonExistingDraftIds =
        in.draftIdsToPublish.stream().filter(id -> !savedDraftsByUuid.containsKey(id)).toList();
    if (!nonExistingDraftIds.isEmpty()) {
      throw new BadRequestException("Non-existing draft IDs: " + nonExistingDraftIds);
    }
    if (in.drafts == DraftHandling.PUBLISH_ALL_REVISIONS || in.drafts == DraftHandling.KEEP) {
      return;
    }
    List<String> draftsForOtherRevisions =
        in.draftIdsToPublish.stream()
            .filter(id -> savedDraftsByUuid.get(id).key.patchSetId != psId.get())
            .toList();
    if (!draftsForOtherRevisions.isEmpty()) {
      throw new BadRequestException(
          String.format(
              "Draft comments for other revisions cannot be published when DraftHandling = PUBLISH."
                  + " (draft IDs: %s)",
              draftsForOtherRevisions));
    }
  }

  private Set<CommentSetEntry> readExistingComments(ChangeContext ctx) {
    return commentsUtil.publishedHumanCommentsByChange(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> filterCurrentPatchsetIfNeeded(
      Map<String, HumanComment> savedDraftsForAllRevisions) {
    if (in.drafts == DraftHandling.PUBLISH_ALL_REVISIONS) {
      return savedDraftsForAllRevisions;
    }
    return savedDraftsForAllRevisions.entrySet().stream()
        .filter(c -> c.getValue().key.patchSetId == psId.get())
        .collect(toMap(Map.Entry::getKey, Map.Entry::getValue));
  }

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