/*
 * Copyright (C) 2010, 2021 Christian Halstrick <christian.halstrick@sap.com> and others
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Distribution License v. 1.0 which is available at
 * https://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */
package org.eclipse.jgit.api;

import static org.eclipse.jgit.api.CherryPickCommitMessageProvider.ORIGINAL;
import static org.eclipse.jgit.lib.Constants.OBJECT_ID_ABBREV_STRING_LENGTH;

import java.io.IOException;
import java.text.MessageFormat;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.eclipse.jgit.api.errors.ConcurrentRefUpdateException;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.errors.JGitInternalException;
import org.eclipse.jgit.api.errors.MultipleParentsNotAllowedException;
import org.eclipse.jgit.api.errors.NoHeadException;
import org.eclipse.jgit.api.errors.NoMessageException;
import org.eclipse.jgit.api.errors.UnmergedPathsException;
import org.eclipse.jgit.api.errors.WrongRepositoryStateException;
import org.eclipse.jgit.dircache.DirCacheCheckout;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.events.WorkingTreeModifiedEvent;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.CommitConfig;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.NullProgressMonitor;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectIdRef;
import org.eclipse.jgit.lib.ProgressMonitor;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Ref.Storage;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.merge.ContentMergeStrategy;
import org.eclipse.jgit.merge.MergeMessageFormatter;
import org.eclipse.jgit.merge.MergeStrategy;
import org.eclipse.jgit.merge.Merger;
import org.eclipse.jgit.merge.ResolveMerger;
import org.eclipse.jgit.merge.ResolveMerger.MergeFailureReason;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.treewalk.FileTreeIterator;

/**
 * A class used to execute a {@code cherry-pick} command. It has setters for all
 * supported options and arguments of this command and a {@link #call()} method
 * to finally execute the command. Each instance of this class should only be
 * used for one invocation of the command (means: one call to {@link #call()})
 *
 * @see <a
 *      href="http://www.kernel.org/pub/software/scm/git/docs/git-cherry-pick.html"
 *      >Git documentation about cherry-pick</a>
 */
public class CherryPickCommand extends GitCommand<CherryPickResult> {
	private String reflogPrefix = "cherry-pick:"; //$NON-NLS-1$

	private List<Ref> commits = new LinkedList<>();

	private String ourCommitName = null;

	private CherryPickCommitMessageProvider messageProvider = ORIGINAL;

	private MergeStrategy strategy = MergeStrategy.RECURSIVE;

	private ContentMergeStrategy contentStrategy;

	private Integer mainlineParentNumber;

	private boolean noCommit = false;

	private ProgressMonitor monitor = NullProgressMonitor.INSTANCE;

	/**
	 * Constructor for CherryPickCommand
	 *
	 * @param repo
	 *            the {@link org.eclipse.jgit.lib.Repository}
	 */
	protected CherryPickCommand(Repository repo) {
		super(repo);
	}

