/*
 * Copyright (C) 2012, GitHub Inc. 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 java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.jgit.api.ResetCommand.ResetType;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.errors.JGitInternalException;
import org.eclipse.jgit.api.errors.NoHeadException;
import org.eclipse.jgit.api.errors.UnmergedPathsException;
import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.dircache.DirCacheBuilder;
import org.eclipse.jgit.dircache.DirCacheEditor;
import org.eclipse.jgit.dircache.DirCacheEditor.DeletePath;
import org.eclipse.jgit.dircache.DirCacheEditor.PathEdit;
import org.eclipse.jgit.dircache.DirCacheEntry;
import org.eclipse.jgit.dircache.DirCacheIterator;
import org.eclipse.jgit.errors.UnmergedPathException;
import org.eclipse.jgit.events.WorkingTreeModifiedEvent;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.CommitBuilder;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.MutableObjectId;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.treewalk.AbstractTreeIterator;
import org.eclipse.jgit.treewalk.FileTreeIterator;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.treewalk.WorkingTreeIterator;
import org.eclipse.jgit.treewalk.filter.AndTreeFilter;
import org.eclipse.jgit.treewalk.filter.IndexDiffFilter;
import org.eclipse.jgit.treewalk.filter.SkipWorkTreeFilter;
import org.eclipse.jgit.util.FileUtils;

/**
 * Command class to stash changes in the working directory and index in a
 * commit.
 *
 * @see <a href="http://www.kernel.org/pub/software/scm/git/docs/git-stash.html"
 *      >Git documentation about Stash</a>
 * @since 2.0
 */
public class StashCreateCommand extends GitCommand<RevCommit> {

	private static final String MSG_INDEX = "index on {0}: {1} {2}"; //$NON-NLS-1$

	private static final String MSG_UNTRACKED = "untracked files on {0}: {1} {2}"; //$NON-NLS-1$

	private static final String MSG_WORKING_DIR = "WIP on {0}: {1} {2}"; //$NON-NLS-1$

	private String indexMessage = MSG_INDEX;

	private String workingDirectoryMessage = MSG_WORKING_DIR;

	private String ref = Constants.R_STASH;

	private PersonIdent person;

	private boolean includeUntracked;

	/**
	 * Create a command to stash changes in the working directory and index
	 *
	 * @param repo
	 *            a {@link org.eclipse.jgit.lib.Repository} object.
	 */
	public StashCreateCommand(Repository repo) {
		super(repo);
		person = new PersonIdent(repo);
	}

	/**
	 * Set the message used when committing index changes
	 * <p>
	 * The message will be formatted with the current branch, abbreviated commit
	 * id, and short commit message when used.
	 *
	 * @param message
	 *            the stash message
	 * @return {@code this}
	 */
	public StashCreateCommand setIndexMessage(String message) {
		indexMessage = message;
		return this;
	}

	/**
	 * Set the message used when committing working directory changes
	 * <p>
	 * The message will be formatted with the current branch, abbreviated commit
	 * id, and short commit message when used.
	 *
	 * @param message
	 *            the working directory message
	 * @return {@code this}
	 */
	public StashCreateCommand setWorkingDirectoryMessage(String message) {
		workingDirectoryMessage = message;
		return this;
	}

	/**
	 * Set the person to use as the author and committer in the commits made
	 *
	 * @param person
	 *            the {@link org.eclipse.jgit.lib.PersonIdent} of the person who
	 *            creates the stash.
	 * @return {@code this}
	 */
	public StashCreateCommand setPerson(PersonIdent person) {
		this.person = person;
		return this;
	}

	/**
	 * Set the reference to update with the stashed commit id If null, no
	 * reference is updated
	 * <p>
	 * This value defaults to {@link org.eclipse.jgit.lib.Constants#R_STASH}
	 *
	 * @param ref
	 *            the name of the {@code Ref} to update
	 * @return {@code this}
	 */
	public StashCreateCommand setRef(String ref) {
		this.ref = ref;
		return this;
	}

