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

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.gerrit.server.CommentsUtil.setCommentRevId;
import static com.google.gerrit.server.notedb.ReviewerStateInternal.REVIEWER;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toSet;
import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST;

import com.google.auto.value.AutoValue;
import com.google.common.base.MoreObjects;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Ordering;
import com.google.common.hash.HashCode;
import com.google.common.hash.Hashing;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.common.TimeUtil;
import com.google.gerrit.common.data.LabelType;
import com.google.gerrit.common.data.LabelTypes;
import com.google.gerrit.common.data.Permission;
import com.google.gerrit.common.data.PermissionRange;
import com.google.gerrit.extensions.api.changes.AddReviewerInput;
import com.google.gerrit.extensions.api.changes.AddReviewerResult;
import com.google.gerrit.extensions.api.changes.NotifyHandling;
import com.google.gerrit.extensions.api.changes.RecipientType;
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.api.changes.ReviewResult;
import com.google.gerrit.extensions.api.changes.ReviewerInfo;
import com.google.gerrit.extensions.client.ReviewerState;
import com.google.gerrit.extensions.client.Side;
import com.google.gerrit.extensions.common.AccountInfo;
import com.google.gerrit.extensions.common.FixReplacementInfo;
import com.google.gerrit.extensions.common.FixSuggestionInfo;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
import com.google.gerrit.extensions.restapi.Url;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.ChangeMessage;
import com.google.gerrit.reviewdb.client.Comment;
import com.google.gerrit.reviewdb.client.FixReplacement;
import com.google.gerrit.reviewdb.client.FixSuggestion;
import com.google.gerrit.reviewdb.client.LabelId;
import com.google.gerrit.reviewdb.client.Patch;
import com.google.gerrit.reviewdb.client.PatchLineComment.Status;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.PatchSetApproval;
import com.google.gerrit.reviewdb.client.RobotComment;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.ApprovalsUtil;
import com.google.gerrit.server.ChangeMessagesUtil;
import com.google.gerrit.server.ChangeUtil;
import com.google.gerrit.server.CommentsUtil;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.PatchSetUtil;
import com.google.gerrit.server.ReviewerSet;
import com.google.gerrit.server.account.AccountsCollection;
import com.google.gerrit.server.extensions.events.CommentAdded;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.notedb.ChangeUpdate;
import com.google.gerrit.server.notedb.NotesMigration;
import com.google.gerrit.server.patch.PatchListCache;
import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.update.BatchUpdate;
import com.google.gerrit.server.update.BatchUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
import com.google.gerrit.server.update.Context;
import com.google.gerrit.server.update.UpdateException;
import com.google.gerrit.server.util.LabelVote;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
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.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Singleton
public class PostReview implements RestModifyView<RevisionResource, ReviewInput> {
  private static final Logger log = LoggerFactory.getLogger(PostReview.class);

  private final Provider<ReviewDb> db;
  private final BatchUpdate.Factory batchUpdateFactory;
  private final ChangesCollection changes;
  private final ChangeData.Factory changeDataFactory;
  private final ApprovalsUtil approvalsUtil;
  private final ChangeMessagesUtil cmUtil;
  private final CommentsUtil commentsUtil;
  private final PatchSetUtil psUtil;
  private final PatchListCache patchListCache;
  private final AccountsCollection accounts;
  private final EmailReviewComments.Factory email;
  private final CommentAdded commentAdded;
  private final PostReviewers postReviewers;
  private final NotesMigration migration;
  private final NotifyUtil notifyUtil;

  @Inject
  PostReview(
      Provider<ReviewDb> db,
      BatchUpdate.Factory batchUpdateFactory,
      ChangesCollection changes,
      ChangeData.Factory changeDataFactory,
      ApprovalsUtil approvalsUtil,
      ChangeMessagesUtil cmUtil,
      CommentsUtil commentsUtil,
      PatchSetUtil psUtil,
      PatchListCache patchListCache,
      AccountsCollection accounts,
      EmailReviewComments.Factory email,
      CommentAdded commentAdded,
      PostReviewers postReviewers,
      NotesMigration migration,
      NotifyUtil notifyUtil) {
    this.db = db;
    this.batchUpdateFactory = batchUpdateFactory;
    this.changes = changes;
    this.changeDataFactory = changeDataFactory;
    this.commentsUtil = commentsUtil;
    this.psUtil = psUtil;
    this.patchListCache = patchListCache;
    this.approvalsUtil = approvalsUtil;
    this.cmUtil = cmUtil;
    this.accounts = accounts;
    this.email = email;
    this.commentAdded = commentAdded;
    this.postReviewers = postReviewers;
    this.migration = migration;
    this.notifyUtil = notifyUtil;
  }