	/**
	 * {@inheritDoc}
	 * <p>
	 * Executes the {@code Cherry-Pick} command with all the options and
	 * parameters collected by the setter methods (e.g. {@link #include(Ref)} of
	 * this class. Each instance of this class should only be used for one
	 * invocation of the command. Don't call this method twice on an instance.
	 */
	@Override
	public CherryPickResult call() throws GitAPIException, NoMessageException,
			UnmergedPathsException, ConcurrentRefUpdateException,
			WrongRepositoryStateException, NoHeadException {
		RevCommit newHead = null;
		List<Ref> cherryPickedRefs = new LinkedList<>();
		checkCallable();

		try (RevWalk revWalk = new RevWalk(repo)) {

			// get the head commit
			Ref headRef = repo.exactRef(Constants.HEAD);
			if (headRef == null) {
				throw new NoHeadException(
						JGitText.get().commitOnRepoWithoutHEADCurrentlyNotSupported);
			}

			newHead = revWalk.parseCommit(headRef.getObjectId());

			// loop through all refs to be cherry-picked
			for (Ref src : commits) {
				// get the commit to be cherry-picked
				// handle annotated tags
				ObjectId srcObjectId = src.getPeeledObjectId();
				if (srcObjectId == null) {
					srcObjectId = src.getObjectId();
				}
				RevCommit srcCommit = revWalk.parseCommit(srcObjectId);

				// get the parent of the commit to cherry-pick
				final RevCommit srcParent = getParentCommit(srcCommit, revWalk);

				String ourName = calculateOurName(headRef);
				String cherryPickName = srcCommit.getId().abbreviate(OBJECT_ID_ABBREV_STRING_LENGTH).name()
						+ " " + srcCommit.getShortMessage(); //$NON-NLS-1$

				Merger merger = strategy.newMerger(repo);
				merger.setProgressMonitor(monitor);
				boolean noProblems;
				Map<String, MergeFailureReason> failingPaths = null;
				List<String> unmergedPaths = null;
				if (merger instanceof ResolveMerger) {
					ResolveMerger resolveMerger = (ResolveMerger) merger;
					resolveMerger.setContentMergeStrategy(contentStrategy);
					resolveMerger.setCommitNames(
							new String[] { "BASE", ourName, cherryPickName }); //$NON-NLS-1$
					resolveMerger
							.setWorkingTreeIterator(new FileTreeIterator(repo));
					if (srcParent != null) {
						resolveMerger.setBase(srcParent.getTree());
					}
					noProblems = merger.merge(newHead, srcCommit);
					failingPaths = resolveMerger.getFailingPaths();
					unmergedPaths = resolveMerger.getUnmergedPaths();
					if (!resolveMerger.getModifiedFiles().isEmpty()) {
						repo.fireEvent(new WorkingTreeModifiedEvent(
								resolveMerger.getModifiedFiles(), null));
					}
				} else {
					noProblems = merger.merge(newHead, srcCommit);
				}
				if (noProblems) {
					if (AnyObjectId.isEqual(newHead.getTree().getId(),
							merger.getResultTreeId())) {
						continue;
					}
					DirCacheCheckout dco = new DirCacheCheckout(repo,
							newHead.getTree(), repo.lockDirCache(),
							merger.getResultTreeId());
					dco.setFailOnConflict(true);
					dco.setProgressMonitor(monitor);
					dco.checkout();
					if (!noCommit) {
						try (Git git = new Git(getRepository())) {
							String commitMessage = messageProvider
									.getCherryPickedCommitMessage(srcCommit);
							newHead = git.commit()
									.setMessage(commitMessage)
									.setReflogComment(reflogPrefix + " " //$NON-NLS-1$
											+ srcCommit.getShortMessage())
									.setAuthor(srcCommit.getAuthorIdent())
									.setNoVerify(true).call();
						}
					}
					cherryPickedRefs.add(src);
				} else {
					if (failingPaths != null && !failingPaths.isEmpty()) {
						return new CherryPickResult(failingPaths);
					}

					// there are merge conflicts

					String message;
					if (unmergedPaths != null) {
						CommitConfig cfg = repo.getConfig()
								.get(CommitConfig.KEY);
						message = srcCommit.getFullMessage();
						char commentChar = cfg.getCommentChar(message);
						message = new MergeMessageFormatter()
								.formatWithConflicts(message, unmergedPaths,
										commentChar);
					} else {
						message = srcCommit.getFullMessage();
					}

					if (!noCommit) {
						repo.writeCherryPickHead(srcCommit.getId());
					}
					repo.writeMergeCommitMsg(message);

					return CherryPickResult.CONFLICT;
				}
			}
		} catch (IOException e) {
			throw new JGitInternalException(
					MessageFormat.format(
							JGitText.get().exceptionCaughtDuringExecutionOfCherryPickCommand,
							e), e);
		}
		return new CherryPickResult(newHead, cherryPickedRefs);
	}

	private RevCommit getParentCommit(RevCommit srcCommit, RevWalk revWalk)
			throws MultipleParentsNotAllowedException, MissingObjectException,
			IOException {
		final RevCommit srcParent;
		if (mainlineParentNumber == null) {
			int nOfParents = srcCommit.getParentCount();
			if (nOfParents == 0) {
				return null;
			} else if (nOfParents != 1) {
				throw new MultipleParentsNotAllowedException(
						MessageFormat.format(
								JGitText.get().canOnlyCherryPickCommitsWithOneParent,
								srcCommit.name(),
								Integer.valueOf(srcCommit.getParentCount())));
			}
			srcParent = srcCommit.getParent(0);
		} else {
			if (mainlineParentNumber.intValue() > srcCommit.getParentCount()) {
				throw new JGitInternalException(MessageFormat.format(
						JGitText.get().commitDoesNotHaveGivenParent, srcCommit,
						mainlineParentNumber));
			}
			srcParent = srcCommit
					.getParent(mainlineParentNumber.intValue() - 1);
		}

		revWalk.parseHeaders(srcParent);
		return srcParent;
	}

	/**
	 * Include a reference to a commit
	 *
	 * @param commit
	 *            a reference to a commit which is cherry-picked to the current
	 *            head
	 * @return {@code this}
	 */
	public CherryPickCommand include(Ref commit) {
		checkCallable();
		commits.add(commit);
		return this;
	}

	/**
	 * Include a commit
	 *
	 * @param commit
	 *            the Id of a commit which is cherry-picked to the current head
	 * @return {@code this}
	 */
	public CherryPickCommand include(AnyObjectId commit) {
		return include(commit.getName(), commit);
	}

