// Copyright (C) 2014 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.edit;

import static com.google.common.base.Preconditions.checkState;

import com.google.common.base.Strings;
import com.google.gerrit.common.FooterConstants;
import com.google.gerrit.common.TimeUtil;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.MergeConflictException;
import com.google.gerrit.extensions.restapi.RawInput;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.PatchSetUtil;
import com.google.gerrit.server.edit.tree.ChangeFileContentModification;
import com.google.gerrit.server.edit.tree.DeleteFileModification;
import com.google.gerrit.server.edit.tree.RenameFileModification;
import com.google.gerrit.server.edit.tree.RestoreFileModification;
import com.google.gerrit.server.edit.tree.TreeCreator;
import com.google.gerrit.server.edit.tree.TreeModification;
import com.google.gerrit.server.index.change.ChangeIndexer;
import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.project.InvalidChangeOperationException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.Optional;
import java.util.TimeZone;
import org.eclipse.jgit.lib.BatchRefUpdate;
import org.eclipse.jgit.lib.CommitBuilder;
import org.eclipse.jgit.lib.NullProgressMonitor;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.merge.MergeStrategy;
import org.eclipse.jgit.merge.ThreeWayMerger;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevTree;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.transport.ReceiveCommand;

/**
 * Utility functions to manipulate change edits.
 *
 * <p>This class contains methods to modify edit's content. For retrieving, publishing and deleting
 * edit see {@link ChangeEditUtil}.
 *
 * <p>
 */
@Singleton
public class ChangeEditModifier {

  private final TimeZone tz;
  private final ChangeIndexer indexer;
  private final Provider<ReviewDb> reviewDb;
  private final Provider<CurrentUser> currentUser;
  private final ChangeEditUtil changeEditUtil;
  private final PatchSetUtil patchSetUtil;

  @Inject
  ChangeEditModifier(
      @GerritPersonIdent PersonIdent gerritIdent,
      ChangeIndexer indexer,
      Provider<ReviewDb> reviewDb,
      Provider<CurrentUser> currentUser,
      ChangeEditUtil changeEditUtil,
      PatchSetUtil patchSetUtil) {
    this.indexer = indexer;
    this.reviewDb = reviewDb;
    this.currentUser = currentUser;
    this.tz = gerritIdent.getTimeZone();
    this.changeEditUtil = changeEditUtil;
    this.patchSetUtil = patchSetUtil;
  }

  /**
   * Creates a new change edit.
   *
   * @param repository the affected Git repository
   * @param changeControl the {@code ChangeControl} of the change for which the change edit should
   *     be created
   * @throws AuthException if the user isn't authenticated or not allowed to use change edits
   * @throws InvalidChangeOperationException if a change edit already existed for the change
   */
  public void createEdit(Repository repository, ChangeControl changeControl)
      throws AuthException, IOException, InvalidChangeOperationException, OrmException {
    ensureAuthenticatedAndPermitted(changeControl);

    Optional<ChangeEdit> changeEdit = lookupChangeEdit(changeControl);
    if (changeEdit.isPresent()) {
      throw new InvalidChangeOperationException(
          String.format("A change edit already exists for change %s", changeControl.getId()));
    }

    PatchSet currentPatchSet = lookupCurrentPatchSet(changeControl);
    ObjectId patchSetCommitId = getPatchSetCommitId(currentPatchSet);
    createEditReference(
        repository, changeControl, currentPatchSet, patchSetCommitId, TimeUtil.nowTs());
  }

