// 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.server.GerritPersonIdent;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.submit.IntegrationException;
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, IntegrationException {
    try (Repository repo = repoManager.openRepository(project)) {
      return build(repo);
    }
  }

  public ObjectId build(Repository repo) throws IOException, IntegrationException {
    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 IntegrationException("Merge aborted"); // because not FF
      }
      return merge(repo, revWalk);
    }
  }

  protected ObjectId merge(Repository repo, RevWalk revWalk)
      throws IOException, IntegrationException {
    ThreeWayMerger merger = getMerger(repo);
    if (!merger.merge(firstParent, secondParent)) {
      throw new IntegrationException("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;
    }
  }
}