	/**
	 * Include a commit
	 *
	 * @param name
	 *            a name given to the commit
	 * @param commit
	 *            the Id of a commit which is cherry-picked to the current head
	 * @return {@code this}
	 */
	public CherryPickCommand include(String name, AnyObjectId commit) {
		return include(new ObjectIdRef.Unpeeled(Storage.LOOSE, name,
				commit.copy()));
	}

	/**
	 * Set the name that should be used in the "OURS" place for conflict markers
	 *
	 * @param ourCommitName
	 *            the name that should be used in the "OURS" place for conflict
	 *            markers
	 * @return {@code this}
	 */
	public CherryPickCommand setOurCommitName(String ourCommitName) {
		this.ourCommitName = ourCommitName;
		return this;
	}

	/**
	 * Set a message provider for a target cherry-picked commit<br>
	 * By default original commit message is used (see
	 * {@link CherryPickCommitMessageProvider#ORIGINAL})
	 *
	 * @param messageProvider
	 *            the commit message provider
	 * @return {@code this}
	 * @since 6.9
	 */
	public CherryPickCommand setCherryPickCommitMessageProvider(
			CherryPickCommitMessageProvider messageProvider) {
		this.messageProvider = messageProvider;
		return this;
	}

	/**
	 * Set the prefix to use in the reflog.
	 * <p>
	 * This is primarily needed for implementing rebase in terms of
	 * cherry-picking
	 *
	 * @param prefix
	 *            including ":"
	 * @return {@code this}
	 * @since 3.1
	 */
	public CherryPickCommand setReflogPrefix(String prefix) {
		this.reflogPrefix = prefix;
		return this;
	}

	/**
	 * Set the {@code MergeStrategy}
	 *
	 * @param strategy
	 *            The merge strategy to use during this Cherry-pick.
	 * @return {@code this}
	 * @since 3.4
	 */
	public CherryPickCommand setStrategy(MergeStrategy strategy) {
		this.strategy = strategy;
		return this;
	}

	/**
	 * Sets the content merge strategy to use if the
	 * {@link #setStrategy(MergeStrategy) merge strategy} is "resolve" or
	 * "recursive".
	 *
	 * @param strategy
	 *            the {@link ContentMergeStrategy} to be used
	 * @return {@code this}
	 * @since 5.12
	 */
	public CherryPickCommand setContentMergeStrategy(
			ContentMergeStrategy strategy) {
		this.contentStrategy = strategy;
		return this;
	}

	/**
	 * Set the (1-based) parent number to diff against
	 *
	 * @param mainlineParentNumber
	 *            the (1-based) parent number to diff against. This allows
	 *            cherry-picking of merges.
	 * @return {@code this}
	 * @since 3.4
	 */
	public CherryPickCommand setMainlineParentNumber(int mainlineParentNumber) {
		this.mainlineParentNumber = Integer.valueOf(mainlineParentNumber);
		return this;
	}

	/**
	 * Allows cherry-picking changes without committing them.
	 * <p>
	 * NOTE: The behavior of cherry-pick is undefined if you pick multiple
	 * commits or if HEAD does not match the index state before cherry-picking.
	 *
	 * @param noCommit
	 *            true to cherry-pick without committing, false to commit after
	 *            each pick (default)
	 * @return {@code this}
	 * @since 3.5
	 */
	public CherryPickCommand setNoCommit(boolean noCommit) {
		this.noCommit = noCommit;
		return this;
	}

	/**
	 * The progress monitor associated with the cherry-pick operation. By
	 * default, this is set to <code>NullProgressMonitor</code>
	 *
	 * @see NullProgressMonitor
	 * @param monitor
	 *            a {@link org.eclipse.jgit.lib.ProgressMonitor}
	 * @return {@code this}
	 * @since 4.11
	 */
	public CherryPickCommand setProgressMonitor(ProgressMonitor monitor) {
		if (monitor == null) {
			monitor = NullProgressMonitor.INSTANCE;
		}
		this.monitor = monitor;
		return this;
	}

	private String calculateOurName(Ref headRef) {
		if (ourCommitName != null)
			return ourCommitName;

		String targetRefName = headRef.getTarget().getName();
		String headName = Repository.shortenRefName(targetRefName);
		return headName;
	}

	@SuppressWarnings("nls")
	@Override
	public String toString() {
		return "CherryPickCommand [repo=" + repo + ",\ncommits=" + commits
				+ ",\nmainlineParentNumber=" + mainlineParentNumber
				+ ", noCommit=" + noCommit + ", ourCommitName=" + ourCommitName
				+ ", reflogPrefix=" + reflogPrefix + ", strategy=" + strategy
				+ "]";
	}

}
