// Copyright (C) 2016 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.googlesource.gerrit.plugins.automerger;

import static com.google.common.base.Strings.isNullOrEmpty;

import com.google.common.base.Joiner;
import com.google.gerrit.extensions.api.GerritApi;
import com.google.gerrit.extensions.api.changes.AbandonInput;
import com.google.gerrit.extensions.api.changes.ChangeApi;
import com.google.gerrit.extensions.api.changes.NotifyHandling;
import com.google.gerrit.extensions.api.changes.RestoreInput;
import com.google.gerrit.extensions.api.changes.ReviewInput;
import com.google.gerrit.extensions.client.ChangeStatus;
import com.google.gerrit.extensions.client.ListChangesOption;
import com.google.gerrit.extensions.common.ApprovalInfo;
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.common.ChangeInput;
import com.google.gerrit.extensions.common.CommitInfo;
import com.google.gerrit.extensions.common.MergeInput;
import com.google.gerrit.extensions.common.MergePatchSetInput;
import com.google.gerrit.extensions.common.RevisionInfo;
import com.google.gerrit.extensions.events.ChangeAbandonedListener;
import com.google.gerrit.extensions.events.ChangeRestoredListener;
import com.google.gerrit.extensions.events.CommentAddedListener;
import com.google.gerrit.extensions.events.DraftPublishedListener;
import com.google.gerrit.extensions.events.RevisionCreatedListener;
import com.google.gerrit.extensions.events.TopicEditedListener;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.MergeConflictException;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.inject.Inject;
import java.io.IOException;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.UUID;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * DownstreamCreator will receive an event on an uploaded, published, or restored patchset, and
 * upload a merge of the original patchset downstream, as determined by the configuration file. When
 * a topic or vote is changed on a patchset, or a change is abandoned, all downstream patchsets will
 * be modified as well.
 */
