/*
 * Copyright (C) 2012, GitHub Inc.
 * and other copyright owners as documented in the project's IP log.
 *
 * This program and the accompanying materials are made available
 * under the terms of the Eclipse Distribution License v1.0 which
 * accompanies this distribution, is reproduced below, and is
 * available at http://www.eclipse.org/org/documents/edl-v10.php
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or
 * without modification, are permitted provided that the following
 * conditions are met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above
 *   copyright notice, this list of conditions and the following
 *   disclaimer in the documentation and/or other materials provided
 *   with the distribution.
 *
 * - Neither the name of the Eclipse Foundation, Inc. nor the
 *   names of its contributors may be used to endorse or promote
 *   products derived from this software without specific prior
 *   written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package org.eclipse.jgit.api;

import static org.eclipse.jgit.lib.Constants.R_STASH;

import java.io.File;
import java.io.IOException;
import java.nio.file.StandardCopyOption;
import java.text.MessageFormat;
import java.util.List;

import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.errors.InvalidRefNameException;
import org.eclipse.jgit.api.errors.JGitInternalException;
import org.eclipse.jgit.api.errors.RefNotFoundException;
import org.eclipse.jgit.errors.LockFailedException;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.internal.storage.file.ReflogWriter;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.RefUpdate.Result;
import org.eclipse.jgit.lib.ReflogEntry;
import org.eclipse.jgit.lib.ReflogReader;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.util.FileUtils;

/**
 * Command class to delete a stashed commit reference
 *
 * @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 StashDropCommand extends GitCommand<ObjectId> {

	private int stashRefEntry;

	private boolean all;

	/**
	 * @param repo
	 */
	public StashDropCommand(Repository repo) {
		super(repo);
	}

	/**
	 * Set the stash reference to drop (0-based).
	 * <p>
	 * This will default to drop the latest stashed commit (stash@{0}) if
	 * unspecified
	 *
	 * @param stashRef
	 * @return {@code this}
	 */
	public StashDropCommand setStashRef(final int stashRef) {
		if (stashRef < 0)
			throw new IllegalArgumentException();

		stashRefEntry = stashRef;
		return this;
	}

	/**
	 * Set wheter drop all stashed commits
	 *
	 * @param all
	 *            true to drop all stashed commits, false to drop only the
	 *            stashed commit set via calling {@link #setStashRef(int)}
	 * @return {@code this}
	 */
	public StashDropCommand setAll(final boolean all) {
		this.all = all;
		return this;
	}

	private Ref getRef() throws GitAPIException {
		try {
			return repo.exactRef(R_STASH);
		} catch (IOException e) {
			throw new InvalidRefNameException(MessageFormat.format(
					JGitText.get().cannotRead, R_STASH), e);
		}
	}

	private RefUpdate createRefUpdate(final Ref stashRef) throws IOException {
		RefUpdate update = repo.updateRef(R_STASH);
		update.disableRefLog();
		update.setExpectedOldObjectId(stashRef.getObjectId());
		update.setForceUpdate(true);
		return update;
	}

	private void deleteRef(final Ref stashRef) {
		try {
			Result result = createRefUpdate(stashRef).delete();
			if (Result.FORCED != result)
				throw new JGitInternalException(MessageFormat.format(
						JGitText.get().stashDropDeleteRefFailed, result));
		} catch (IOException e) {
			throw new JGitInternalException(JGitText.get().stashDropFailed, e);
		}
	}

	private void updateRef(Ref stashRef, ObjectId newId) {
		try {
			RefUpdate update = createRefUpdate(stashRef);
			update.setNewObjectId(newId);
			Result result = update.update();
			switch (result) {
			case FORCED:
			case NEW:
			case NO_CHANGE:
				return;
			default:
				throw new JGitInternalException(MessageFormat.format(
						JGitText.get().updatingRefFailed, R_STASH, newId,
						result));
			}
		} catch (IOException e) {
			throw new JGitInternalException(JGitText.get().stashDropFailed, e);
		}
	}

	/**
	 * Drop the configured entry from the stash reflog and return value of the
	 * stash reference after the drop occurs
	 *
	 * @return commit id of stash reference or null if no more stashed changes
	 * @throws GitAPIException
	 */
	public ObjectId call() throws GitAPIException {
		checkCallable();

		Ref stashRef = getRef();
		if (stashRef == null)
			return null;

		if (all) {
			deleteRef(stashRef);
			return null;
		}

		List<ReflogEntry> entries;
		try {
			ReflogReader reader = repo.getReflogReader(R_STASH);
			if (reader == null) {
				throw new RefNotFoundException(MessageFormat
						.format(JGitText.get().refNotResolved, stashRef));
			}
			entries = reader.getReverseEntries();
		} catch (IOException e) {
			throw new JGitInternalException(JGitText.get().stashDropFailed, e);
		}

		if (stashRefEntry >= entries.size())
			throw new JGitInternalException(
					JGitText.get().stashDropMissingReflog);

		if (entries.size() == 1) {
			deleteRef(stashRef);
			return null;
		}

		ReflogWriter writer = new ReflogWriter(repo, true);
		String stashLockRef = ReflogWriter.refLockFor(R_STASH);
		File stashLockFile = writer.logFor(stashLockRef);
		File stashFile = writer.logFor(R_STASH);
		if (stashLockFile.exists())
			throw new JGitInternalException(JGitText.get().stashDropFailed,
					new LockFailedException(stashFile));

		entries.remove(stashRefEntry);
		ObjectId entryId = ObjectId.zeroId();
		try {
			for (int i = entries.size() - 1; i >= 0; i--) {
				ReflogEntry entry = entries.get(i);
				writer.log(stashLockRef, entryId, entry.getNewId(),
						entry.getWho(), entry.getComment());
				entryId = entry.getNewId();
			}
			try {
				FileUtils.rename(stashLockFile, stashFile,
						StandardCopyOption.ATOMIC_MOVE);
			} catch (IOException e) {
					throw new JGitInternalException(MessageFormat.format(
							JGitText.get().renameFileFailed,
								stashLockFile.getPath(), stashFile.getPath()),
						e);
			}
		} catch (IOException e) {
			throw new JGitInternalException(JGitText.get().stashDropFailed, e);
		}
		updateRef(stashRef, entryId);

		try {
			Ref newStashRef = repo.exactRef(R_STASH);
			return newStashRef != null ? newStashRef.getObjectId() : null;
		} catch (IOException e) {
			throw new InvalidRefNameException(MessageFormat.format(
					JGitText.get().cannotRead, R_STASH), e);
		}
	}
}