  @Override
  public Response<ReviewResult> apply(RevisionResource revision, ReviewInput input)
      throws RestApiException, UpdateException, OrmException, IOException {
    return apply(revision, input, TimeUtil.nowTs());
  }

  public Response<ReviewResult> apply(RevisionResource revision, ReviewInput input, Timestamp ts)
      throws RestApiException, UpdateException, OrmException, IOException {
    // Respect timestamp, but truncate at change created-on time.
    ts = Ordering.natural().max(ts, revision.getChange().getCreatedOn());
    if (revision.getEdit().isPresent()) {
      throw new ResourceConflictException("cannot post review on edit");
    }
    if (input.onBehalfOf != null) {
      revision = onBehalfOf(revision, input);
    } else if (input.drafts == null) {
      input.drafts = DraftHandling.DELETE;
    }
    if (input.labels != null) {
      checkLabels(revision, input.strictLabels, input.labels);
    }
    if (input.comments != null) {
      cleanUpComments(input.comments);
      checkComments(revision, input.comments);
    }
    if (input.robotComments != null) {
      if (!migration.readChanges()) {
        throw new MethodNotAllowedException("robot comments not supported");
      }
      checkRobotComments(revision, input.robotComments);
    }

    if (input.notify == null) {
      log.warn("notify = null; assuming notify = NONE");
      input.notify = NotifyHandling.NONE;
    }

    ListMultimap<RecipientType, Account.Id> accountsToNotify =
        notifyUtil.resolveAccounts(input.notifyDetails);

    Map<String, AddReviewerResult> reviewerJsonResults = null;
    List<PostReviewers.Addition> reviewerResults = Lists.newArrayList();
    boolean hasError = false;
    boolean confirm = false;
    if (input.reviewers != null) {
      reviewerJsonResults = Maps.newHashMap();
      for (AddReviewerInput reviewerInput : input.reviewers) {
        // Prevent notifications because setting reviewers is batched.
        reviewerInput.notify = NotifyHandling.NONE;

        PostReviewers.Addition result =
            postReviewers.prepareApplication(revision.getChangeResource(), reviewerInput, true);
        reviewerJsonResults.put(reviewerInput.reviewer, result.result);
        if (result.result.error != null) {
          hasError = true;
          continue;
        }
        if (result.result.confirm != null) {
          confirm = true;
          continue;
        }
        reviewerResults.add(result);
      }
    }

    ReviewResult output = new ReviewResult();
    output.reviewers = reviewerJsonResults;
    if (hasError || confirm) {
      return Response.withStatusCode(SC_BAD_REQUEST, output);
    }
    output.labels = input.labels;

    try (BatchUpdate bu =
        batchUpdateFactory.create(
            db.get(), revision.getChange().getProject(), revision.getUser(), ts)) {
      Account.Id id = revision.getUser().getAccountId();
      boolean ccOrReviewer = false;
      if (input.labels != null && !input.labels.isEmpty()) {
        ccOrReviewer = input.labels.values().stream().filter(v -> v != 0).findFirst().isPresent();
      }

      if (!ccOrReviewer) {
        // Check if user was already CCed or reviewing prior to this review.
        ReviewerSet currentReviewers =
            approvalsUtil.getReviewers(db.get(), revision.getChangeResource().getNotes());
        ccOrReviewer = currentReviewers.all().contains(id);
      }

      // Apply reviewer changes first. Revision emails should be sent to the
      // updated set of reviewers. Also keep track of whether the user added
      // themselves as a reviewer or to the CC list.
      for (PostReviewers.Addition reviewerResult : reviewerResults) {
        bu.addOp(revision.getChange().getId(), reviewerResult.op);
        if (!ccOrReviewer && reviewerResult.result.reviewers != null) {
          for (ReviewerInfo reviewerInfo : reviewerResult.result.reviewers) {
            if (Objects.equals(id.get(), reviewerInfo._accountId)) {
              ccOrReviewer = true;
              break;
            }
          }
        }
        if (!ccOrReviewer && reviewerResult.result.ccs != null) {
          for (AccountInfo accountInfo : reviewerResult.result.ccs) {
            if (Objects.equals(id.get(), accountInfo._accountId)) {
              ccOrReviewer = true;
              break;
            }
          }
        }
      }

      if (!ccOrReviewer) {
        // User posting this review isn't currently in the reviewer or CC list,
        // isn't being explicitly added, and isn't voting on any label.
        // Automatically CC them on this change so they receive replies.
        PostReviewers.Addition selfAddition =
            postReviewers.ccCurrentUser(revision.getUser(), revision);
        bu.addOp(revision.getChange().getId(), selfAddition.op);
      }

      bu.addOp(
          revision.getChange().getId(),
          new Op(revision.getPatchSet().getId(), input, accountsToNotify, reviewerResults));
      bu.execute();

      for (PostReviewers.Addition reviewerResult : reviewerResults) {
        reviewerResult.gatherResults();
      }

      emailReviewers(revision.getChange(), reviewerResults, input.notify, accountsToNotify);
    }

    return Response.ok(output);
  }

