// Copyright (C) 2017 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.git;

import static com.google.common.base.MoreObjects.firstNonNull;
import static com.google.gerrit.server.mail.EmailFactories.CHANGE_REVERTED;
import static com.google.gerrit.server.update.context.RefUpdateContext.RefUpdateType.CHANGE_MODIFICATION;

import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.extensions.api.changes.NotifyHandling;
import com.google.gerrit.extensions.api.changes.RevertInput;
import com.google.gerrit.extensions.common.CommitInfo;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
import com.google.gerrit.server.ChangeMessagesUtil;
import com.google.gerrit.server.ChangeUtil;
import com.google.gerrit.server.CommonConverters;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.ReviewerSet;
import com.google.gerrit.server.Sequences;
import com.google.gerrit.server.approval.ApprovalsUtil;
import com.google.gerrit.server.change.ChangeInserter;
import com.google.gerrit.server.change.ChangeMessages;
import com.google.gerrit.server.change.NotifyResolver;
import com.google.gerrit.server.change.ValidationOptionsUtil;
import com.google.gerrit.server.extensions.events.ChangeReverted;
import com.google.gerrit.server.git.CodeReviewCommit.CodeReviewRevWalk;
import com.google.gerrit.server.mail.EmailFactories;
import com.google.gerrit.server.mail.send.ChangeEmail;
import com.google.gerrit.server.mail.send.MessageIdGenerator;
import com.google.gerrit.server.mail.send.OutgoingEmail;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.notedb.ReviewerStateInternal;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.InternalChangeQuery;
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.PostUpdateContext;
import com.google.gerrit.server.update.UpdateException;
import com.google.gerrit.server.update.context.RefUpdateContext;
import com.google.gerrit.server.util.CommitMessageUtil;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.io.IOException;
import java.text.MessageFormat;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.errors.InvalidObjectIdException;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.CommitBuilder;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.FooterLine;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.util.ChangeIdUtil;

/** Static utilities for working with {@link RevCommit}s. */
@Singleton
public class CommitUtil {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  private final GitRepositoryManager repoManager;
  private final Provider<PersonIdent> serverIdent;
  private final Sequences seq;
  private final ApprovalsUtil approvalsUtil;
  private final ChangeInserter.Factory changeInserterFactory;
  private final NotifyResolver notifyResolver;
  private final EmailFactories emailFactories;
  private final ChangeMessagesUtil cmUtil;
  private final ChangeNotes.Factory changeNotesFactory;
  private final ChangeReverted changeReverted;
  private final BatchUpdate.Factory updateFactory;
  private final MessageIdGenerator messageIdGenerator;

  @Inject
  CommitUtil(
      GitRepositoryManager repoManager,
      @GerritPersonIdent Provider<PersonIdent> serverIdent,
      Sequences seq,
      ApprovalsUtil approvalsUtil,
      ChangeInserter.Factory changeInserterFactory,
      NotifyResolver notifyResolver,
      EmailFactories emailFactories,
      ChangeMessagesUtil cmUtil,
      ChangeNotes.Factory changeNotesFactory,
      ChangeReverted changeReverted,
      BatchUpdate.Factory updateFactory,
      MessageIdGenerator messageIdGenerator) {
    this.repoManager = repoManager;
    this.serverIdent = serverIdent;
    this.seq = seq;
    this.approvalsUtil = approvalsUtil;
    this.changeInserterFactory = changeInserterFactory;
    this.notifyResolver = notifyResolver;
    this.emailFactories = emailFactories;
    this.cmUtil = cmUtil;
    this.changeNotesFactory = changeNotesFactory;
    this.changeReverted = changeReverted;
    this.updateFactory = updateFactory;
    this.messageIdGenerator = messageIdGenerator;
  }

  public static CommitInfo toCommitInfo(RevCommit commit) throws IOException {
    return toCommitInfo(commit, null);
  }