public class DownstreamCreator
    implements ChangeAbandonedListener,
        ChangeRestoredListener,
        CommentAddedListener,
        DraftPublishedListener,
        RevisionCreatedListener,
        TopicEditedListener {
  private static final Logger log = LoggerFactory.getLogger(DownstreamCreator.class);
  private static final String AUTOMERGER_TAG = "autogenerated:Automerger";
  private static final String MERGE_CONFLICT_TAG = "autogenerated:MergeConflict";
  private static final String SUBJECT_PREFIX = "[automerger]";

  protected GerritApi gApi;
  protected ConfigLoader config;

  @Inject
  public DownstreamCreator(GerritApi gApi, ConfigLoader config) {
    this.gApi = gApi;
    this.config = config;
  }

  /**
   * Abandons downstream changes if a change is abandoned.
   *
   * @param event Event we are listening to.
   */
  @Override
  public void onChangeAbandoned(ChangeAbandonedListener.Event event) {
    ChangeInfo change = event.getChange();
    String revision = event.getRevision().commit.commit;
    log.debug("Detected revision {} abandoned on {}.", revision, change.project);
    try {
      abandonDownstream(change, revision);
    } catch (ConfigInvalidException e) {
      log.error("Automerger plugin failed onChangeAbandoned for {}", change.id, e);
    }
  }

  /**
   * Updates downstream topics if a change has its topic modified.
   *
   * @param event Event we are listening to.
   */
  @Override
  public void onTopicEdited(TopicEditedListener.Event event) {
    ChangeInfo eventChange = event.getChange();
    // We have to re-query for this in order to include the current revision
    ChangeInfo change;
    try {
      change =
          gApi.changes()
              .id(eventChange._number)
              .get(EnumSet.of(ListChangesOption.CURRENT_REVISION));
    } catch (RestApiException e) {
      log.error("Automerger could not get change with current revision for onTopicEdited: ", e);
      return;
    }
    String oldTopic = event.getOldTopic();
    String revision = change.currentRevision;
    Set<String> downstreamBranches;
    try {
      downstreamBranches = config.getDownstreamBranches(change.branch, change.project);
    } catch (RestApiException | IOException | ConfigInvalidException e) {
      log.error("Failed to edit downstream topics of {}", change.id, e);
      return;
    }

    if (downstreamBranches.isEmpty()) {
      log.debug("Downstream branches of {} on {} are empty", change.branch, change.project);
      return;
    }

    // If change is empty, prevent someone breaking topic.
    if (isNullOrEmpty(change.topic)) {
      try {
        gApi.changes().id(change._number).topic(oldTopic);
        ReviewInput reviewInput = new ReviewInput();
        reviewInput.message(
            "Automerger prevented the topic from changing. Topic can only be modified on "
                + "non-automerger-created CLs to a non-empty value.");
        reviewInput.notify = NotifyHandling.NONE;
        gApi.changes().id(change._number).revision(change.currentRevision).review(reviewInput);
      } catch (RestApiException e) {
        log.error("Failed to prevent setting empty topic for automerger plugin.", e);
      }
    } else {
      for (String downstreamBranch : downstreamBranches) {
        try {
          List<Integer> existingDownstream =
              getExistingMergesOnBranch(revision, oldTopic, downstreamBranch);
          for (Integer changeNumber : existingDownstream) {
            log.debug("Setting topic {} on {}", change.topic, changeNumber);
            gApi.changes().id(changeNumber).topic(change.topic);
          }
        } catch (RestApiException | InvalidQueryParameterException e) {
          log.error("Failed to edit downstream topics of {}", change.id, e);
        }
      }
    }
  }

  /**
   * Updates downstream votes for a change each time a comment is made.
   *
   * @param event Event we are listening to.
   */
  @Override
  public void onCommentAdded(CommentAddedListener.Event event) {
    RevisionInfo eventRevision = event.getRevision();
    if (!eventRevision.isCurrent) {
      log.info(
          "Not updating downstream votes since revision {} is not current.", eventRevision._number);
      return;
    }
    ChangeInfo change = event.getChange();
    String revision = change.currentRevision;
    Set<String> downstreamBranches;
    try {
      downstreamBranches = config.getDownstreamBranches(change.branch, change.project);
    } catch (RestApiException | IOException | ConfigInvalidException e) {
      log.error("Failed to update downstream votes of {}", change.id, e);
      return;
    }

    if (downstreamBranches.isEmpty()) {
      log.debug("Downstream branches of {} on {} are empty", change.branch, change.project);
      return;
    }

    Map<String, ApprovalInfo> approvals = event.getApprovals();

    for (String downstreamBranch : downstreamBranches) {
      try {
        List<Integer> existingDownstream =
            getExistingMergesOnBranch(revision, change.topic, downstreamBranch);
        for (Integer changeNumber : existingDownstream) {
          ChangeInfo downstreamChange =
              gApi.changes().id(changeNumber).get(EnumSet.of(ListChangesOption.CURRENT_REVISION));
          for (Map.Entry<String, ApprovalInfo> label : approvals.entrySet()) {
            updateVote(downstreamChange, label.getKey(), label.getValue().value.shortValue());
          }
        }
      } catch (RestApiException | InvalidQueryParameterException e) {
        log.error("Exception when updating downstream votes of {}", change.id, e);
      }
    }
  }

  /**
   * Automerges changes downstream if a change is restored.
   *
   * @param event Event we are listening to.
   */
  @Override
  public void onChangeRestored(ChangeRestoredListener.Event event) {
    ChangeInfo change = event.getChange();
    try {
      automergeChanges(change, event.getRevision());
    } catch (RestApiException
        | IOException
        | ConfigInvalidException
        | InvalidQueryParameterException e) {
      log.error("Automerger plugin failed onChangeRestored for {}", change.id, e);
    }
  }

  /**
   * Automerges changes downstream if a draft is published.
   *
   * @param event Event we are listening to.
   */
  @Override
  public void onDraftPublished(DraftPublishedListener.Event event) {
    ChangeInfo change = event.getChange();
    try {
      automergeChanges(change, event.getRevision());
    } catch (RestApiException
        | IOException
        | ConfigInvalidException
        | InvalidQueryParameterException e) {
      log.error("Automerger plugin failed onDraftPublished for {}", change.id, e);
    }
  }

  /**
   * Automerges changes downstream if a revision is created.
   *
   * @param event Event we are listening to.
   */
  @Override
  public void onRevisionCreated(RevisionCreatedListener.Event event) {
    ChangeInfo change = event.getChange();
    try {
      automergeChanges(change, event.getRevision());
    } catch (RestApiException
        | IOException
        | ConfigInvalidException
        | InvalidQueryParameterException e) {
      log.error("Automerger plugin failed onRevisionCreated for {}", change.id, e);
    }
  }

  /**
   * Creates merges downstream, and votes on the automerge label if we have a failed merge.
   *
   * @param mdsMergeInput Input containing the downstream branch map and source change ID.
   * @throws RestApiException Throws if we fail a REST API call.
   * @throws ConfigInvalidException Throws if we get a malformed configuration
   * @throws InvalidQueryParameterException Throws if we attempt to add an invalid value to query.
   */
  public void createMergesAndHandleConflicts(MultipleDownstreamMergeInput mdsMergeInput)
      throws RestApiException, ConfigInvalidException, InvalidQueryParameterException {
    ReviewInput reviewInput = new ReviewInput();
    Map<String, Short> labels = new HashMap<String, Short>();
    try {
      createDownstreamMerges(mdsMergeInput);

      reviewInput.message =
          "Automerging to "
              + Joiner.on(", ").join(mdsMergeInput.dsBranchMap.keySet())
              + " succeeded!";
      reviewInput.notify = NotifyHandling.NONE;
    } catch (FailedMergeException e) {
      reviewInput.message = e.getDisplayString();
      reviewInput.notify = NotifyHandling.ALL;
      reviewInput.tag = MERGE_CONFLICT_TAG;
      // Vote minAutomergeVote if we hit a conflict.
      if (!config.minAutomergeVoteDisabled()) {
        labels.put(config.getAutomergeLabel(), config.getMinAutomergeVote());
      }
    }
    reviewInput.labels = labels;
    // if this fails, i.e. -2 is restricted, catch it and still post message without a vote.
    try {
      gApi.changes()
          .id(mdsMergeInput.changeNumber)
          .revision(mdsMergeInput.currentRevision)
          .review(reviewInput);
    } catch (AuthException e) {
      reviewInput.labels = null;
      gApi.changes()
          .id(mdsMergeInput.changeNumber)
          .revision(mdsMergeInput.currentRevision)
          .review(reviewInput);
    }
  }

  /**
   * Creates merge downstream.
   *
   * @param mdsMergeInput Input containing the downstream branch map and source change ID.
   * @throws RestApiException Throws if we fail a REST API call.
   * @throws FailedMergeException Throws if we get a merge conflict when merging downstream.
   * @throws ConfigInvalidException Throws if we get a malformed config file
   * @throws InvalidQueryParameterException Throws if we attempt to add an invalid value to query.
   */
  public void createDownstreamMerges(MultipleDownstreamMergeInput mdsMergeInput)
      throws RestApiException, FailedMergeException, ConfigInvalidException,
          InvalidQueryParameterException {
    // Map from branch to error message
    Map<String, String> failedMergeBranchMap = new TreeMap<String, String>();

    List<Integer> existingDownstream;
    for (String downstreamBranch : mdsMergeInput.dsBranchMap.keySet()) {
      // If there are existing downstream merges, update them
      // Otherwise, create them.
      boolean createDownstreams = true;
      if (mdsMergeInput.obsoleteRevision != null) {
        existingDownstream =
            getExistingMergesOnBranch(
                mdsMergeInput.obsoleteRevision, mdsMergeInput.topic, downstreamBranch);
        if (!existingDownstream.isEmpty()) {
          log.debug(
              "Attempting to update downstream merge of {} on branch {}",
              mdsMergeInput.currentRevision,
              downstreamBranch);
          // existingDownstream should almost always be of length one, but
          // it's possible to construct it so that it's not
          for (Integer dsChangeNumber : existingDownstream) {
            try {
              updateDownstreamMerge(
                  mdsMergeInput.currentRevision,
                  mdsMergeInput.subject,
                  dsChangeNumber,
                  mdsMergeInput.dsBranchMap.get(downstreamBranch));
              createDownstreams = false;
            } catch (MergeConflictException e) {
              failedMergeBranchMap.put(downstreamBranch, e.getMessage());
              log.debug("Abandoning existing, obsolete {} due to merge conflict.", dsChangeNumber);
              abandonChange(dsChangeNumber);
            }
          }
        }
      }
      if (createDownstreams) {
        log.debug(
            "Attempting to create downstream merge of {} on branch {}",
            mdsMergeInput.currentRevision,
            downstreamBranch);
        SingleDownstreamMergeInput sdsMergeInput = new SingleDownstreamMergeInput();
        sdsMergeInput.currentRevision = mdsMergeInput.currentRevision;
        sdsMergeInput.changeNumber = mdsMergeInput.changeNumber;
        sdsMergeInput.project = mdsMergeInput.project;
        sdsMergeInput.topic = mdsMergeInput.topic;
        sdsMergeInput.subject = mdsMergeInput.subject;
        sdsMergeInput.downstreamBranch = downstreamBranch;
        sdsMergeInput.doMerge = mdsMergeInput.dsBranchMap.get(downstreamBranch);
        try {
          createSingleDownstreamMerge(sdsMergeInput);
        } catch (MergeConflictException e) {
          failedMergeBranchMap.put(downstreamBranch, e.getMessage());
        }
      }
    }

    if (!failedMergeBranchMap.isEmpty()) {
      throw new FailedMergeException(
          failedMergeBranchMap,
          mdsMergeInput.currentRevision,
          config.getHostName(),
          mdsMergeInput.project,
          mdsMergeInput.changeNumber,
          mdsMergeInput.patchsetNumber,
          config.getConflictMessage(),
          mdsMergeInput.topic);
    }
  }

  /**
   * Get change IDs of the immediately downstream changes of the revision on the branch.
   *
   * @param upstreamRevision Revision of the original change.
   * @param topic Topic of the original change.
   * @param downstreamBranch Branch to check for existing merge CLs.
   * @return List of change numbers that are downstream of the given branch.
   * @throws RestApiException Throws when we fail a REST API call.
   * @throws InvalidQueryParameterException Throws when we try to add an invalid value to the query.
   */
  public List<Integer> getExistingMergesOnBranch(
      String upstreamRevision, String topic, String downstreamBranch)
      throws RestApiException, InvalidQueryParameterException {
    List<Integer> downstreamChangeNumbers = new ArrayList<Integer>();
    List<ChangeInfo> changes = getChangesInTopicAndBranch(topic, downstreamBranch);

    for (ChangeInfo change : changes) {
      String changeRevision = change.currentRevision;
      RevisionInfo revision = change.revisions.get(changeRevision);
      List<CommitInfo> parents = revision.commit.parents;
      if (parents.size() > 1) {
        String secondParent = parents.get(1).commit;
        if (secondParent.equals(upstreamRevision)) {
          downstreamChangeNumbers.add(change._number);
        }
      }
    }
    return downstreamChangeNumbers;
  }

  /**
   * Create a single downstream merge.
   *
   * @param sdsMergeInput Input containing metadata for the merge.
   * @throws RestApiException
   * @throws ConfigInvalidException
   * @throws InvalidQueryParameterException
   */
  public void createSingleDownstreamMerge(SingleDownstreamMergeInput sdsMergeInput)
      throws RestApiException, ConfigInvalidException, InvalidQueryParameterException {
    String currentTopic = getOrSetTopic(sdsMergeInput.changeNumber, sdsMergeInput.topic);

    if (isAlreadyMerged(sdsMergeInput, currentTopic)) {
      log.info(
          "Commit {} already merged into {}, not automerging again.",
          sdsMergeInput.currentRevision,
          sdsMergeInput.downstreamBranch);
      return;
    }

    MergeInput mergeInput = new MergeInput();
    mergeInput.source = sdsMergeInput.currentRevision;
    mergeInput.strategy = "recursive";

    log.debug("Creating downstream merge for {}", sdsMergeInput.currentRevision);
    ChangeInput downstreamChangeInput = new ChangeInput();
    downstreamChangeInput.project = sdsMergeInput.project;
    downstreamChangeInput.branch = sdsMergeInput.downstreamBranch;
    downstreamChangeInput.subject =
        getSubjectForDownstreamMerge(sdsMergeInput.subject, sdsMergeInput.currentRevision, false);
    downstreamChangeInput.topic = currentTopic;
    downstreamChangeInput.merge = mergeInput;
    downstreamChangeInput.notify = NotifyHandling.NONE;

    downstreamChangeInput.baseChange =
        getBaseChangeId(
            getChangeParents(sdsMergeInput.changeNumber, sdsMergeInput.currentRevision),
            sdsMergeInput.downstreamBranch);

    if (!sdsMergeInput.doMerge) {
      mergeInput.strategy = "ours";
      downstreamChangeInput.subject =
          getSubjectForDownstreamMerge(sdsMergeInput.subject, sdsMergeInput.currentRevision, true);
      log.debug(
          "Skipping merge for {} to {}",
          sdsMergeInput.currentRevision,
          sdsMergeInput.downstreamBranch);
    }

    ChangeApi downstreamChange = gApi.changes().create(downstreamChangeInput);

    // Vote maxAutomergeVote on the change so we know it was successful.
    if (!config.maxAutomergeVoteDisabled()) {
      updateVote(downstreamChange.get(), config.getAutomergeLabel(), config.getMaxAutomergeVote());
    }
  }

  public String getOrSetTopic(int sourceId, String topic) throws RestApiException {
    if (isNullOrEmpty(topic)) {
      topic = "am-" + UUID.randomUUID();
      log.debug("Setting original change {} topic to {}", sourceId, topic);
      gApi.changes().id(sourceId).topic(topic);
    }
    return topic;
  }

  /**
   * Get the base change ID that the downstream change should be based off of, given the parents.
   *
   * <p>Given changes A and B where A is the first parent of B, and where A' is the change whose
   * second parent is A, and B' is the change whose second parent is B, the first parent of B'
   * should be A'.
   *
   * @param parents Parent commit SHAs of the change
   * @return The base change ID that the change should be based off of, null if there is none.
   * @throws InvalidQueryParameterException
   * @throws RestApiException
   */
  private String getBaseChangeId(List<String> parents, String branch)
      throws InvalidQueryParameterException, RestApiException {
    if (parents.isEmpty()) {
      log.info("No base change id for change with no parents.");
      return null;
    }
    // 1) Get topic of first parent
    String firstParentTopic = getTopic(parents.get(0));
    if (firstParentTopic == null) {
      return null;
    }
    // 2) query that topic and use that to find A'
    List<ChangeInfo> changesInTopic = getChangesInTopicAndBranch(firstParentTopic, branch);
    String firstParent = parents.get(0);
    for (ChangeInfo change : changesInTopic) {
      List<CommitInfo> topicChangeParents =
          change.revisions.get(change.currentRevision).commit.parents;
      if (topicChangeParents.size() > 1 && topicChangeParents.get(1).commit.equals(firstParent)) {
        return String.valueOf(change._number);
      }
    }
    return null;
  }

  private void automergeChanges(ChangeInfo change, RevisionInfo revisionInfo)
      throws RestApiException, IOException, ConfigInvalidException, InvalidQueryParameterException {
    if (revisionInfo.draft != null && revisionInfo.draft) {
      log.debug("Patchset {} is draft change, ignoring.", revisionInfo.commit.commit);
      return;
    }

    String currentRevision = revisionInfo.commit.commit;
    log.debug(
        "Handling patchsetevent with change id {} and revision {}", change.id, currentRevision);

    Set<String> downstreamBranches = config.getDownstreamBranches(change.branch, change.project);

    if (downstreamBranches.isEmpty()) {
      log.debug("Downstream branches of {} on {} are empty", change.branch, change.project);
      return;
    }

    // Map whether or not we should merge it or skip it for each downstream
    Map<String, Boolean> dsBranchMap = new HashMap<String, Boolean>();
    for (String downstreamBranch : downstreamBranches) {
      boolean isSkipMerge = config.isSkipMerge(change.branch, downstreamBranch, change.subject);
      dsBranchMap.put(downstreamBranch, !isSkipMerge);
    }
    log.debug("Automerging change {} from branch {}", change.id, change.branch);

    ChangeApi currentChange = gApi.changes().id(change._number);
    String previousRevision = getPreviousRevision(currentChange, revisionInfo._number);

    MultipleDownstreamMergeInput mdsMergeInput = new MultipleDownstreamMergeInput();
    mdsMergeInput.dsBranchMap = dsBranchMap;
    mdsMergeInput.changeNumber = change._number;
    mdsMergeInput.patchsetNumber = revisionInfo._number;
    mdsMergeInput.project = change.project;
    mdsMergeInput.topic = getOrSetTopic(change._number, change.topic);
    mdsMergeInput.subject = change.subject;
    mdsMergeInput.obsoleteRevision = previousRevision;
    mdsMergeInput.currentRevision = currentRevision;

    createMergesAndHandleConflicts(mdsMergeInput);
  }

  private void abandonDownstream(ChangeInfo change, String revision) throws ConfigInvalidException {
    try {
      Set<String> downstreamBranches = config.getDownstreamBranches(change.branch, change.project);
      if (downstreamBranches.isEmpty()) {
        log.debug("Downstream branches of {} on {} are empty", change.branch, change.project);
        return;
      }

      for (String downstreamBranch : downstreamBranches) {
        List<Integer> existingDownstream =
            getExistingMergesOnBranch(revision, change.topic, downstreamBranch);
        log.debug("Abandoning existing downstreams: {}", existingDownstream);
        for (Integer changeNumber : existingDownstream) {
          abandonChange(changeNumber);
        }
      }
    } catch (RestApiException | IOException | InvalidQueryParameterException e) {
      log.error("Failed to abandon downstreams of {}", change.id, e);
    }
  }

  private void updateVote(ChangeInfo change, String label, short vote) throws RestApiException {
    log.debug("Giving {} for label {} to {}", vote, label, change.id);
    // Vote on all downstream branches unless merge conflict.
    ReviewInput reviewInput = new ReviewInput();
    Map<String, Short> labels = new HashMap<String, Short>();
    labels.put(label, vote);
    reviewInput.labels = labels;
    reviewInput.notify = NotifyHandling.NONE;
    reviewInput.tag = AUTOMERGER_TAG;
    try {
      gApi.changes().id(change.id).revision(change.currentRevision).review(reviewInput);
    } catch (AuthException e) {
      log.error("Automerger could not set label, but still continuing.", e);
    }
  }

  private void updateDownstreamMerge(
      String newParentRevision, String upstreamSubject, Integer sourceNum, boolean doMerge)
      throws RestApiException, ConfigInvalidException {
    MergeInput mergeInput = new MergeInput();
    mergeInput.source = newParentRevision;

    MergePatchSetInput mergePatchSetInput = new MergePatchSetInput();

    mergePatchSetInput.subject =
        getSubjectForDownstreamMerge(upstreamSubject, newParentRevision, false);
    if (!doMerge) {
      mergeInput.strategy = "ours";
      mergePatchSetInput.subject =
          getSubjectForDownstreamMerge(upstreamSubject, newParentRevision, true);
      log.debug("Skipping merge for {} on {}", newParentRevision, sourceNum);
    }
    mergePatchSetInput.merge = mergeInput;

    ChangeApi originalChange = gApi.changes().id(sourceNum);

    if (originalChange.info().status == ChangeStatus.ABANDONED) {
      RestoreInput restoreInput = new RestoreInput();
      restoreInput.message = "Restoring change due to upstream automerge.";
      originalChange.restore(restoreInput);
    }

    ChangeInfo downstreamChange = originalChange.createMergePatchSet(mergePatchSetInput);
    if (!config.maxAutomergeVoteDisabled()) {
      updateVote(downstreamChange, config.getAutomergeLabel(), config.getMaxAutomergeVote());
    }
  }

  private String getPreviousRevision(ChangeApi change, int currentPatchSetNumber)
      throws RestApiException {
    String previousRevision = null;
    int maxPatchSetNum = 0;
    if (currentPatchSetNumber > 1) {
      // Get sha of patch set with highest number we can see
      Map<String, RevisionInfo> revisionMap =
          change.get(EnumSet.of(ListChangesOption.ALL_REVISIONS)).revisions;
      for (Map.Entry<String, RevisionInfo> revisionEntry : revisionMap.entrySet()) {
        int revisionPatchNumber = revisionEntry.getValue()._number;
        if (revisionPatchNumber > maxPatchSetNum && revisionPatchNumber < currentPatchSetNumber) {
          previousRevision = revisionEntry.getKey();
          maxPatchSetNum = revisionPatchNumber;
        }
      }
    }
    return previousRevision;
  }

  private List<String> getChangeParents(int changeNumber, String currentRevision)
      throws RestApiException {
    ChangeApi change = gApi.changes().id(changeNumber);
    List<String> parents = new ArrayList<>();
    Map<String, RevisionInfo> revisionMap =
        change.get(EnumSet.of(ListChangesOption.ALL_REVISIONS, ListChangesOption.CURRENT_COMMIT))
            .revisions;
    List<CommitInfo> changeParents = revisionMap.get(currentRevision).commit.parents;
    for (CommitInfo commit : changeParents) {
      parents.add(commit.commit);
    }
    return parents;
  }

  private void abandonChange(Integer changeNumber) throws RestApiException {
    log.debug("Abandoning change: {}", changeNumber);
    AbandonInput abandonInput = new AbandonInput();
    abandonInput.notify = NotifyHandling.NONE;
    abandonInput.message = "Merge parent updated; abandoning due to upstream conflict.";
    gApi.changes().id(changeNumber).abandon(abandonInput);
  }

  private String getTopic(String revision) throws InvalidQueryParameterException, RestApiException {
    QueryBuilder queryBuilder = new QueryBuilder();
    queryBuilder.addParameter("commit", revision);
    List<ChangeInfo> changes =
        gApi.changes()
            .query(queryBuilder.get())
            .withOption(ListChangesOption.CURRENT_REVISION)
            .get();
    if (!changes.isEmpty()) {
      for (ChangeInfo change : changes) {
        if (change.currentRevision.equals(revision) && !"".equals(change.topic)) {
          return change.topic;
        }
      }
    }
    return null;
  }

  private List<ChangeInfo> getChangesInTopicAndBranch(String topic, String downstreamBranch)
      throws InvalidQueryParameterException, RestApiException {
    QueryBuilder queryBuilder = new QueryBuilder();
    queryBuilder.addParameter("topic", topic);
    queryBuilder.addParameter("branch", downstreamBranch);
    queryBuilder.addParameter("status", "open");
    return gApi.changes()
        .query(queryBuilder.get())
        .withOptions(ListChangesOption.ALL_REVISIONS, ListChangesOption.CURRENT_COMMIT)
        .get();
  }

  private boolean isAlreadyMerged(SingleDownstreamMergeInput sdsMergeInput, String currentTopic)
      throws InvalidQueryParameterException, RestApiException {
    // If we've already merged this commit to this branch, don't do it again.
    List<ChangeInfo> changes =
        getChangesInTopicAndBranch(currentTopic, sdsMergeInput.downstreamBranch);
    for (ChangeInfo change : changes) {
      if (change.branch.equals(sdsMergeInput.downstreamBranch)) {
        List<CommitInfo> parents = change.revisions.get(change.currentRevision).commit.parents;
        if (parents.size() > 1) {
          String secondParent = parents.get(1).commit;
          if (secondParent.equals(sdsMergeInput.currentRevision)) {
            return true;
          }
        }
      }
    }
    return false;
  }

  /**
   * Create subject line for downstream merge with metadata from upstream change.
   *
   * <p>The downstream subject will be in the format: "[automerger] upstreamSubject am:
   * upstreamRevision". If it is a skip, "am" will be replaced with "skipped". [automerger] will not
   * be repeated for changes with multiple downstreams.
   *
   * @param upstreamSubject Subject line of the upstream change
   * @param upstreamRevision Commit SHA1 of the upstream change
   * @param skipped Whether or not the merge is done with "-s ours"
   * @return Subject line for downstream merge
   */
  private String getSubjectForDownstreamMerge(
      String upstreamSubject, String upstreamRevision, boolean skipped) {
    if (!upstreamSubject.startsWith(SUBJECT_PREFIX)) {
      upstreamSubject = Joiner.on(" ").join(SUBJECT_PREFIX, upstreamSubject);
    }
    String denotationString = skipped ? "skipped:" : "am:";
    return Joiner.on(" ")
        .join(upstreamSubject, denotationString, upstreamRevision.substring(0, 10));
  }
}