	/**
	 * Whether to include untracked files in the stash.
	 *
	 * @param includeUntracked
	 *            whether to include untracked files in the stash
	 * @return {@code this}
	 * @since 3.4
	 */
	public StashCreateCommand setIncludeUntracked(boolean includeUntracked) {
		this.includeUntracked = includeUntracked;
		return this;
	}

	private RevCommit parseCommit(final ObjectReader reader,
			final ObjectId headId) throws IOException {
		try (RevWalk walk = new RevWalk(reader)) {
			return walk.parseCommit(headId);
		}
	}

	private CommitBuilder createBuilder() {
		CommitBuilder builder = new CommitBuilder();
		PersonIdent author = person;
		if (author == null)
			author = new PersonIdent(repo);
		builder.setAuthor(author);
		builder.setCommitter(author);
		return builder;
	}

	private void updateStashRef(ObjectId commitId, PersonIdent refLogIdent,
			String refLogMessage) throws IOException {
		if (ref == null)
			return;
		Ref currentRef = repo.findRef(ref);
		RefUpdate refUpdate = repo.updateRef(ref);
		refUpdate.setNewObjectId(commitId);
		refUpdate.setRefLogIdent(refLogIdent);
		refUpdate.setRefLogMessage(refLogMessage, false);
		refUpdate.setForceRefLog(true);
		if (currentRef != null)
			refUpdate.setExpectedOldObjectId(currentRef.getObjectId());
		else
			refUpdate.setExpectedOldObjectId(ObjectId.zeroId());
		refUpdate.forceUpdate();
	}

	private Ref getHead() throws GitAPIException {
		try {
			Ref head = repo.exactRef(Constants.HEAD);
			if (head == null || head.getObjectId() == null)
				throw new NoHeadException(JGitText.get().headRequiredToStash);
			return head;
		} catch (IOException e) {
			throw new JGitInternalException(JGitText.get().stashFailed, e);
		}
	}