  public static CommitInfo toCommitInfo(RevCommit commit, @Nullable RevWalk walk)
      throws IOException {
    CommitInfo info = new CommitInfo();
    info.commit = commit.getName();
    info.author = CommonConverters.toGitPerson(commit.getAuthorIdent());
    info.committer = CommonConverters.toGitPerson(commit.getCommitterIdent());
    info.subject = commit.getShortMessage();
    info.message = commit.getFullMessage();
    info.parents = new ArrayList<>(commit.getParentCount());
    for (int i = 0; i < commit.getParentCount(); i++) {
      RevCommit p = walk == null ? commit.getParent(i) : walk.parseCommit(commit.getParent(i));
      CommitInfo parentInfo = new CommitInfo();
      parentInfo.commit = p.getName();
      parentInfo.subject = p.getShortMessage();
      info.parents.add(parentInfo);
    }
    return info;
  }

  /**
   * Allows creating a revert change.
   *
   * @param notes ChangeNotes of the change being reverted.
   * @param user Current User performing the revert.
   * @param input the RevertInput entity for conducting the revert.
   * @param timestamp timestamp for the created change.
   * @return ObjectId that represents the newly created commit.
   */
  public Change.Id createRevertChange(
      ChangeNotes notes, CurrentUser user, RevertInput input, Instant timestamp)
      throws RestApiException, UpdateException, ConfigInvalidException, IOException {
    String message = Strings.emptyToNull(input.message);
    try (RefUpdateContext ctx = RefUpdateContext.open(CHANGE_MODIFICATION)) {
      try (Repository git = repoManager.openRepository(notes.getProjectName());
          ObjectInserter oi = git.newObjectInserter();
          ObjectReader reader = oi.newReader();
          CodeReviewRevWalk revWalk = CodeReviewCommit.newRevWalk(reader)) {
        ObjectId generatedChangeId = CommitMessageUtil.generateChangeId();
        CodeReviewCommit revertCommit =
            createRevertCommit(message, notes, user, timestamp, oi, revWalk, generatedChangeId);
        return createRevertChangeFromCommit(
            revertCommit, input, notes, user, generatedChangeId, timestamp, oi, revWalk, git);
      } catch (RepositoryNotFoundException e) {
        throw new ResourceNotFoundException(notes.getChangeId().toString(), e);
      }
    }
  }

  /**
   * Wrapper function for creating a revert Commit.
   *
   * @param message Commit message for the revert commit.
   * @param notes ChangeNotes of the change being reverted.
   * @param user Current User performing the revert.
   * @param ts Timestamp of creation for the commit.
   * @return that newly created revert commit.
   */
  public CodeReviewCommit createRevertCommit(
      String message, ChangeNotes notes, CurrentUser user, Instant ts)
      throws RestApiException, IOException {

    try (Repository git = repoManager.openRepository(notes.getProjectName());
        ObjectInserter oi = git.newObjectInserter();
        ObjectReader reader = oi.newReader();
        CodeReviewRevWalk revWalk = CodeReviewCommit.newRevWalk(reader)) {
      return createRevertCommit(message, notes, user, ts, oi, revWalk, null);
    } catch (RepositoryNotFoundException e) {
      throw new ResourceNotFoundException(notes.getProjectName().toString(), e);
    }
  }

  /**
   * Creates a commit with the specified tree ID.
   *
   * @param oi ObjectInserter for inserting the newly created commit.
   * @param authorIdent of the new commit
   * @param committerIdent of the new commit
   * @param parents of the new commit. Can be empty.
   * @param commitMessage for the new commit.
   * @param treeId of the content for the new commit.
   * @return the newly created commit.
   * @throws IOException if fails to insert the commit.
   */
  public static ObjectId createCommitWithTree(
      ObjectInserter oi,
      PersonIdent authorIdent,
      PersonIdent committerIdent,
      List<RevCommit> parents,
      String commitMessage,
      ObjectId treeId)
      throws IOException {
    logger.atFine().log("Creating commit with tree: %s", treeId.getName());
    CommitBuilder commit = new CommitBuilder();
    commit.setTreeId(treeId);
    commit.setParentIds(parents.stream().map(RevCommit::getId).collect(Collectors.toList()));
    commit.setAuthor(authorIdent);
    commit.setCommitter(committerIdent);
    commit.setMessage(commitMessage);

    ObjectId id = oi.insert(commit);
    oi.flush();
    return id;
  }

