/*
 * Copyright (C) 2008, Google 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.transport;

import static org.eclipse.jgit.transport.ReceiveCommand.Result.NOT_ATTEMPTED;
import static org.eclipse.jgit.transport.ReceiveCommand.Result.REJECTED_OTHER_REASON;

import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevObject;
import org.eclipse.jgit.revwalk.RevWalk;

/**
 * A command being processed by {@link BaseReceivePack}.
 * <p>
 * This command instance roughly translates to the server side representation of
 * the {@link RemoteRefUpdate} created by the client.
 */
public class ReceiveCommand {
	/** Type of operation requested. */
	public static enum Type {
		/** Create a new ref; the ref must not already exist. */
		CREATE,

		/**
		 * Update an existing ref with a fast-forward update.
		 * <p>
		 * During a fast-forward update no changes will be lost; only new
		 * commits are inserted into the ref.
		 */
		UPDATE,

		/**
		 * Update an existing ref by potentially discarding objects.
		 * <p>
		 * The current value of the ref is not fully reachable from the new
		 * value of the ref, so a successful command may result in one or more
		 * objects becoming unreachable.
		 */
		UPDATE_NONFASTFORWARD,

		/** Delete an existing ref; the ref should already exist. */
		DELETE;
	}

	/** Result of the update command. */
	public static enum Result {
		/** The command has not yet been attempted by the server. */
		NOT_ATTEMPTED,

		/** The server is configured to deny creation of this ref. */
		REJECTED_NOCREATE,

		/** The server is configured to deny deletion of this ref. */
		REJECTED_NODELETE,

		/** The update is a non-fast-forward update and isn't permitted. */
		REJECTED_NONFASTFORWARD,

		/** The update affects <code>HEAD</code> and cannot be permitted. */
		REJECTED_CURRENT_BRANCH,

		/**
		 * One or more objects aren't in the repository.
		 * <p>
		 * This is severe indication of either repository corruption on the
		 * server side, or a bug in the client wherein the client did not supply
		 * all required objects during the pack transfer.
		 */
		REJECTED_MISSING_OBJECT,

		/** Other failure; see {@link ReceiveCommand#getMessage()}. */
		REJECTED_OTHER_REASON,

		/** The ref could not be locked and updated atomically; try again. */
		LOCK_FAILURE,

		/** The change was completed successfully. */
		OK;
	}

	/**
	 * Filter a collection of commands according to result.
	 *
	 * @param in
	 *            commands to filter.
	 * @param want
	 *            desired status to filter by.
	 * @return a copy of the command list containing only those commands with
	 *         the desired status.
	 * @since 4.2
	 */
	public static List<ReceiveCommand> filter(Iterable<ReceiveCommand> in,
			Result want) {
		List<ReceiveCommand> r;
		if (in instanceof Collection)
			r = new ArrayList<>(((Collection<?>) in).size());
		else
			r = new ArrayList<>();
		for (ReceiveCommand cmd : in) {
			if (cmd.getResult() == want)
				r.add(cmd);
		}
		return r;
	}

	/**
	 * Filter a list of commands according to result.
	 *
	 * @param commands
	 *            commands to filter.
	 * @param want
	 *            desired status to filter by.
	 * @return a copy of the command list containing only those commands with
	 *         the desired status.
	 * @since 2.0
	 */
	public static List<ReceiveCommand> filter(List<ReceiveCommand> commands,
			Result want) {
		return filter((Iterable<ReceiveCommand>) commands, want);
	}

	/**
	 * Set unprocessed commands as failed due to transaction aborted.
	 * <p>
	 * If a command is still {@link Result#NOT_ATTEMPTED} it will be set to
	 * {@link Result#REJECTED_OTHER_REASON}.
	 *
	 * @param commands
	 *            commands to mark as failed.
	 * @since 4.2
	 */
	public static void abort(Iterable<ReceiveCommand> commands) {
		for (ReceiveCommand c : commands) {
			if (c.getResult() == NOT_ATTEMPTED) {
				c.setResult(REJECTED_OTHER_REASON,
						JGitText.get().transactionAborted);
			}
		}
	}

	private final ObjectId oldId;

	private final ObjectId newId;

	private final String name;

	private Type type;

	private Ref ref;