  private void emailReviewers(
      Change change,
      List<PostReviewers.Addition> reviewerAdditions,
      NotifyHandling notify,
      ListMultimap<RecipientType, Account.Id> accountsToNotify) {
    List<Account.Id> to = new ArrayList<>();
    List<Account.Id> cc = new ArrayList<>();
    for (PostReviewers.Addition addition : reviewerAdditions) {
      if (addition.op.state == ReviewerState.REVIEWER) {
        to.addAll(addition.op.reviewers.keySet());
      } else if (addition.op.state == ReviewerState.CC) {
        cc.addAll(addition.op.reviewers.keySet());
      }
    }
    postReviewers.emailReviewers(change, to, cc, notify, accountsToNotify);
  }

  private RevisionResource onBehalfOf(RevisionResource rev, ReviewInput in)
      throws BadRequestException, AuthException, UnprocessableEntityException, OrmException {
    if (in.labels == null || in.labels.isEmpty()) {
      throw new AuthException(
          String.format("label required to post review on behalf of \"%s\"", in.onBehalfOf));
    }
    if (in.drafts == null) {
      in.drafts = DraftHandling.KEEP;
    }
    if (in.drafts != DraftHandling.KEEP) {
      throw new AuthException("not allowed to modify other user's drafts");
    }

    ChangeControl caller = rev.getControl();
    Iterator<Map.Entry<String, Short>> itr = in.labels.entrySet().iterator();
    while (itr.hasNext()) {
      Map.Entry<String, Short> ent = itr.next();
      LabelType type = caller.getLabelTypes().byLabel(ent.getKey());
      if (type == null && in.strictLabels) {
        throw new BadRequestException(
            String.format("label \"%s\" is not a configured label", ent.getKey()));
      } else if (type == null) {
        itr.remove();
        continue;
      }

      if (caller.getUser().isInternalUser()) {
        continue;
      }

      PermissionRange r = caller.getRange(Permission.forLabelAs(type.getName()));
      if (r == null || r.isEmpty() || !r.contains(ent.getValue())) {
        throw new AuthException(
            String.format(
                "not permitted to modify label \"%s\" on behalf of \"%s\"",
                ent.getKey(), in.onBehalfOf));
      }
    }
    if (in.labels.isEmpty()) {
      throw new AuthException(
          String.format("label required to post review on behalf of \"%s\"", in.onBehalfOf));
    }

    ChangeControl target =
        caller.forUser(accounts.parseOnBehalfOf(caller.getUser(), in.onBehalfOf));
    if (!target.getRefControl().isVisible()) {
      throw new UnprocessableEntityException(
          String.format(
              "on_behalf_of account %s cannot see destination ref",
              target.getUser().getAccountId()));
    }
    return new RevisionResource(changes.parse(target), rev.getPatchSet());
  }

  private void checkLabels(RevisionResource revision, boolean strict, Map<String, Short> labels)
      throws BadRequestException, AuthException {
    ChangeControl ctl = revision.getControl();
    Iterator<Map.Entry<String, Short>> itr = labels.entrySet().iterator();
    while (itr.hasNext()) {
      Map.Entry<String, Short> ent = itr.next();

      LabelType lt = revision.getControl().getLabelTypes().byLabel(ent.getKey());
      if (lt == null) {
        if (strict) {
          throw new BadRequestException(
              String.format("label \"%s\" is not a configured label", ent.getKey()));
        }
        itr.remove();
        continue;
      }

      if (ent.getValue() == null || ent.getValue() == 0) {
        // Always permit 0, even if it is not within range.
        // Later null/0 will be deleted and revoke the label.
        continue;
      }

      if (lt.getValue(ent.getValue()) == null) {
        if (strict) {
          throw new BadRequestException(
              String.format("label \"%s\": %d is not a valid value", ent.getKey(), ent.getValue()));
        }
        itr.remove();
        continue;
      }

      String name = lt.getName();
      PermissionRange range = ctl.getRange(Permission.forLabel(name));
      if (range == null || !range.contains(ent.getValue())) {
        if (strict) {
          throw new AuthException(
              String.format(
                  "Applying label \"%s\": %d is restricted", ent.getKey(), ent.getValue()));
        } else if (range == null || range.isEmpty()) {
          ent.setValue((short) 0);
        } else {
          ent.setValue((short) range.squash(ent.getValue()));
        }
      }
    }
  }