  public static String getBugAndIssueFooters(RevCommit commit) {
    StringBuilder footers = new StringBuilder();
    for (FooterLine footerLine : commit.getFooterLines()) {
      String key = footerLine.getKey();
      if (key.equalsIgnoreCase("Bug") || key.equalsIgnoreCase("Issue")) {
        footers.append(footerLine.getKey()).append(": ").append(footerLine.getValue()).append("\n");
      }
    }
    return footers.toString();
  }

  /**
   * Creates a revert commit.
   *
   * @param message Commit message for the revert commit.
   * @param notes ChangeNotes of the change being reverted.
   * @param user Current User performing the revert.
   * @param ts Timestamp of creation for the commit.
   * @param oi ObjectInserter for inserting the newly created commit.
   * @param revWalk Used for parsing the original commit.
   * @param generatedChangeId The changeId for the commit message, can be null since it is not
   *     needed for commits, only for changes.
   * @return ObjectId that represents the newly created commit.
   * @throws ResourceConflictException Can't revert the initial commit.
   * @throws IOException Thrown in case of I/O errors.
   */
  private CodeReviewCommit createRevertCommit(
      String message,
      ChangeNotes notes,
      CurrentUser user,
      Instant ts,
      ObjectInserter oi,
      CodeReviewRevWalk revWalk,
      @Nullable ObjectId generatedChangeId)
      throws ResourceConflictException, IOException {

    PatchSet patch = notes.getCurrentPatchSet();
    RevCommit commitToRevert = revWalk.parseCommit(patch.commitId());
    if (commitToRevert.getParentCount() == 0) {
      throw new ResourceConflictException("Cannot revert initial commit");
    }

    PersonIdent committerIdent = serverIdent.get();
    PersonIdent authorIdent =
        user.asIdentifiedUser().newCommitterIdent(ts, committerIdent.getZoneId());

    RevCommit parentToCommitToRevert = commitToRevert.getParent(0);
    revWalk.parseHeaders(parentToCommitToRevert);

    Change changeToRevert = notes.getChange();
    String subject = changeToRevert.getSubject();
    if (subject.length() > 63) {
      subject = subject.substring(0, 59) + "...";
    }
    if (message == null) {
      message =
          MessageFormat.format(
              ChangeMessages.revertChangeDefaultMessage, subject, patch.commitId().name());
    }

    String newFooters = getBugAndIssueFooters(commitToRevert);
    if (!newFooters.isEmpty()) {
      StringBuilder footersToAdd = new StringBuilder();
      for (String footer : Splitter.on('\n').split(newFooters)) {
        if (footer.isEmpty()) {
          continue;
        }
        boolean alreadyExists =
            Arrays.stream(message.split("\n"))
                .anyMatch(line -> line.trim().equalsIgnoreCase(footer.trim()));
        if (!alreadyExists) {
          footersToAdd.append(footer).append("\n");
        }
      }

      if (footersToAdd.length() > 0) {
        String trimmedMsg = message.trim();
        List<String> lines = Splitter.on('\n').splitToList(trimmedMsg);
        String lastLine = lines.isEmpty() ? "" : lines.get(lines.size() - 1);
        boolean endsWithFooter = lastLine.matches("^[a-zA-Z0-9-]+:.*");

        if (endsWithFooter) {
          message = trimmedMsg + "\n" + footersToAdd.toString().trim();
        } else {
          message = trimmedMsg + "\n\n" + footersToAdd.toString().trim();
        }
      }
    }

    if (generatedChangeId != null) {
      message = ChangeIdUtil.insertId(message, generatedChangeId, true);
    }

    CodeReviewCommit revertCommit =
        revWalk.parseCommit(
            createCommitWithTree(
                oi,
                authorIdent,
                committerIdent,
                ImmutableList.of(commitToRevert),
                message,
                parentToCommitToRevert.getTree()));

    // The revert commit is based on the commit that is being reverted and has the same tree as the
    // parent of the commit that is being reverted. This means revert commit never contains any
    // conflicts.
    revertCommit.setNoConflictsForNonMergeCommit();

    return revertCommit;
  }