	private Result status = Result.NOT_ATTEMPTED;

	private String message;

	private boolean typeIsCorrect;

	/**
	 * Create a new command for {@link BaseReceivePack}.
	 *
	 * @param oldId
	 *            the expected old object id; must not be null. Use
	 *            {@link ObjectId#zeroId()} to indicate a ref creation.
	 * @param newId
	 *            the new object id; must not be null. Use
	 *            {@link ObjectId#zeroId()} to indicate a ref deletion.
	 * @param name
	 *            name of the ref being affected.
	 */
	public ReceiveCommand(final ObjectId oldId, final ObjectId newId,
			final String name) {
		if (oldId == null) {
			throw new IllegalArgumentException(JGitText.get().oldIdMustNotBeNull);
		}
		if (newId == null) {
			throw new IllegalArgumentException(JGitText.get().newIdMustNotBeNull);
		}
		this.oldId = oldId;
		this.newId = newId;
		this.name = name;

		type = Type.UPDATE;
		if (ObjectId.zeroId().equals(oldId)) {
			type = Type.CREATE;
		}
		if (ObjectId.zeroId().equals(newId)) {
			type = Type.DELETE;
		}
	}

	/**
	 * Create a new command for {@link BaseReceivePack}.
	 *
	 * @param oldId
	 *            the old object id; must not be null. Use
	 *            {@link ObjectId#zeroId()} to indicate a ref creation.
	 * @param newId
	 *            the new object id; must not be null. Use
	 *            {@link ObjectId#zeroId()} to indicate a ref deletion.
	 * @param name
	 *            name of the ref being affected.
	 * @param type
	 *            type of the command. Must be {@link Type#CREATE} if {@code
	 *            oldId} is zero, or {@link Type#DELETE} if {@code newId} is zero.
	 * @since 2.0
	 */
	public ReceiveCommand(final ObjectId oldId, final ObjectId newId,
			final String name, final Type type) {
		if (oldId == null) {
			throw new IllegalArgumentException(JGitText.get().oldIdMustNotBeNull);
		}
		if (newId == null) {
			throw new IllegalArgumentException(JGitText.get().newIdMustNotBeNull);
		}
		this.oldId = oldId;
		this.newId = newId;
		this.name = name;
		switch (type) {
		case CREATE:
			if (!ObjectId.zeroId().equals(oldId)) {
				throw new IllegalArgumentException(
						JGitText.get().createRequiresZeroOldId);
			}
			break;
		case DELETE:
			if (!ObjectId.zeroId().equals(newId)) {
				throw new IllegalArgumentException(
						JGitText.get().deleteRequiresZeroNewId);
			}
			break;
		case UPDATE:
		case UPDATE_NONFASTFORWARD:
			if (ObjectId.zeroId().equals(newId)
					|| ObjectId.zeroId().equals(oldId)) {
				throw new IllegalArgumentException(
						JGitText.get().updateRequiresOldIdAndNewId);
			}
			break;
		default:
			throw new IllegalStateException(JGitText.get().enumValueNotSupported0);
		}
		this.type = type;
	}

	/** @return the old value the client thinks the ref has. */
	public ObjectId getOldId() {
		return oldId;
	}

	/** @return the requested new value for this ref. */
	public ObjectId getNewId() {
		return newId;
	}

	/** @return the name of the ref being updated. */
	public String getRefName() {
		return name;
	}

	/** @return the type of this command; see {@link Type}. */
	public Type getType() {
		return type;
	}

	/** @return the ref, if this was advertised by the connection. */
	public Ref getRef() {
		return ref;
	}

	/** @return the current status code of this command. */
	public Result getResult() {
		return status;
	}

	/** @return the message associated with a failure status. */
	public String getMessage() {
		return message;
	}

	/**
	 * Set the status of this command.
	 *
	 * @param s
	 *            the new status code for this command.
	 */
	public void setResult(final Result s) {
		setResult(s, null);
	}

	/**
	 * Set the status of this command.
	 *
	 * @param s
	 *            new status code for this command.
	 * @param m
	 *            optional message explaining the new status.
	 */
	public void setResult(final Result s, final String m) {
		status = s;
		message = m;
	}