	/**
	 * {@inheritDoc}
	 * <p>
	 * Stash the contents on the working directory and index in separate commits
	 * and reset to the current HEAD commit.
	 */
	@Override
	public RevCommit call() throws GitAPIException {
		checkCallable();

		List<String> deletedFiles = new ArrayList<>();
		Ref head = getHead();
		try (ObjectReader reader = repo.newObjectReader()) {
			RevCommit headCommit = parseCommit(reader, head.getObjectId());
			DirCache cache = repo.lockDirCache();
			ObjectId commitId;
			try (ObjectInserter inserter = repo.newObjectInserter();
					TreeWalk treeWalk = new TreeWalk(repo, reader)) {

				treeWalk.setRecursive(true);
				treeWalk.addTree(headCommit.getTree());
				treeWalk.addTree(new DirCacheIterator(cache));
				treeWalk.addTree(new FileTreeIterator(repo));
				treeWalk.getTree(2, FileTreeIterator.class)
						.setDirCacheIterator(treeWalk, 1);
				treeWalk.setFilter(AndTreeFilter.create(new SkipWorkTreeFilter(
						1), new IndexDiffFilter(1, 2)));

				// Return null if no local changes to stash
				if (!treeWalk.next())
					return null;

				MutableObjectId id = new MutableObjectId();
				List<PathEdit> wtEdits = new ArrayList<>();
				List<String> wtDeletes = new ArrayList<>();
				List<DirCacheEntry> untracked = new ArrayList<>();
				boolean hasChanges = false;
				do {
					AbstractTreeIterator headIter = treeWalk.getTree(0,
							AbstractTreeIterator.class);
					DirCacheIterator indexIter = treeWalk.getTree(1,
							DirCacheIterator.class);
					WorkingTreeIterator wtIter = treeWalk.getTree(2,
							WorkingTreeIterator.class);
					if (indexIter != null
							&& !indexIter.getDirCacheEntry().isMerged())
						throw new UnmergedPathsException(
								new UnmergedPathException(
										indexIter.getDirCacheEntry()));
					if (wtIter != null) {
						if (indexIter == null && headIter == null
								&& !includeUntracked)
							continue;
						hasChanges = true;
						if (indexIter != null && wtIter.idEqual(indexIter))
							continue;
						if (headIter != null && wtIter.idEqual(headIter))
							continue;
						treeWalk.getObjectId(id, 0);
						final DirCacheEntry entry = new DirCacheEntry(
								treeWalk.getRawPath());
						entry.setLength(wtIter.getEntryLength());
						entry.setLastModified(
								wtIter.getEntryLastModifiedInstant());
						entry.setFileMode(wtIter.getEntryFileMode());
						long contentLength = wtIter.getEntryContentLength();
						try (InputStream in = wtIter.openEntryStream()) {
							entry.setObjectId(inserter.insert(
									Constants.OBJ_BLOB, contentLength, in));
						}

						if (indexIter == null && headIter == null)
							untracked.add(entry);
						else
							wtEdits.add(new PathEdit(entry) {
								@Override
								public void apply(DirCacheEntry ent) {
									ent.copyMetaData(entry);
								}
							});
					}
					hasChanges = true;
					if (wtIter == null && headIter != null)
						wtDeletes.add(treeWalk.getPathString());
				} while (treeWalk.next());

				if (!hasChanges)
					return null;

				String branch = Repository.shortenRefName(head.getTarget()
						.getName());

				// Commit index changes
				CommitBuilder builder = createBuilder();
				builder.setParentId(headCommit);
				builder.setTreeId(cache.writeTree(inserter));
				builder.setMessage(MessageFormat.format(indexMessage, branch,
						headCommit.abbreviate(7).name(),
						headCommit.getShortMessage()));
				ObjectId indexCommit = inserter.insert(builder);

				// Commit untracked changes
				ObjectId untrackedCommit = null;
				if (!untracked.isEmpty()) {
					DirCache untrackedDirCache = DirCache.newInCore();
					DirCacheBuilder untrackedBuilder = untrackedDirCache
							.builder();
					for (DirCacheEntry entry : untracked)
						untrackedBuilder.add(entry);
					untrackedBuilder.finish();

					builder.setParentIds(new ObjectId[0]);
					builder.setTreeId(untrackedDirCache.writeTree(inserter));
					builder.setMessage(MessageFormat.format(MSG_UNTRACKED,
							branch, headCommit.abbreviate(7).name(),
							headCommit.getShortMessage()));
					untrackedCommit = inserter.insert(builder);
				}

				// Commit working tree changes
				if (!wtEdits.isEmpty() || !wtDeletes.isEmpty()) {
					DirCacheEditor editor = cache.editor();
					for (PathEdit edit : wtEdits)
						editor.add(edit);
					for (String path : wtDeletes)
						editor.add(new DeletePath(path));
					editor.finish();
				}
				builder.setParentId(headCommit);
				builder.addParentId(indexCommit);
				if (untrackedCommit != null)
					builder.addParentId(untrackedCommit);
				builder.setMessage(MessageFormat.format(
						workingDirectoryMessage, branch,
						headCommit.abbreviate(7).name(),
						headCommit.getShortMessage()));
				builder.setTreeId(cache.writeTree(inserter));
				commitId = inserter.insert(builder);
				inserter.flush();

				updateStashRef(commitId, builder.getAuthor(),
						builder.getMessage());

				// Remove untracked files
				if (includeUntracked) {
					for (DirCacheEntry entry : untracked) {
						String repoRelativePath = entry.getPathString();
						File file = new File(repo.getWorkTree(),
								repoRelativePath);
						FileUtils.delete(file);
						deletedFiles.add(repoRelativePath);
					}
				}

			} finally {
				cache.unlock();
			}

			// Hard reset to HEAD
			new ResetCommand(repo).setMode(ResetType.HARD).call();

			// Return stashed commit
			return parseCommit(reader, commitId);
		} catch (IOException e) {
			throw new JGitInternalException(JGitText.get().stashFailed, e);
		} finally {
			if (!deletedFiles.isEmpty()) {
				repo.fireEvent(
						new WorkingTreeModifiedEvent(null, deletedFiles));
			}
		}
	}
}
