// 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.ChangeMergedListener;
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.UUID;
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,
        ChangeMergedListener,
        ChangeRestoredListener,
        CommentAddedListener,
        DraftPublishedListener,
        RevisionCreatedListener,
        TopicEditedListener {
  private static final Logger log = LoggerFactory.getLogger(DownstreamCreator.class);

  protected GerritApi gApi;
  protected ConfigLoader config;

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

  /**
   * Updates the config in memory if the config project is updated.
   *
   * @param event Event we are listening to.
   */
  @Override
  public void onChangeMerged(ChangeMergedListener.Event event) {
    ChangeInfo change = event.getChange();
    try {
      if (change.project.equals(config.configProject)
          && change.branch.equals(config.configProjectBranch)) {
        loadConfig();
      }
    } catch (RestApiException | IOException e) {
      log.error("Failed to reload config at {}", change.id, e);
    }
  }

  /**
   * 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);
    abandonDownstream(change, revision);
  }

  /**
   * 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 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 e) {
        log.error("RestApiException when editing 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 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 e) {
        log.error("RestApiException 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 e) {
      log.error("Failed to edit downstream topics of {}", 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 e) {
      log.error("Failed to edit downstream topics of {}", 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 e) {
      log.error("Failed to edit downstream topics of {}", change.id, e);
    }
  }

  /**
   * Creates merges downstream, and votes -1 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.
   */
  public void createMergesAndHandleConflicts(MultipleDownstreamMergeInput mdsMergeInput)
      throws RestApiException {
    ReviewInput reviewInput = new ReviewInput();
    Map<String, Short> labels = new HashMap<String, Short>();
    short vote = 0;
    try {
      createDownstreamMerges(mdsMergeInput);

      reviewInput.message =
          "Automerging to "
              + Joiner.on(", ").join(mdsMergeInput.dsBranchMap.keySet())
              + " succeeded!";
      reviewInput.notify = NotifyHandling.NONE;
    } catch (FailedMergeException e) {
      reviewInput.message = e.displayConflicts();
      reviewInput.notify = NotifyHandling.ALL;
      vote = -1;
    }
    // Zero out automerge label if success, -1 vote if fail.
    labels.put(config.getAutomergeLabel(), vote);
    reviewInput.labels = labels;
    gApi.changes()
        .id(mdsMergeInput.sourceId)
        .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.
   */
  public void createDownstreamMerges(MultipleDownstreamMergeInput mdsMergeInput)
      throws RestApiException, FailedMergeException {
    Map<String, String> failedMerges = new HashMap<String, String>();

    List<Integer> existingDownstream;
    for (String downstreamBranch : mdsMergeInput.dsBranchMap.keySet()) {
      // If there are existing downstream merges, update them
      // Otherwise, create them.
      try {
        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) {
              updateDownstreamMerge(
                  mdsMergeInput.currentRevision,
                  mdsMergeInput.subject,
                  dsChangeNumber,
                  mdsMergeInput.dsBranchMap.get(downstreamBranch));
              createDownstreams = false;
            }
          }
        }
        if (createDownstreams) {
          log.debug(
              "Attempting to create downstream merge of {} on branch {}",
              mdsMergeInput.currentRevision,
              downstreamBranch);
          SingleDownstreamMergeInput sdsMergeInput = new SingleDownstreamMergeInput();
          sdsMergeInput.currentRevision = mdsMergeInput.currentRevision;
          sdsMergeInput.sourceId = mdsMergeInput.sourceId;
          sdsMergeInput.project = mdsMergeInput.project;
          sdsMergeInput.topic = mdsMergeInput.topic;
          sdsMergeInput.subject = mdsMergeInput.subject;
          sdsMergeInput.downstreamBranch = downstreamBranch;
          sdsMergeInput.doMerge = mdsMergeInput.dsBranchMap.get(downstreamBranch);
          createSingleDownstreamMerge(sdsMergeInput);
        }
      } catch (MergeConflictException e) {
        log.debug("Merge conflict from {} to {}", mdsMergeInput.currentRevision, downstreamBranch);
        failedMerges.put(downstreamBranch, e.getMessage());
        log.debug("Abandoning downstream of {}", mdsMergeInput.sourceId);
        abandonDownstream(
            gApi.changes().id(mdsMergeInput.sourceId).info(), mdsMergeInput.currentRevision);
      }
    }

    if (!failedMerges.keySet().isEmpty()) {
      throw new FailedMergeException(failedMerges);
    }
  }

  /**
   * 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.
   */
  public List<Integer> getExistingMergesOnBranch(
      String upstreamRevision, String topic, String downstreamBranch) throws RestApiException {
    List<Integer> downstreamChangeNumbers = new ArrayList<Integer>();
    // get changes in same topic and check if their parent is upstreamRevision
    String query = "topic:" + topic + " status:open branch:" + downstreamBranch;
    List<ChangeInfo> changes =
        gApi.changes()
            .query(query)
            .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
   */
  public void createSingleDownstreamMerge(SingleDownstreamMergeInput sdsMergeInput)
      throws RestApiException {

    String currentTopic = setTopic(sdsMergeInput.sourceId, 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;

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

    gApi.changes().create(downstreamChangeInput);
  }

  private void loadConfig() throws IOException, RestApiException {
    try {
      config.loadConfig();
    } catch (IOException | RestApiException e) {
      log.error("Config failed to sync!", e);
      throw e;
    }
  }

  private void automergeChanges(ChangeInfo change, RevisionInfo revisionInfo)
      throws RestApiException, IOException {
    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.sourceId = change.id;
    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) {
    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 e) {
      log.error("Failed to abandon downstreams of {}", change.id, e);
    }
  }

  private void updateVote(ChangeInfo change, String label, short vote) throws RestApiException {
    if (label.equals(config.getAutomergeLabel())) {
      log.debug("Not updating automerge label, as it blocks when there is a merge conflict.");
      return;
    }
    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;
    gApi.changes().id(change.id).revision(change.currentRevision).review(reviewInput);
  }

  private void updateDownstreamMerge(
      String newParentRevision, String upstreamSubject, Integer sourceNum, boolean doMerge)
      throws RestApiException {
    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);
    }

    originalChange.createMergePatchSet(mergePatchSetInput);
  }

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

  private String setTopic(String 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;
  }
}