  /**
   * Rebase change edit on latest patch set
   *
   * @param repository the affected Git repository
   * @param changeControl the {@code ChangeControl} of the change whose change edit should be
   *     rebased
   * @throws AuthException if the user isn't authenticated or not allowed to use change edits
   * @throws InvalidChangeOperationException if a change edit doesn't exist for the specified
   *     change, the change edit is already based on the latest patch set, or the change represents
   *     the root commit
   * @throws MergeConflictException if rebase fails due to merge conflicts
   */
  public void rebaseEdit(Repository repository, ChangeControl changeControl)
      throws AuthException, InvalidChangeOperationException, IOException, OrmException,
          MergeConflictException {
    ensureAuthenticatedAndPermitted(changeControl);

    Optional<ChangeEdit> optionalChangeEdit = lookupChangeEdit(changeControl);
    if (!optionalChangeEdit.isPresent()) {
      throw new InvalidChangeOperationException(
          String.format("No change edit exists for change %s", changeControl.getId()));
    }
    ChangeEdit changeEdit = optionalChangeEdit.get();

    PatchSet currentPatchSet = lookupCurrentPatchSet(changeControl);
    if (isBasedOn(changeEdit, currentPatchSet)) {
      throw new InvalidChangeOperationException(
          String.format(
              "Change edit for change %s is already based on latest patch set %s",
              changeControl.getId(), currentPatchSet.getId()));
    }

    rebase(repository, changeEdit, currentPatchSet);
  }

  private void rebase(Repository repository, ChangeEdit changeEdit, PatchSet currentPatchSet)
      throws IOException, MergeConflictException, InvalidChangeOperationException, OrmException {
    RevCommit currentEditCommit = changeEdit.getEditCommit();
    if (currentEditCommit.getParentCount() == 0) {
      throw new InvalidChangeOperationException(
          "Rebase change edit against root commit not supported");
    }

    Change change = changeEdit.getChange();
    RevCommit basePatchSetCommit = lookupCommit(repository, currentPatchSet);
    RevTree basePatchSetTree = basePatchSetCommit.getTree();

    ObjectId newTreeId = merge(repository, changeEdit, basePatchSetTree);
    Timestamp nowTimestamp = TimeUtil.nowTs();
    String commitMessage = currentEditCommit.getFullMessage();
    ObjectId newEditCommitId =
        createCommit(repository, basePatchSetCommit, newTreeId, commitMessage, nowTimestamp);

    String newEditRefName = getEditRefName(change, currentPatchSet);
    updateReferenceWithNameChange(
        repository,
        changeEdit.getRefName(),
        currentEditCommit,
        newEditRefName,
        newEditCommitId,
        nowTimestamp);
    reindex(change);
  }

  /**
   * Modifies the commit message of a change edit. If the change edit doesn't exist, a new one will
   * be created based on the current patch set.
   *
   * @param repository the affected Git repository
   * @param changeControl the {@code ChangeControl} of the change whose change edit's message should
   *     be modified
   * @param newCommitMessage the new commit message
   * @throws AuthException if the user isn't authenticated or not allowed to use change edits
   * @throws UnchangedCommitMessageException if the commit message is the same as before
   * @throws ResourceConflictException if the commit message has a Change-Id modification
   */
  public void modifyMessage(
      Repository repository, ChangeControl changeControl, String newCommitMessage)
      throws AuthException, IOException, UnchangedCommitMessageException, OrmException,
          ResourceConflictException {
    ensureAuthenticatedAndPermitted(changeControl);
    newCommitMessage = getWellFormedCommitMessage(newCommitMessage);

    Optional<ChangeEdit> optionalChangeEdit = lookupChangeEdit(changeControl);
    PatchSet basePatchSet = getBasePatchSet(optionalChangeEdit, changeControl);
    RevCommit basePatchSetCommit = lookupCommit(repository, basePatchSet);
    RevCommit baseCommit =
        optionalChangeEdit.map(ChangeEdit::getEditCommit).orElse(basePatchSetCommit);

    String currentCommitMessage = baseCommit.getFullMessage();
    if (newCommitMessage.equals(currentCommitMessage)) {
      throw new UnchangedCommitMessageException();
    }

    RevTree baseTree = baseCommit.getTree();
    Timestamp nowTimestamp = TimeUtil.nowTs();
    ObjectId newEditCommit =
        createCommit(repository, basePatchSetCommit, baseTree, newCommitMessage, nowTimestamp);

    if (changeControl.getProjectControl().getProjectState().isRequireChangeID()) {
      try (RevWalk revWalk = new RevWalk(repository)) {
        if (!revWalk
            .parseCommit(newEditCommit)
            .getFooterLines(FooterConstants.CHANGE_ID)
            .contains(changeControl.getChange().getKey().get())) {
          throw new ResourceConflictException("Editing of the Change-Id footer is not allowed");
        }
      }
    }

    if (optionalChangeEdit.isPresent()) {
      updateEditReference(repository, optionalChangeEdit.get(), newEditCommit, nowTimestamp);
    } else {
      createEditReference(repository, changeControl, basePatchSet, newEditCommit, nowTimestamp);
    }
  }

