// Copyright (C) 2012 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.change;

import com.google.gerrit.common.TimeUtil;
import com.google.gerrit.common.errors.EmailException;
import com.google.gerrit.reviewdb.client.Branch;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Change.Status;
import com.google.gerrit.reviewdb.client.ChangeMessage;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RevId;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.ChangeUtil;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.change.PatchSetInserter.ValidatePolicy;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.MergeConflictException;
import com.google.gerrit.server.git.MergeUtil;
import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.project.InvalidChangeOperationException;
import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;

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.PersonIdent;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.merge.ThreeWayMerger;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.TimeZone;

@Singleton
public class RebaseChange {
  private static final Logger log = LoggerFactory.getLogger(RebaseChange.class);

  private final ChangeControl.GenericFactory changeControlFactory;
  private final Provider<ReviewDb> db;
  private final GitRepositoryManager gitManager;
  private final TimeZone serverTimeZone;
  private final MergeUtil.Factory mergeUtilFactory;
  private final PatchSetInserter.Factory patchSetInserterFactory;

  @Inject
  RebaseChange(ChangeControl.GenericFactory changeControlFactory,
      Provider<ReviewDb> db,
      @GerritPersonIdent PersonIdent myIdent,
      GitRepositoryManager gitManager,
      MergeUtil.Factory mergeUtilFactory,
      PatchSetInserter.Factory patchSetInserterFactory) {
    this.changeControlFactory = changeControlFactory;
    this.db = db;
    this.gitManager = gitManager;
    this.serverTimeZone = myIdent.getTimeZone();
    this.mergeUtilFactory = mergeUtilFactory;
    this.patchSetInserterFactory = patchSetInserterFactory;
  }

  /**
   * Rebase the change of the given patch set.
   * <p>
   * It is verified that the current user is allowed to do the rebase.
   * <p>
   * If the patch set has no dependency to an open change, then the change is
   * rebased on the tip of the destination branch.
   * <p>
   * If the patch set depends on an open change, it is rebased on the latest
   * patch set of this change.
   * <p>
   * The rebased commit is added as new patch set to the change.
   * <p>
   * E-mail notification and triggering of hooks happens for the creation of the
   * new patch set.
   *
   * @param git the repository.
   * @param rw the RevWalk.
   * @param change the change to rebase.
   * @param patchSetId the patch set ID to rebase.
   * @param uploader the user that creates the rebased patch set.
   * @param newBaseRev the commit that should be the new base.
   * @throws NoSuchChangeException if the change to which the patch set belongs
   *     does not exist or is not visible to the user.
   * @throws EmailException if sending the e-mail to notify about the new patch
   *     set fails.
   * @throws OrmException if accessing the database fails.
   * @throws IOException if accessing the repository fails.
   * @throws InvalidChangeOperationException if rebase is not possible or not
   *     allowed.
   */
  public void rebase(Repository git, RevWalk rw, Change change,
      PatchSet.Id patchSetId, IdentifiedUser uploader, String newBaseRev)
      throws NoSuchChangeException, EmailException, OrmException, IOException,
      InvalidChangeOperationException {
    Change.Id changeId = patchSetId.getParentKey();
    ChangeControl changeControl =
        changeControlFactory.validateFor(change, uploader);
    if (!changeControl.canRebase()) {
      throw new InvalidChangeOperationException("Cannot rebase: New patch sets"
          + " are not allowed to be added to change: " + changeId);
    }
    try (ObjectInserter inserter = git.newObjectInserter()) {
      String baseRev = newBaseRev;
      if (baseRev == null) {
        baseRev = findBaseRevision(
            patchSetId, db.get(), change.getDest(), git, rw);
      }
      ObjectId baseObjectId = git.resolve(baseRev);
      if (baseObjectId == null) {
        throw new InvalidChangeOperationException(
          "Cannot rebase: Failed to resolve baseRev: " + baseRev);
      }
      RevCommit baseCommit = rw.parseCommit(baseObjectId);

      PersonIdent committerIdent =
          uploader.newCommitterIdent(TimeUtil.nowTs(), serverTimeZone);

      rebase(git, rw, inserter, change, patchSetId,
          uploader, baseCommit, mergeUtilFactory.create(
              changeControl.getProjectControl().getProjectState(), true),
          committerIdent, true, ValidatePolicy.GERRIT);
    } catch (MergeConflictException e) {
      throw new IOException(e.getMessage());
    }
  }