	/**
	 * Update the type of this command by checking for fast-forward.
	 * <p>
	 * If the command's current type is UPDATE, a merge test will be performed
	 * using the supplied RevWalk to determine if {@link #getOldId()} is fully
	 * merged into {@link #getNewId()}. If some commits are not merged the
	 * update type is changed to {@link Type#UPDATE_NONFASTFORWARD}.
	 *
	 * @param walk
	 *            an instance to perform the merge test with. The caller must
	 *            allocate and release this object.
	 * @throws IOException
	 *             either oldId or newId is not accessible in the repository
	 *             used by the RevWalk. This usually indicates data corruption,
	 *             and the command cannot be processed.
	 */
	public void updateType(RevWalk walk) throws IOException {
		if (typeIsCorrect)
			return;
		if (type == Type.UPDATE && !AnyObjectId.equals(oldId, newId)) {
			RevObject o = walk.parseAny(oldId);
			RevObject n = walk.parseAny(newId);
			if (!(o instanceof RevCommit)
					|| !(n instanceof RevCommit)
					|| !walk.isMergedInto((RevCommit) o, (RevCommit) n))
				setType(Type.UPDATE_NONFASTFORWARD);
		}
		typeIsCorrect = true;
	}

	/**
	 * Execute this command during a receive-pack session.
	 * <p>
	 * Sets the status of the command as a side effect.
	 *
	 * @param rp
	 *            receive-pack session.
	 * @since 2.0
	 */
	public void execute(final BaseReceivePack rp) {
		try {
			final RefUpdate ru = rp.getRepository().updateRef(getRefName());
			ru.setRefLogIdent(rp.getRefLogIdent());
			switch (getType()) {
			case DELETE:
				if (!ObjectId.zeroId().equals(getOldId())) {
					// We can only do a CAS style delete if the client
					// didn't bork its delete request by sending the
					// wrong zero id rather than the advertised one.
					//
					ru.setExpectedOldObjectId(getOldId());
				}
				ru.setForceUpdate(true);
				setResult(ru.delete(rp.getRevWalk()));
				break;

			case CREATE:
			case UPDATE:
			case UPDATE_NONFASTFORWARD:
				ru.setForceUpdate(rp.isAllowNonFastForwards());
				ru.setExpectedOldObjectId(getOldId());
				ru.setNewObjectId(getNewId());
				ru.setRefLogMessage("push", true); //$NON-NLS-1$
				setResult(ru.update(rp.getRevWalk()));
				break;
			}
		} catch (IOException err) {
			reject(err);
		}
	}

	void setRef(final Ref r) {
		ref = r;
	}

	void setType(final Type t) {
		type = t;
	}

	void setTypeFastForwardUpdate() {
		type = Type.UPDATE;
		typeIsCorrect = true;
	}

	/**
	 * Set the result of this command.
	 *
	 * @param r
	 *            the new result code for this command.
	 */
	public void setResult(RefUpdate.Result r) {
		switch (r) {
		case NOT_ATTEMPTED:
			setResult(Result.NOT_ATTEMPTED);
			break;

		case LOCK_FAILURE:
		case IO_FAILURE:
			setResult(Result.LOCK_FAILURE);
			break;

		case NO_CHANGE:
		case NEW:
		case FORCED:
		case FAST_FORWARD:
			setResult(Result.OK);
			break;

		case REJECTED:
			setResult(Result.REJECTED_NONFASTFORWARD);
			break;

		case REJECTED_CURRENT_BRANCH:
			setResult(Result.REJECTED_CURRENT_BRANCH);
			break;

		case REJECTED_MISSING_OBJECT:
			setResult(Result.REJECTED_MISSING_OBJECT);
			break;

		case REJECTED_OTHER_REASON:
			setResult(Result.REJECTED_OTHER_REASON);
			break;

		default:
			setResult(Result.REJECTED_OTHER_REASON, r.name());
			break;
		}
	}

	void reject(IOException err) {
		setResult(Result.REJECTED_OTHER_REASON, MessageFormat.format(
				JGitText.get().lockError, err.getMessage()));
	}

	@SuppressWarnings("nls")
	@Override
	public String toString() {
		return getType().name() + ": " + getOldId().name() + " "
				+ getNewId().name() + " " + getRefName();
	}
}