  private <T extends CommentInput> void cleanUpComments(Map<String, List<T>> commentsPerPath) {
    Iterator<List<T>> mapValueIterator = commentsPerPath.values().iterator();
    while (mapValueIterator.hasNext()) {
      List<T> comments = mapValueIterator.next();
      if (comments == null) {
        mapValueIterator.remove();
        continue;
      }

      cleanUpComments(comments);
      if (comments.isEmpty()) {
        mapValueIterator.remove();
      }
    }
  }

  private <T extends CommentInput> void cleanUpComments(List<T> comments) {
    Iterator<T> commentsIterator = comments.iterator();
    while (commentsIterator.hasNext()) {
      T comment = commentsIterator.next();
      if (comment == null) {
        commentsIterator.remove();
        continue;
      }

      comment.message = Strings.nullToEmpty(comment.message).trim();
      if (comment.message.isEmpty()) {
        commentsIterator.remove();
      }
    }
  }

  private <T extends CommentInput> void checkComments(
      RevisionResource revision, Map<String, List<T>> commentsPerPath)
      throws OrmException, BadRequestException {
    Set<String> revisionFilePaths = getAffectedFilePaths(revision);
    for (Map.Entry<String, List<T>> entry : commentsPerPath.entrySet()) {
      String path = entry.getKey();
      PatchSet.Id patchSetId = revision.getChange().currentPatchSetId();
      ensurePathRefersToAvailableOrMagicFile(path, revisionFilePaths, patchSetId);

      List<T> comments = entry.getValue();
      for (T comment : comments) {
        ensureLineIsNonNegative(comment.line, path);
        ensureCommentNotOnMagicFilesOfAutoMerge(path, comment);
        ensureRangeIsValid(path, comment.range);
      }
    }
  }

  private Set<String> getAffectedFilePaths(RevisionResource revision) throws OrmException {
    ChangeData changeData = changeDataFactory.create(db.get(), revision.getControl());
    return new HashSet<>(changeData.filePaths(revision.getPatchSet()));
  }

  private void ensurePathRefersToAvailableOrMagicFile(
      String path, Set<String> availableFilePaths, PatchSet.Id patchSetId)
      throws BadRequestException {
    if (!availableFilePaths.contains(path) && !Patch.isMagic(path)) {
      throw new BadRequestException(
          String.format("file %s not found in revision %s", path, patchSetId));
    }
  }

  private void ensureLineIsNonNegative(Integer line, String path) throws BadRequestException {
    if (line != null && line < 0) {
      throw new BadRequestException(
          String.format("negative line number %d not allowed on %s", line, path));
    }
  }

  private <T extends CommentInput> void ensureCommentNotOnMagicFilesOfAutoMerge(
      String path, T comment) throws BadRequestException {
    if (Patch.isMagic(path) && comment.side == Side.PARENT && comment.parent == null) {
      throw new BadRequestException(String.format("cannot comment on %s on auto-merge", path));
    }
  }

  private void checkRobotComments(
      RevisionResource revision, Map<String, List<RobotCommentInput>> in)
      throws BadRequestException, OrmException {
    cleanUpComments(in);
    for (Map.Entry<String, List<RobotCommentInput>> e : in.entrySet()) {
      String commentPath = e.getKey();
      for (RobotCommentInput c : e.getValue()) {
        ensureRobotIdIsSet(c.robotId, commentPath);
        ensureRobotRunIdIsSet(c.robotRunId, commentPath);
        ensureFixSuggestionsAreAddable(c.fixSuggestions, commentPath);
      }
    }
    checkComments(revision, in);
  }

  private void ensureRobotIdIsSet(String robotId, String commentPath) throws BadRequestException {
    if (robotId == null) {
      throw new BadRequestException(
          String.format("robotId is missing for robot comment on %s", commentPath));
    }
  }

  private void ensureRobotRunIdIsSet(String robotRunId, String commentPath)
      throws BadRequestException {
    if (robotRunId == null) {
      throw new BadRequestException(
          String.format("robotRunId is missing for robot comment on %s", commentPath));
    }
  }

  private void ensureFixSuggestionsAreAddable(
      List<FixSuggestionInfo> fixSuggestionInfos, String commentPath) throws BadRequestException {
    if (fixSuggestionInfos == null) {
      return;
    }

    for (FixSuggestionInfo fixSuggestionInfo : fixSuggestionInfos) {
      ensureDescriptionIsSet(commentPath, fixSuggestionInfo.description);
      ensureFixReplacementsAreAddable(commentPath, fixSuggestionInfo.replacements);
    }
  }

  private void ensureDescriptionIsSet(String commentPath, String description)
      throws BadRequestException {
    if (description == null) {
      throw new BadRequestException(
          String.format(
              "A description is required for the suggested fix of the robot comment on %s",
              commentPath));
    }
  }