  /**
   * Find the commit onto which a patch set should be rebased.
   * <p>
   * This is defined as the latest patch set of the change corresponding to
   * this commit's parent, or the destination branch tip in the case where the
   * parent's change is merged.
   *
   * @param patchSetId patch set ID for which the new base commit should be
   *     found.
   * @param db the ReviewDb.
   * @param destBranch the destination branch.
   * @param git the repository.
   * @param rw the RevWalk.
   * @return the commit onto which the patch set should be rebased.
   * @throws InvalidChangeOperationException if rebase is not possible or not
   *     allowed.
   * @throws IOException if accessing the repository fails.
   * @throws OrmException if accessing the database fails.
   */
  private static String findBaseRevision(PatchSet.Id patchSetId,
      ReviewDb db, Branch.NameKey destBranch, Repository git, RevWalk rw)
      throws InvalidChangeOperationException, IOException, OrmException {
    String baseRev = null;

    PatchSet patchSet = db.patchSets().get(patchSetId);
    if (patchSet == null) {
      throw new InvalidChangeOperationException(
          "Patch set " + patchSetId + " not found");
    }
    RevCommit commit = rw.parseCommit(
        ObjectId.fromString(patchSet.getRevision().get()));

    if (commit.getParentCount() > 1) {
      throw new InvalidChangeOperationException(
          "Cannot rebase a change with multiple parents.");
    } else if (commit.getParentCount() == 0) {
      throw new InvalidChangeOperationException(
          "Cannot rebase a change without any parents"
          + " (is this the initial commit?).");
    }

    RevId parentRev = new RevId(commit.getParent(0).name());

    for (PatchSet depPatchSet : db.patchSets().byRevision(parentRev)) {
      Change.Id depChangeId = depPatchSet.getId().getParentKey();
      Change depChange = db.changes().get(depChangeId);
      if (!depChange.getDest().equals(destBranch)) {
        continue;
      }

      if (depChange.getStatus() == Status.ABANDONED) {
        throw new InvalidChangeOperationException(
            "Cannot rebase a change with an abandoned parent: "
            + depChange.getKey());
      }

      if (depChange.getStatus().isOpen()) {
        if (depPatchSet.getId().equals(depChange.currentPatchSetId())) {
          throw new InvalidChangeOperationException(
              "Change is already based on the latest patch set of the"
              + " dependent change.");
        }
        PatchSet latestDepPatchSet =
            db.patchSets().get(depChange.currentPatchSetId());
        baseRev = latestDepPatchSet.getRevision().get();
      }
      break;
    }

    if (baseRev == null) {
      // We are dependent on a merged PatchSet or have no PatchSet
      // dependencies at all.
      Ref destRef = git.getRef(destBranch.get());
      if (destRef == null) {
        throw new InvalidChangeOperationException(
            "The destination branch does not exist: " + destBranch.get());
      }
      baseRev = destRef.getObjectId().getName();
      if (baseRev.equals(parentRev.get())) {
        throw new InvalidChangeOperationException(
            "Change is already up to date.");
      }
    }
    return baseRev;
  }