  /**
   * Modifies the contents of a file of a change edit. If the change edit doesn't exist, a new one
   * will be created based on the current patch set.
   *
   * @param repository the affected Git repository
   * @param changeControl the {@code ChangeControl} of the change whose change edit should be
   *     modified
   * @param filePath the path of the file whose contents should be modified
   * @param newContent the new file content
   * @throws AuthException if the user isn't authenticated or not allowed to use change edits
   * @throws InvalidChangeOperationException if the file already had the specified content
   */
  public void modifyFile(
      Repository repository, ChangeControl changeControl, String filePath, RawInput newContent)
      throws AuthException, InvalidChangeOperationException, IOException, OrmException {
    modifyTree(repository, changeControl, new ChangeFileContentModification(filePath, newContent));
  }

  /**
   * Deletes a file from the Git tree of a change edit. If the change edit doesn't exist, a new one
   * will be created based on the current patch set.
   *
   * @param repository the affected Git repository
   * @param changeControl the {@code ChangeControl} of the change whose change edit should be
   *     modified
   * @param file path of the file which should be deleted
   * @throws AuthException if the user isn't authenticated or not allowed to use change edits
   * @throws InvalidChangeOperationException if the file does not exist
   */
  public void deleteFile(Repository repository, ChangeControl changeControl, String file)
      throws AuthException, InvalidChangeOperationException, IOException, OrmException {
    modifyTree(repository, changeControl, new DeleteFileModification(file));
  }

  /**
   * Renames a file of a change edit or moves it to another directory. If the change edit doesn't
   * exist, a new one will be created based on the current patch set.
   *
   * @param repository the affected Git repository
   * @param changeControl the {@code ChangeControl} of the change whose change edit should be
   *     modified
   * @param currentFilePath the current path/name of the file
   * @param newFilePath the desired path/name of the file
   * @throws AuthException if the user isn't authenticated or not allowed to use change edits
   * @throws InvalidChangeOperationException if the file was already renamed to the specified new
   *     name
   */
  public void renameFile(
      Repository repository,
      ChangeControl changeControl,
      String currentFilePath,
      String newFilePath)
      throws AuthException, InvalidChangeOperationException, IOException, OrmException {
    modifyTree(repository, changeControl, new RenameFileModification(currentFilePath, newFilePath));
  }

  /**
   * Restores a file of a change edit to the state it was in before the patch set on which the
   * change edit is based. If the change edit doesn't exist, a new one will be created based on the
   * current patch set.
   *
   * @param repository the affected Git repository
   * @param changeControl the {@code ChangeControl} of the change whose change edit should be
   *     modified
   * @param file the path of the file which should be restored
   * @throws AuthException if the user isn't authenticated or not allowed to use change edits
   * @throws InvalidChangeOperationException if the file was already restored
   */
  public void restoreFile(Repository repository, ChangeControl changeControl, String file)
      throws AuthException, InvalidChangeOperationException, IOException, OrmException {
    modifyTree(repository, changeControl, new RestoreFileModification(file));
  }

  private void modifyTree(
      Repository repository, ChangeControl changeControl, TreeModification treeModification)
      throws AuthException, IOException, OrmException, InvalidChangeOperationException {
    ensureAuthenticatedAndPermitted(changeControl);

    Optional<ChangeEdit> optionalChangeEdit = lookupChangeEdit(changeControl);
    PatchSet basePatchSet = getBasePatchSet(optionalChangeEdit, changeControl);
    RevCommit basePatchSetCommit = lookupCommit(repository, basePatchSet);
    RevCommit baseCommit =
        optionalChangeEdit.map(ChangeEdit::getEditCommit).orElse(basePatchSetCommit);

    ObjectId newTreeId = createNewTree(repository, baseCommit, treeModification);

    String commitMessage = baseCommit.getFullMessage();
    Timestamp nowTimestamp = TimeUtil.nowTs();
    ObjectId newEditCommit =
        createCommit(repository, basePatchSetCommit, newTreeId, commitMessage, nowTimestamp);

    if (optionalChangeEdit.isPresent()) {
      updateEditReference(repository, optionalChangeEdit.get(), newEditCommit, nowTimestamp);
    } else {
      createEditReference(repository, changeControl, basePatchSet, newEditCommit, nowTimestamp);
    }
  }