  private void ensureFixReplacementsAreAddable(
      String commentPath, List<FixReplacementInfo> fixReplacementInfos) throws BadRequestException {
    ensureReplacementsArePresent(commentPath, fixReplacementInfos);

    for (FixReplacementInfo fixReplacementInfo : fixReplacementInfos) {
      ensureReplacementPathIsSet(commentPath, fixReplacementInfo.path);
      ensureReplacementPathRefersToFileOfComment(commentPath, fixReplacementInfo.path);
      ensureRangeIsSet(commentPath, fixReplacementInfo.range);
      ensureRangeIsValid(commentPath, fixReplacementInfo.range);
      ensureReplacementStringIsSet(commentPath, fixReplacementInfo.replacement);
    }
  }

  private void ensureReplacementsArePresent(
      String commentPath, List<FixReplacementInfo> fixReplacementInfos) throws BadRequestException {
    if (fixReplacementInfos == null || fixReplacementInfos.isEmpty()) {
      throw new BadRequestException(
          String.format(
              "At least one replacement is "
                  + "required for the suggested fix of the robot comment on %s",
              commentPath));
    }
  }

  private void ensureReplacementPathIsSet(String commentPath, String replacementPath)
      throws BadRequestException {
    if (replacementPath == null) {
      throw new BadRequestException(
          String.format(
              "A file path must be given for the replacement of the robot comment on %s",
              commentPath));
    }
  }

  private void ensureReplacementPathRefersToFileOfComment(
      String commentPath, String replacementPath) throws BadRequestException {
    if (!Objects.equals(commentPath, replacementPath)) {
      throw new BadRequestException(
          String.format(
              "Replacements may only be "
                  + "specified for the file %s on which the robot comment was added",
              commentPath));
    }
  }

  private void ensureRangeIsSet(
      String commentPath, com.google.gerrit.extensions.client.Comment.Range range)
      throws BadRequestException {
    if (range == null) {
      throw new BadRequestException(
          String.format(
              "A range must be given for the replacement of the robot comment on %s", commentPath));
    }
  }

  private void ensureRangeIsValid(
      String commentPath, com.google.gerrit.extensions.client.Comment.Range range)
      throws BadRequestException {
    if (range == null) {
      return;
    }
    if (!range.isValid()) {
      throw new BadRequestException(
          String.format(
              "Range (%s:%s - %s:%s) is not valid for the comment on %s",
              range.startLine,
              range.startCharacter,
              range.endLine,
              range.endCharacter,
              commentPath));
    }
  }

  private void ensureReplacementStringIsSet(String commentPath, String replacement)
      throws BadRequestException {
    if (replacement == null) {
      throw new BadRequestException(
          String.format(
              "A content for replacement "
                  + "must be indicated for the replacement of the robot comment on %s",
              commentPath));
    }
  }

  /** Used to compare Comments with CommentInput comments. */
  @AutoValue
  abstract static class CommentSetEntry {
    private static CommentSetEntry create(
        String filename,
        int patchSetId,
        Integer line,
        Side side,
        HashCode message,
        Comment.Range range) {
      return new AutoValue_PostReview_CommentSetEntry(
          filename, patchSetId, line, side, message, range);
    }

    @SuppressWarnings("deprecation") // Use Hashing.sha1 for compatibility.
    public static CommentSetEntry create(Comment comment) {
      return create(
          comment.key.filename,
          comment.key.patchSetId,
          comment.lineNbr,
          Side.fromShort(comment.side),
          Hashing.sha1().hashString(comment.message, UTF_8),
          comment.range);
    }

    abstract String filename();

    abstract int patchSetId();

    @Nullable
    abstract Integer line();

    abstract Side side();

    abstract HashCode message();

    @Nullable
    abstract Comment.Range range();
  }

  private class Op implements BatchUpdateOp {
    private final PatchSet.Id psId;
    private final ReviewInput in;
    private final ListMultimap<RecipientType, Account.Id> accountsToNotify;
    private final List<PostReviewers.Addition> reviewerResults;

    private IdentifiedUser user;
    private ChangeNotes notes;
    private PatchSet ps;
    private ChangeMessage message;
    private List<Comment> comments = new ArrayList<>();
    private List<LabelVote> labelDelta = new ArrayList<>();
    private Map<String, Short> approvals = new HashMap<>();
    private Map<String, Short> oldApprovals = new HashMap<>();

    private Op(
        PatchSet.Id psId,
        ReviewInput in,
        ListMultimap<RecipientType, Account.Id> accountsToNotify,
        List<PostReviewers.Addition> reviewerResults) {
      this.psId = psId;
      this.in = in;
      this.accountsToNotify = checkNotNull(accountsToNotify);
      this.reviewerResults = reviewerResults;
    }