  private Change.Id createRevertChangeFromCommit(
      CodeReviewCommit revertCommit,
      RevertInput input,
      ChangeNotes notes,
      CurrentUser user,
      @Nullable ObjectId generatedChangeId,
      Instant ts,
      ObjectInserter oi,
      RevWalk revWalk,
      Repository git)
      throws IOException, RestApiException, UpdateException, ConfigInvalidException {
    Change.Id changeId = Change.id(seq.nextChangeId());
    if (input.getWorkInProgress()) {
      input.notify = firstNonNull(input.notify, NotifyHandling.NONE);
    }
    NotifyResolver.Result notify =
        notifyResolver.resolve(firstNonNull(input.notify, NotifyHandling.ALL), input.notifyDetails);

    Change changeToRevert = notes.getChange();
    ChangeInserter ins =
        changeInserterFactory
            .create(changeId, revertCommit, changeToRevert.getDest().branch())
            .setTopic(input.topic == null ? changeToRevert.getTopic() : input.topic.trim());
    ins.setMessage("Uploaded patch set 1.");
    ins.setValidationOptions(
        ValidationOptionsUtil.getValidateOptionsAsMultimap(input.validationOptions));

    ReviewerSet reviewerSet = approvalsUtil.getReviewers(notes);

    Set<Account.Id> reviewers = new HashSet<>();
    reviewers.add(changeToRevert.getOwner());
    reviewers.addAll(reviewerSet.byState(ReviewerStateInternal.REVIEWER));
    reviewers.remove(user.getAccountId());
    Set<Account.Id> ccs = new HashSet<>(reviewerSet.byState(ReviewerStateInternal.CC));
    ccs.remove(user.getAccountId());
    ins.setReviewersAndCcsIgnoreVisibility(reviewers, ccs);
    ins.setRevertOf(notes.getChangeId());
    ins.setWorkInProgress(input.getWorkInProgress());
    revertCommit.getConflicts().ifPresent(ins::setConflicts);

    try (BatchUpdate bu = updateFactory.create(notes.getProjectName(), user, ts)) {
      bu.setRepository(git, revWalk, oi);
      bu.setNotify(notify);
      bu.insertChange(ins);
      if (!input.getWorkInProgress()) {
        addChangeRevertedNotificationOps(
            bu, changeToRevert.getId(), changeId, generatedChangeId.name());
      }
      bu.execute();
    }
    return changeId;
  }

  /**
   * Notify the owners of a change that their change is being reverted.
   *
   * @param bu to append the notification actions to.
   * @param revertedChangeId to be notified.
   * @param revertingChangeId to notify about.
   * @param revertingChangeKey to notify about.
   */
  public void addChangeRevertedNotificationOps(
      BatchUpdate bu,
      Change.Id revertedChangeId,
      Change.Id revertingChangeId,
      String revertingChangeKey) {
    bu.addOp(revertingChangeId, new ChangeRevertedNotifyOp(revertedChangeId, revertingChangeId));
    bu.addOp(revertedChangeId, new PostRevertedMessageOp(revertingChangeKey));
  }

  private class ChangeRevertedNotifyOp implements BatchUpdateOp {
    private final Change.Id revertedChangeId;
    private final Change.Id revertingChangeId;

    ChangeRevertedNotifyOp(Change.Id revertedChangeId, Change.Id revertingChangeId) {
      this.revertedChangeId = revertedChangeId;
      this.revertingChangeId = revertingChangeId;
    }