  private void ensureAuthenticatedAndPermitted(ChangeControl changeControl)
      throws AuthException, OrmException {
    ensureAuthenticated();
    ensurePermitted(changeControl);
  }

  private void ensureAuthenticated() throws AuthException {
    if (!currentUser.get().isIdentifiedUser()) {
      throw new AuthException("Authentication required");
    }
  }

  private void ensurePermitted(ChangeControl changeControl) throws OrmException, AuthException {
    if (!changeControl.canAddPatchSet(reviewDb.get())) {
      throw new AuthException("Not allowed to edit a change.");
    }
  }

  private String getWellFormedCommitMessage(String commitMessage) {
    String wellFormedMessage = Strings.nullToEmpty(commitMessage).trim();
    checkState(!wellFormedMessage.isEmpty(), "Commit message cannot be null or empty");
    wellFormedMessage = wellFormedMessage + "\n";
    return wellFormedMessage;
  }

  private Optional<ChangeEdit> lookupChangeEdit(ChangeControl changeControl)
      throws AuthException, IOException {
    return changeEditUtil.byChange(changeControl);
  }

  private PatchSet getBasePatchSet(
      Optional<ChangeEdit> optionalChangeEdit, ChangeControl changeControl) throws OrmException {
    Optional<PatchSet> editBasePatchSet = optionalChangeEdit.map(ChangeEdit::getBasePatchSet);
    return editBasePatchSet.isPresent()
        ? editBasePatchSet.get()
        : lookupCurrentPatchSet(changeControl);
  }

  private PatchSet lookupCurrentPatchSet(ChangeControl changeControl) throws OrmException {
    return patchSetUtil.current(reviewDb.get(), changeControl.getNotes());
  }

  private static boolean isBasedOn(ChangeEdit changeEdit, PatchSet patchSet) {
    PatchSet editBasePatchSet = changeEdit.getBasePatchSet();
    return editBasePatchSet.getId().equals(patchSet.getId());
  }

  private static RevCommit lookupCommit(Repository repository, PatchSet patchSet)
      throws IOException {
    ObjectId patchSetCommitId = getPatchSetCommitId(patchSet);
    try (RevWalk revWalk = new RevWalk(repository)) {
      return revWalk.parseCommit(patchSetCommitId);
    }
  }

  private static ObjectId createNewTree(
      Repository repository, RevCommit baseCommit, TreeModification treeModification)
      throws IOException, InvalidChangeOperationException {
    TreeCreator treeCreator = new TreeCreator(baseCommit);
    treeCreator.addTreeModification(treeModification);
    ObjectId newTreeId = treeCreator.createNewTreeAndGetId(repository);

    if (ObjectId.equals(newTreeId, baseCommit.getTree())) {
      throw new InvalidChangeOperationException("no changes were made");
    }
    return newTreeId;
  }

  private ObjectId merge(Repository repository, ChangeEdit changeEdit, ObjectId newTreeId)
      throws IOException, MergeConflictException {
    PatchSet basePatchSet = changeEdit.getBasePatchSet();
    ObjectId basePatchSetCommitId = getPatchSetCommitId(basePatchSet);
    ObjectId editCommitId = changeEdit.getEditCommit();

    ThreeWayMerger threeWayMerger = MergeStrategy.RESOLVE.newMerger(repository, true);
    threeWayMerger.setBase(basePatchSetCommitId);
    boolean successful = threeWayMerger.merge(newTreeId, editCommitId);

    if (!successful) {
      throw new MergeConflictException(
          "The existing change edit could not be merged with another tree.");
    }
    return threeWayMerger.getResultTreeId();
  }