    @Override
    public boolean updateChange(ChangeContext ctx)
        throws OrmException, ResourceConflictException, UnprocessableEntityException {
      user = ctx.getIdentifiedUser();
      notes = ctx.getNotes();
      ps = psUtil.get(ctx.getDb(), ctx.getNotes(), psId);
      boolean dirty = false;
      dirty |= insertComments(ctx);
      dirty |= insertRobotComments(ctx);
      dirty |= updateLabels(ctx);
      dirty |= insertMessage(ctx);
      return dirty;
    }

    @Override
    public void postUpdate(Context ctx) throws OrmException {
      if (message == null) {
        return;
      }
      if (in.notify.compareTo(NotifyHandling.NONE) > 0 || !accountsToNotify.isEmpty()) {
        email
            .create(
                in.notify,
                accountsToNotify,
                notes,
                ps,
                user,
                message,
                comments,
                in.message,
                labelDelta)
            .sendAsync();
      }
      commentAdded.fire(
          notes.getChange(),
          ps,
          user.getAccount(),
          message.getMessage(),
          approvals,
          oldApprovals,
          ctx.getWhen());
    }

    private boolean insertComments(ChangeContext ctx)
        throws OrmException, UnprocessableEntityException {
      Map<String, List<CommentInput>> map = in.comments;
      if (map == null) {
        map = Collections.emptyMap();
      }

      Map<String, Comment> drafts = Collections.emptyMap();
      if (!map.isEmpty() || in.drafts != DraftHandling.KEEP) {
        if (in.drafts == DraftHandling.PUBLISH_ALL_REVISIONS) {
          drafts = changeDrafts(ctx);
        } else {
          drafts = patchSetDrafts(ctx);
        }
      }

      List<Comment> toDel = new ArrayList<>();
      List<Comment> toPublish = new ArrayList<>();

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

      for (Map.Entry<String, List<CommentInput>> ent : map.entrySet()) {
        String path = ent.getKey();
        for (CommentInput c : ent.getValue()) {
          String parent = Url.decode(c.inReplyTo);
          Comment e = drafts.remove(Url.decode(c.id));
          if (e == null) {
            e = commentsUtil.newComment(ctx, path, psId, c.side(), c.message, c.unresolved, parent);
          } else {
            e.writtenOn = ctx.getWhen();
            e.side = c.side();
            e.message = c.message;
          }

          setCommentRevId(e, patchListCache, ctx.getChange(), ps);
          e.setLineNbrAndRange(c.line, c.range);
          e.tag = in.tag;

          if (existingIds.contains(CommentSetEntry.create(e))) {
            continue;
          }
          toPublish.add(e);
        }
      }

      switch (in.drafts) {
        case KEEP:
        default:
          break;
        case DELETE:
          toDel.addAll(drafts.values());
          break;
        case PUBLISH:
          for (Comment e : drafts.values()) {
            toPublish.add(publishComment(ctx, e, ps));
          }
          break;
        case PUBLISH_ALL_REVISIONS:
          publishAllRevisions(ctx, drafts, toPublish);
          break;
      }
      ChangeUpdate u = ctx.getUpdate(psId);
      commentsUtil.deleteComments(ctx.getDb(), u, toDel);
      commentsUtil.putComments(ctx.getDb(), u, Status.PUBLISHED, toPublish);
      comments.addAll(toPublish);
      return !toDel.isEmpty() || !toPublish.isEmpty();
    }

    private boolean insertRobotComments(ChangeContext ctx) throws OrmException {
      if (in.robotComments == null) {
        return false;
      }

      List<RobotComment> newRobotComments = getNewRobotComments(ctx);
      commentsUtil.putRobotComments(ctx.getUpdate(psId), newRobotComments);
      comments.addAll(newRobotComments);
      return !newRobotComments.isEmpty();
    }

    private List<RobotComment> getNewRobotComments(ChangeContext ctx) throws OrmException {
      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) throws OrmException {
      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;
      setCommentRevId(robotComment, patchListCache, ctx.getChange(), ps);
      robotComment.fixSuggestions = createFixSuggestionsFromInput(robotCommentInput.fixSuggestions);
      return robotComment;
    }

    private List<FixSuggestion> createFixSuggestionsFromInput(
        List<FixSuggestionInfo> fixSuggestionInfos) {
      if (fixSuggestionInfos == null) {
        return Collections.emptyList();
      }

      List<FixSuggestion> fixSuggestions = new ArrayList<>(fixSuggestionInfos.size());
      for (FixSuggestionInfo fixSuggestionInfo : fixSuggestionInfos) {
        fixSuggestions.add(createFixSuggestionFromInput(fixSuggestionInfo));
      }
      return fixSuggestions;
    }

    private FixSuggestion createFixSuggestionFromInput(FixSuggestionInfo fixSuggestionInfo) {
      List<FixReplacement> fixReplacements = toFixReplacements(fixSuggestionInfo.replacements);
      String fixId = ChangeUtil.messageUuid();
      return new FixSuggestion(fixId, fixSuggestionInfo.description, fixReplacements);
    }

