// 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 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.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";

  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 change = event.getChange();
    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;
    }

    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.
      labels.put(config.getAutomergeLabel(), config.getMinAutomergeVote());
    }
    reviewInput.labels = labels;
    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>();
    QueryBuilder queryBuilder = new QueryBuilder();
    queryBuilder.addParameter("topic", topic);
    queryBuilder.addParameter("branch", downstreamBranch);
    queryBuilder.addParameter("status", "open");
    // get changes in same topic and check if their parent is upstreamRevision
    List<ChangeInfo> changes =
        gApi.changes()
            .query(queryBuilder.get())
            .withOptions(ListChangesOption.ALL_REVISIONS, ListChangesOption.CURRENT_COMMIT)
            .get();

    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
   */
  public void createSingleDownstreamMerge(SingleDownstreamMergeInput sdsMergeInput)
      throws RestApiException, ConfigInvalidException {
    String currentTopic = getOrSetTopic(sdsMergeInput.changeNumber, sdsMergeInput.topic);

    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 =
        sdsMergeInput.subject + " am: " + sdsMergeInput.currentRevision.substring(0, 10);
    downstreamChangeInput.topic = currentTopic;
    downstreamChangeInput.merge = mergeInput;
    downstreamChangeInput.notify = NotifyHandling.NONE;

    if (!sdsMergeInput.doMerge) {
      mergeInput.strategy = "ours";
      downstreamChangeInput.subject =
          sdsMergeInput.subject + " skipped: " + sdsMergeInput.currentRevision.substring(0, 10);
      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.
    updateVote(downstreamChange.get(), config.getAutomergeLabel(), config.getMaxAutomergeVote());
  }

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

  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 = 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;
    gApi.changes().id(change.id).revision(change.currentRevision).review(reviewInput);
  }

  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 = upstreamSubject + " am: " + newParentRevision.substring(0, 10);
    if (!doMerge) {
      mergeInput.strategy = "ours";
      mergePatchSetInput.subject =
          upstreamSubject + " skipped: " + newParentRevision.substring(0, 10);
      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);
    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 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);
  }
}