  private ObjectId createCommit(
      Repository repository,
      RevCommit basePatchSetCommit,
      ObjectId tree,
      String commitMessage,
      Timestamp timestamp)
      throws IOException {
    try (ObjectInserter objectInserter = repository.newObjectInserter()) {
      CommitBuilder builder = new CommitBuilder();
      builder.setTreeId(tree);
      builder.setParentIds(basePatchSetCommit.getParents());
      builder.setAuthor(basePatchSetCommit.getAuthorIdent());
      builder.setCommitter(getCommitterIdent(timestamp));
      builder.setMessage(commitMessage);
      ObjectId newCommitId = objectInserter.insert(builder);
      objectInserter.flush();
      return newCommitId;
    }
  }

  private PersonIdent getCommitterIdent(Timestamp commitTimestamp) {
    IdentifiedUser user = currentUser.get().asIdentifiedUser();
    return user.newCommitterIdent(commitTimestamp, tz);
  }

  private static ObjectId getPatchSetCommitId(PatchSet patchSet) {
    return ObjectId.fromString(patchSet.getRevision().get());
  }

  private void createEditReference(
      Repository repository,
      ChangeControl changeControl,
      PatchSet basePatchSet,
      ObjectId newEditCommit,
      Timestamp timestamp)
      throws IOException, OrmException {
    Change change = changeControl.getChange();
    String editRefName = getEditRefName(change, basePatchSet);
    updateReference(repository, editRefName, ObjectId.zeroId(), newEditCommit, timestamp);
    reindex(change);
  }

  private String getEditRefName(Change change, PatchSet basePatchSet) {
    IdentifiedUser me = currentUser.get().asIdentifiedUser();
    return RefNames.refsEdit(me.getAccountId(), change.getId(), basePatchSet.getId());
  }

  private void updateEditReference(
      Repository repository, ChangeEdit changeEdit, ObjectId newEditCommit, Timestamp timestamp)
      throws IOException, OrmException {
    String editRefName = changeEdit.getRefName();
    RevCommit currentEditCommit = changeEdit.getEditCommit();
    updateReference(repository, editRefName, currentEditCommit, newEditCommit, timestamp);
    reindex(changeEdit.getChange());
  }

  private void updateReference(
      Repository repository,
      String refName,
      ObjectId currentObjectId,
      ObjectId targetObjectId,
      Timestamp timestamp)
      throws IOException {
    RefUpdate ru = repository.updateRef(refName);
    ru.setExpectedOldObjectId(currentObjectId);
    ru.setNewObjectId(targetObjectId);
    ru.setRefLogIdent(getRefLogIdent(timestamp));
    ru.setRefLogMessage("inline edit (amend)", false);
    ru.setForceUpdate(true);
    try (RevWalk revWalk = new RevWalk(repository)) {
      RefUpdate.Result res = ru.update(revWalk);
      if (res != RefUpdate.Result.NEW && res != RefUpdate.Result.FORCED) {
        throw new IOException("update failed: " + ru);
      }
    }
  }

  private void updateReferenceWithNameChange(
      Repository repository,
      String currentRefName,
      ObjectId currentObjectId,
      String newRefName,
      ObjectId targetObjectId,
      Timestamp timestamp)
      throws IOException {
    BatchRefUpdate batchRefUpdate = repository.getRefDatabase().newBatchUpdate();
    batchRefUpdate.addCommand(new ReceiveCommand(ObjectId.zeroId(), targetObjectId, newRefName));
    batchRefUpdate.addCommand(
        new ReceiveCommand(currentObjectId, ObjectId.zeroId(), currentRefName));
    batchRefUpdate.setRefLogMessage("rebase edit", false);
    batchRefUpdate.setRefLogIdent(getRefLogIdent(timestamp));
    try (RevWalk revWalk = new RevWalk(repository)) {
      batchRefUpdate.execute(revWalk, NullProgressMonitor.INSTANCE);
    }
    for (ReceiveCommand cmd : batchRefUpdate.getCommands()) {
      if (cmd.getResult() != ReceiveCommand.Result.OK) {
        throw new IOException("failed: " + cmd);
      }
    }
  }

  private PersonIdent getRefLogIdent(Timestamp timestamp) {
    IdentifiedUser user = currentUser.get().asIdentifiedUser();
    return user.newRefLogIdent(timestamp, tz);
  }

  private void reindex(Change change) throws IOException, OrmException {
    indexer.index(reviewDb.get(), change);
  }
}