    private List<FixReplacement> toFixReplacements(List<FixReplacementInfo> fixReplacementInfos) {
      return fixReplacementInfos.stream().map(this::toFixReplacement).collect(toList());
    }

    private FixReplacement toFixReplacement(FixReplacementInfo fixReplacementInfo) {
      Comment.Range range = new Comment.Range(fixReplacementInfo.range);
      return new FixReplacement(fixReplacementInfo.path, range, fixReplacementInfo.replacement);
    }

    private Set<CommentSetEntry> readExistingComments(ChangeContext ctx) throws OrmException {
      return commentsUtil.publishedByChange(ctx.getDb(), ctx.getNotes()).stream()
          .map(CommentSetEntry::create)
          .collect(toSet());
    }

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

    private Map<String, Comment> changeDrafts(ChangeContext ctx) throws OrmException {
      Map<String, Comment> drafts = new HashMap<>();
      for (Comment c :
          commentsUtil.draftByChangeAuthor(ctx.getDb(), ctx.getNotes(), user.getAccountId())) {
        c.tag = in.tag;
        drafts.put(c.key.uuid, c);
      }
      return drafts;
    }

    private Map<String, Comment> patchSetDrafts(ChangeContext ctx) throws OrmException {
      Map<String, Comment> drafts = new HashMap<>();
      for (Comment c :
          commentsUtil.draftByPatchSetAuthor(
              ctx.getDb(), psId, user.getAccountId(), ctx.getNotes())) {
        drafts.put(c.key.uuid, c);
      }
      return drafts;
    }

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

    private Comment publishComment(ChangeContext ctx, Comment c, PatchSet ps) throws OrmException {
      c.writtenOn = ctx.getWhen();
      c.tag = in.tag;
      // Draft may have been created by a different real user; copy the current
      // real user. (Only applies to X-Gerrit-RunAs, since modifying drafts via
      // on_behalf_of is not allowed.)
      ctx.getUser().updateRealAccountId(c::setRealAuthor);
      setCommentRevId(c, patchListCache, ctx.getChange(), checkNotNull(ps));
      return c;
    }

    private void publishAllRevisions(
        ChangeContext ctx, Map<String, Comment> drafts, List<Comment> ups) throws OrmException {
      boolean needOtherPatchSets = false;
      for (Comment c : drafts.values()) {
        if (c.key.patchSetId != psId.get()) {
          needOtherPatchSets = true;
          break;
        }
      }
      Map<PatchSet.Id, PatchSet> patchSets =
          needOtherPatchSets
              ? psUtil.byChangeAsMap(ctx.getDb(), ctx.getNotes())
              : ImmutableMap.of(psId, ps);
      for (Comment e : drafts.values()) {
        ups.add(
            publishComment(
                ctx, e, patchSets.get(new PatchSet.Id(ctx.getChange().getId(), e.key.patchSetId))));
      }
    }

    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) throws OrmException {
      if (ctx.getAccountId().equals(ctx.getChange().getOwner())) {
        return true;
      }
      for (PostReviewers.Addition addition : reviewerResults) {
        if (addition.op.addedReviewers == null) {
          continue;
        }
        for (PatchSetApproval psa : addition.op.addedReviewers) {
          if (psa.getAccountId().equals(ctx.getAccountId())) {
            return true;
          }
        }
      }
      ChangeData cd = changeDataFactory.create(db.get(), ctx.getControl());
      ReviewerSet reviewers = cd.reviewers();
      if (reviewers.byState(REVIEWER).contains(ctx.getAccountId())) {
        return true;
      }
      return false;
    }