    @Override
    public void postUpdate(PostUpdateContext ctx) throws Exception {
      ChangeData revertedChange =
          ctx.getChangeData(changeNotesFactory.createChecked(ctx.getProject(), revertedChangeId));
      ChangeData revertingChange =
          ctx.getChangeData(changeNotesFactory.createChecked(ctx.getProject(), revertingChangeId));
      changeReverted.fire(revertedChange, revertingChange, ctx.getWhen());
      try {
        ChangeEmail changeEmail =
            emailFactories.createChangeEmail(
                ctx.getProject(),
                revertedChange.getId(),
                emailFactories.createRevertedChangeEmail());
        OutgoingEmail outgoingEmail =
            emailFactories.createOutgoingEmail(CHANGE_REVERTED, changeEmail);
        outgoingEmail.setFrom(ctx.getAccountId());
        outgoingEmail.setNotify(ctx.getNotify(revertedChangeId));
        outgoingEmail.setMessageId(
            messageIdGenerator.fromChangeUpdate(
                ctx.getRepoView(), revertedChange.currentPatchSet().id()));
        outgoingEmail.send();
      } catch (Exception err) {
        logger.atSevere().withCause(err).log(
            "Cannot send email for revert change %s", revertedChangeId);
      }
    }
  }

  private class PostRevertedMessageOp implements BatchUpdateOp {
    private final String revertingChangeKey;

    PostRevertedMessageOp(String revertingChangeKey) {
      this.revertingChangeKey = revertingChangeKey;
    }

    @Override
    public boolean updateChange(ChangeContext ctx) {
      cmUtil.setChangeMessage(
          ctx,
          "Created a revert of this change as I" + revertingChangeKey,
          ChangeMessagesUtil.TAG_REVERT);
      return true;
    }
  }

  /**
   * Returns the parent commit for a new commit.
   *
   * <p>If {@code baseSha1} is provided, the method verifies it can be used as a base. If {@code
   * baseSha1} is not provided the tip of the {@code destRef} is returned.
   *
   * @param project The name of the project.
   * @param changeQuery Used for looking up the base commit.
   * @param revWalk Used for parsing the base commit.
   * @param destRef The destination branch.
   * @param baseSha1 The hash of the base commit. Nullable.
   * @return the base commit. Either the commit matching the provided hash, or the direct parent if
   *     a hash was not provided.
   * @throws IOException if the branch reference cannot be parsed.
   * @throws RestApiException if the base commit cannot be fetched.
   */
  public static RevCommit getBaseCommit(
      String project,
      InternalChangeQuery changeQuery,
      RevWalk revWalk,
      Ref destRef,
      @Nullable String baseSha1)
      throws IOException, RestApiException {
    RevCommit destRefTip = revWalk.parseCommit(destRef.getObjectId());
    // The tip commit of the destination ref is the default base for the newly created change.
    if (Strings.isNullOrEmpty(baseSha1)) {
      return destRefTip;
    }

    ObjectId baseObjectId;
    try {
      baseObjectId = ObjectId.fromString(baseSha1);
    } catch (InvalidObjectIdException e) {
      throw new BadRequestException(
          String.format("Base %s doesn't represent a valid SHA-1", baseSha1), e);
    }

    RevCommit baseCommit;
    try {
      baseCommit = revWalk.parseCommit(baseObjectId);
    } catch (MissingObjectException e) {
      throw new UnprocessableEntityException(
          String.format("Base %s doesn't exist", baseObjectId.name()), e);
    }

    changeQuery.enforceVisibility(true);
    List<ChangeData> changeDatas = changeQuery.byBranchCommit(project, destRef.getName(), baseSha1);

    if (changeDatas.isEmpty()) {
      if (revWalk.isMergedInto(baseCommit, destRefTip)) {
        // The base commit is a merged commit with no change associated.
        return baseCommit;
      }
      throw new UnprocessableEntityException(
          String.format("Commit %s does not exist on branch %s", baseSha1, destRef.getName()));
    } else if (changeDatas.size() != 1) {
      throw new ResourceConflictException("Multiple changes found for commit " + baseSha1);
    }

    Change change = changeDatas.get(0).change();
    if (!change.isAbandoned()) {
      // The base commit is a valid change revision.
      return baseCommit;
    }

    throw new ResourceConflictException(
        String.format(
            "Change %s with commit %s is %s",
            change.getChangeId(), baseSha1, ChangeUtil.status(change)));
  }
}