  /**
   * Rebase the change of the given patch set on the given base commit.
   * <p>
   * The rebased commit is added as new patch set to the change.
   * <p>
   * E-mail notification and triggering of hooks is only done for the creation
   * of the new patch set if {@code sendEmail} and {@code runHooks} are true,
   * respectively.
   *
   * @param git the repository.
   * @param inserter the object inserter.
   * @param change the change to rebase.
   * @param patchSetId the patch set ID to rebase.
   * @param uploader the user that creates the rebased patch set.
   * @param baseCommit the commit that should be the new base.
   * @param mergeUtil merge utilities for the destination project.
   * @param committerIdent the committer's identity.
   * @param runHooks if hooks should be run for the new patch set.
   * @param validate if commit validation should be run for the new patch set.
   * @param rw the RevWalk.
   * @return the new patch set, which is based on the given base commit.
   * @throws NoSuchChangeException if the change to which the patch set belongs
   *     does not exist or is not visible to the user.
   * @throws OrmException if accessing the database fails.
   * @throws IOException if rebase is not possible.
   * @throws InvalidChangeOperationException if rebase is not possible or not
   *     allowed.
   */
  public PatchSet rebase(Repository git, RevWalk rw,
      ObjectInserter inserter, Change change, PatchSet.Id patchSetId,
      IdentifiedUser uploader, RevCommit baseCommit, MergeUtil mergeUtil,
      PersonIdent committerIdent, boolean runHooks, ValidatePolicy validate)
      throws NoSuchChangeException, OrmException, IOException,
      InvalidChangeOperationException, MergeConflictException {
    if (!change.currentPatchSetId().equals(patchSetId)) {
      throw new InvalidChangeOperationException("patch set is not current");
    }
    PatchSet originalPatchSet = db.get().patchSets().get(patchSetId);

    RevCommit rebasedCommit;
    ObjectId oldId = ObjectId.fromString(originalPatchSet.getRevision().get());
    ObjectId newId = rebaseCommit(git, inserter, rw.parseCommit(oldId),
        baseCommit, mergeUtil, committerIdent);

    rebasedCommit = rw.parseCommit(newId);

    ChangeControl changeControl =
        changeControlFactory.validateFor(change, uploader);

    PatchSetInserter patchSetInserter = patchSetInserterFactory
        .create(git, rw, changeControl, rebasedCommit)
        .setValidatePolicy(validate)
        .setDraft(originalPatchSet.isDraft())
        .setUploader(uploader.getAccountId())
        .setSendMail(false)
        .setRunHooks(runHooks);

    PatchSet.Id newPatchSetId = patchSetInserter.getPatchSetId();
    ChangeMessage cmsg = new ChangeMessage(
        new ChangeMessage.Key(change.getId(),
            ChangeUtil.messageUUID(db.get())), uploader.getAccountId(),
            TimeUtil.nowTs(), patchSetId);

    cmsg.setMessage("Patch Set " + newPatchSetId.get()
        + ": Patch Set " + patchSetId.get() + " was rebased");

    Change newChange = patchSetInserter
        .setMessage(cmsg)
        .insert();

    return db.get().patchSets().get(newChange.currentPatchSetId());
  }

  /**
   * Rebase a commit.
   *
   * @param git repository to find commits in.
   * @param inserter inserter to handle new trees and blobs.
   * @param original the commit to rebase.
   * @param base base to rebase against.
   * @param mergeUtil merge utilities for the destination project.
   * @param committerIdent committer identity.
   * @return the id of the rebased commit.
   * @throws MergeConflictException the rebase failed due to a merge conflict.
   * @throws IOException the merge failed for another reason.
   */
  private ObjectId rebaseCommit(Repository git, ObjectInserter inserter,
      RevCommit original, RevCommit base, MergeUtil mergeUtil,
      PersonIdent committerIdent) throws MergeConflictException, IOException,
      InvalidChangeOperationException {
    RevCommit parentCommit = original.getParent(0);

    if (base.equals(parentCommit)) {
      throw new InvalidChangeOperationException(
          "Change is already up to date.");
    }

    ThreeWayMerger merger = mergeUtil.newThreeWayMerger(git, inserter);
    merger.setBase(parentCommit);
    merger.merge(original, base);

    if (merger.getResultTreeId() == null) {
      throw new MergeConflictException(
          "The change could not be rebased due to a conflict during merge.");
    }

    CommitBuilder cb = new CommitBuilder();
    cb.setTreeId(merger.getResultTreeId());
    cb.setParentId(base);
    cb.setAuthor(original.getAuthorIdent());
    cb.setMessage(original.getFullMessage());
    cb.setCommitter(committerIdent);
    ObjectId objectId = inserter.insert(cb);
    inserter.flush();
    return objectId;
  }

  public boolean canRebase(ChangeResource r) {
    Change c = r.getChange();
    return canRebase(c.getProject(), c.currentPatchSetId(), c.getDest());
  }

  public boolean canRebase(RevisionResource r) {
    return canRebase(r.getChange().getProject(),
        r.getPatchSet().getId(), r.getChange().getDest());
  }

  public boolean canRebase(Project.NameKey project, PatchSet.Id patchSetId,
      Branch.NameKey branch) {
    Repository git;
    try {
      git = gitManager.openRepository(project);
    } catch (RepositoryNotFoundException err) {
      return false;
    } catch (IOException err) {
      return false;
    }
    try (RevWalk rw = new RevWalk(git)) {
      findBaseRevision(patchSetId, db.get(), branch, git, rw);
      return true;
    } catch (InvalidChangeOperationException e) {
      return false;
    } catch (OrmException | IOException e) {
      log.warn("Error checking if patch set " + patchSetId + " on " + branch
          + " can be rebased", e);
      return false;
    } finally {
      git.close();
    }
  }
}