    private boolean updateLabels(ChangeContext ctx) throws OrmException, ResourceConflictException {
      Map<String, Short> inLabels =
          MoreObjects.firstNonNull(in.labels, Collections.<String, Short>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().getStatus().isClosed()) {
        return false;
      }

      List<PatchSetApproval> del = new ArrayList<>();
      List<PatchSetApproval> ups = new ArrayList<>();
      Map<String, PatchSetApproval> current = scanLabels(ctx, del);
      LabelTypes labelTypes = ctx.getControl().getLabelTypes();
      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 = checkNotNull(labelTypes.byLabel(name), 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.getValue() != 0) {
              addLabelDelta(normName, (short) 0);
              oldApprovals.put(normName, previous.get(normName));
            }
            del.add(c);
            update.putApproval(normName, (short) 0);
          }
        } else if (c != null && c.getValue() != ent.getValue()) {
          c.setValue(ent.getValue());
          c.setGranted(ctx.getWhen());
          c.setTag(in.tag);
          ctx.getUser().updateRealAccountId(c::setRealAccountId);
          ups.add(c);
          addLabelDelta(normName, c.getValue());
          oldApprovals.put(normName, previous.get(normName));
          approvals.put(normName, c.getValue());
          update.putApproval(normName, ent.getValue());
        } else if (c != null && c.getValue() == ent.getValue()) {
          current.put(normName, c);
          oldApprovals.put(normName, null);
          approvals.put(normName, c.getValue());
        } else if (c == null) {
          c = ApprovalsUtil.newApproval(psId, user, lt.getLabelId(), ent.getValue(), ctx.getWhen());
          c.setTag(in.tag);
          c.setGranted(ctx.getWhen());
          ups.add(c);
          addLabelDelta(normName, c.getValue());
          oldApprovals.put(normName, previous.get(normName));
          approvals.put(normName, c.getValue());
          update.putReviewer(user.getAccountId(), REVIEWER);
          update.putApproval(normName, ent.getValue());
        }
      }

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

      forceCallerAsReviewer(ctx, current, ups, del);
      ctx.getDb().patchSetApprovals().delete(del);
      ctx.getDb().patchSetApprovals().upsert(ups);
      return !del.isEmpty() || !ups.isEmpty();
    }

    private void validatePostSubmitLabels(
        ChangeContext ctx,
        LabelTypes labelTypes,
        Map<String, Short> previous,
        List<PatchSetApproval> ups,
        List<PatchSetApproval> del)
        throws ResourceConflictException {
      if (ctx.getChange().getStatus().isOpen()) {
        return; // Not closed, nothing to validate.
      } else if (del.isEmpty() && ups.isEmpty()) {
        return; // No new votes.
      } else if (ctx.getChange().getStatus() != Change.Status.MERGED) {
        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 = checkNotNull(labelTypes.byLabel(psa.getLabel()));
        String normName = lt.getName();
        if (!lt.allowPostSubmit()) {
          disallowed.add(normName);
        }
        Short prev = previous.get(normName);
        if (prev != null && prev != 0) {
          reduced.add(psa);
        }
      }

      for (PatchSetApproval psa : ups) {
        LabelType lt = checkNotNull(labelTypes.byLabel(psa.getLabel()));
        String normName = lt.getName();
        if (!lt.allowPostSubmit()) {
          disallowed.add(normName);
        }
        Short prev = previous.get(normName);
        if (prev == null) {
          continue;
        }
        checkState(prev != psa.getValue()); // Should be filtered out above.
        if (prev > psa.getValue()) {
          reduced.add(psa);
        } else {
          // Set postSubmit bit in ReviewDb; not required for NoteDb, which sets
          // it automatically.
          psa.setPostSubmit(true);
        }
      }

      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(p -> p.getLabel())
                    .distinct()
                    .sorted()
                    .collect(joining(", ")));
      }
    }

    private void forceCallerAsReviewer(
        ChangeContext ctx,
        Map<String, PatchSetApproval> current,
        List<PatchSetApproval> ups,
        List<PatchSetApproval> del) {
      if (current.isEmpty() && ups.isEmpty()) {
        // TODO Find another way to link reviewers to changes.
        if (del.isEmpty()) {
          // If no existing label is being set to 0, hack in the caller
          // as a reviewer by picking the first server-wide LabelType.
          LabelId labelId = ctx.getControl().getLabelTypes().getLabelTypes().get(0).getLabelId();
          PatchSetApproval c = ApprovalsUtil.newApproval(psId, user, labelId, 0, ctx.getWhen());
          c.setTag(in.tag);
          c.setGranted(ctx.getWhen());
          ups.add(c);
        } else {
          // Pick a random label that is about to be deleted and keep it.
          Iterator<PatchSetApproval> i = del.iterator();
          PatchSetApproval c = i.next();
          c.setValue((short) 0);
          c.setGranted(ctx.getWhen());
          i.remove();
          ups.add(c);
        }
      }
      ctx.getUpdate(ctx.getChange().currentPatchSetId()).putReviewer(user.getAccountId(), REVIEWER);
    }

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

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

        LabelType lt = labelTypes.byLabel(a.getLabelId());
        if (lt != null) {
          current.put(lt.getName(), a);
        } else {
          del.add(a);
        }
      }
      return current;
    }

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

      StringBuilder buf = new StringBuilder();
      for (LabelVote d : labelDelta) {
        buf.append(" ").append(d.format());
      }
      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()) {
        buf.append("\n\n").append(msg);
      }
      if (buf.length() == 0) {
        return false;
      }

      message =
          ChangeMessagesUtil.newMessage(
              psId, user, ctx.getWhen(), "Patch Set " + psId.get() + ":" + buf, in.tag);
      cmUtil.addChangeMessage(ctx.getDb(), ctx.getUpdate(psId), message);
      return true;
    }

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