// 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.googlesource.gerrit.plugins.batch.util;

import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.Project;
import com.google.gerrit.extensions.restapi.MergeConflictException;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.concurrent.Callable;
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.Repository;
import org.eclipse.jgit.merge.MergeStrategy;
import org.eclipse.jgit.merge.Merger;
import org.eclipse.jgit.merge.ThreeWayMerger;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.util.StringUtils;

public class MergeBuilder implements Callable<ObjectId> {
  /**
   * The modes available for fast forward merges corresponding to the --ff, --no-ff and --ff-only
   * options
   */
  public static enum FastForwardMode {
    /**
     * Corresponds to the default --ff option (for a fast forward update the branch pointer only).
     */
    FF("ff"),
    /** Corresponds to the --no-ff option (create a merge commit even for a fast forward). */
    NO_FF("no-ff"),
    /**
     * Corresponds to the --ff-only option (abort unless the merge is a fast forward or branch is
     * already up-to-date).
     */
    FF_ONLY("ff-only");
    public final String name;

    private FastForwardMode(final String name) {
      this.name = name;
    }

    public String getName() {
      return name;
    }

    public static FastForwardMode fromString(String str) {
      if (StringUtils.isEmptyOrNull(str)) {
        return null;
      }
      for (FastForwardMode mode : FastForwardMode.values()) {
        if (mode.getName().equalsIgnoreCase(str)) {
          return mode;
        }
      }
      return null;
    }
  }

  public interface Factory {
    MergeBuilder create(
        @Assisted Project.NameKey project,
        @Assisted("message") @Nullable String message,
        @Assisted @Nullable MergeStrategy strategy,
        @Assisted @Nullable FastForwardMode fastForwardMode,
        @Assisted("firstParent") ObjectId firstParent,
        @Assisted("secondParent") ObjectId secondParent);
  }

  protected final GitRepositoryManager repoManager;
  protected final PersonIdent gerrit;
  protected final IdentifiedUser user;
  protected final Project.NameKey project;
  protected String message;
  protected final MergeStrategy strategy;
  protected FastForwardMode fastForwardMode = FastForwardMode.FF;
  protected final ObjectId firstParent;
  protected final ObjectId secondParent;

  @Inject
  MergeBuilder(
      GitRepositoryManager repoManager,
      @GerritPersonIdent PersonIdent gerrit,
      IdentifiedUser user,
      @Assisted Project.NameKey project,
      @Assisted("message") @Nullable String message,
      @Assisted @Nullable MergeStrategy strategy,
      @Assisted @Nullable FastForwardMode fastForwardMode,
      @Assisted("firstParent") ObjectId firstParent,
      @Assisted("secondParent") ObjectId secondParent) {
    this.repoManager = repoManager;
    this.gerrit = gerrit;
    this.user = user;
    this.project = project;
    this.message = message;
    this.strategy = strategy;
    if (fastForwardMode != null) {
      this.fastForwardMode = fastForwardMode;
    }
    this.firstParent = firstParent;
    this.secondParent = secondParent;
  }

  @Override
  public ObjectId call() throws IOException, MergeConflictException {
    try (Repository repo = repoManager.openRepository(project)) {
      return build(repo);
    }
  }

  public ObjectId build(Repository repo) throws IOException, MergeConflictException {
    try (RevWalk revWalk = new RevWalk(repo)) {
      RevCommit firstParentCommit = revWalk.lookupCommit(firstParent);
      RevCommit secondParentCommit = revWalk.lookupCommit(secondParent);
      if (revWalk.isMergedInto(secondParentCommit, firstParentCommit)) {
        return firstParent; // already up to date
      }
      if (fastForwardMode != FastForwardMode.NO_FF
          && revWalk.isMergedInto(firstParentCommit, secondParentCommit)) {
        return secondParent; // Fast forward merge
      }
      if (fastForwardMode == FastForwardMode.FF_ONLY) {
        throw new MergeConflictException("Merge aborted"); // because not FF
      }
      return merge(repo, revWalk);
    }
  }

  protected ObjectId merge(Repository repo, RevWalk revWalk)
      throws IOException, MergeConflictException {
    ThreeWayMerger merger = getMerger(repo);
    if (!merger.merge(firstParent, secondParent)) {
      throw new MergeConflictException("Merge conflict");
    }
    message = defaultMessage(revWalk, message);
    return insert(merger, buildCommit(merger));
  }

  protected ThreeWayMerger getMerger(Repository repo) {
    if (strategy == MergeStrategy.RESOLVE) {
      return MergeStrategy.RESOLVE.newMerger(repo, true);
    }
    return MergeStrategy.SIMPLE_TWO_WAY_IN_CORE.newMerger(repo);
  }

  protected CommitBuilder buildCommit(Merger merger) {
    final CommitBuilder mergeCommit = new CommitBuilder();
    mergeCommit.setTreeId(merger.getResultTreeId());
    mergeCommit.setParentIds(firstParent, secondParent);
    mergeCommit.setAuthor(
        user.newCommitterIdent(new Timestamp(System.currentTimeMillis()), gerrit.getTimeZone()));
    mergeCommit.setCommitter(gerrit);
    mergeCommit.setMessage(message);
    return mergeCommit;
  }

  protected String defaultMessage(RevWalk walk, String message) {
    if (message == null) {
      try {
        message = walk.parseCommit(secondParent).getShortMessage();
      } catch (Exception e) {
        message = secondParent.getName();
      }
      message = "Merge \"" + message + "\"";
    }
    return message;
  }

  protected ObjectId insert(Merger merger, CommitBuilder commit) throws IOException {
    try (ObjectInserter objInserter = merger.getObjectInserter()) {
      ObjectId mergeCommitId = objInserter.insert(commit);
      objInserter.flush();
      return mergeCommitId;
    }
  }
}
