/**
 * <copyright> 
 *
 * Copyright (c) 2002-2004 IBM Corporation and others.
 * All rights reserved.   This program and the accompanying materials
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 * 
 * Contributors: 
 *   IBM - Initial API and implementation
 *
 * </copyright>
 *
 * $Id: StrictCompoundCommand.java,v 1.1 2005/04/15 23:31:25 david_williams Exp $
 */
package org.eclipse.emf.common.command;


import java.util.List;
import java.util.ListIterator;

import org.eclipse.wst.sse.core.internal.Logger;


/**
 * A composite command which assumes that later commands in the list may
 * depend on the results and side-effects of earlier commands in the list.
 * Because of this, it must implement {@link Command#canExecute} more
 * carefully, i.e., in order to determine canExecute for the composite, it
 * doesn't simply test each command. It tests the first command to see if it
 * can execute; then, if there is another command in the list, it checks if
 * the first command can undo and then goes ahead and executes it! This
 * process is repeated until the last command that is not followed by another,
 * which then determines the final result. (For efficiency, when this
 * processing gets to the last command, that command is tested for canUndo too
 * and that result is cached.) All the commands that have been executed are
 * then undone, if {@link #isPessimistic} is <code>true</code>; by default
 * it's <code>false</code>.
 * 
 * <p>
 * It is important for all but the last command to have no visible
 * side-effect! Multiple commands with visible side-effects must be composed
 * into a single command using just a {@link CompoundCommand} and that
 * composite could be the last command of a strict composite.
 * 
 * <p>
 * Here is an example of how this can be used in conjunction with a
 * {@link CommandWrapper}.
 * 
 * <pre>
 * 
 *  
 *     Command strictCompoundCommand = new StrictCompoundCommand();
 *     Command copyCommand = new CopyCommand(...);
 *     strictCompoundCommand.add(copyCommand);
 *  
 *     Command addCommand =
 *       new CommandWrapper()
 *       {
 *         public Command createCommand()
 *         {
 *           new AddCommand(parent, copyCommand.getResult()); 
 *         }
 *       };
 *     strictCompoundCommand.append(addCommand);
 *   
 *  
 * </pre>
 * 
 * Here the add command won't know which command to create until it has the
 * result of the copy command. The proxy makes sure the creation of the add
 * command is deferred and the strict composite ensures that execution
 * dependencies are met.
 */
public class StrictCompoundCommand extends CompoundCommand {
	/**
	 * The result for {@link Command#canUndo}.
	 */
	protected boolean isUndoable;

	/**
	 * Whether commands that have been tentatively executed need to be undone.
	 */
	protected boolean isPessimistic;

	/**
	 * Remember to call redo instead of execute for any command at or before
	 * this index in the list.
	 */
	protected int rightMostExecutedCommandIndex = -1;

	/**
	 * Creates an empty instance.
	 */
	public StrictCompoundCommand() {
		super();
		resultIndex = LAST_COMMAND_ALL;
	}

	/**
	 * Creates an instance with the given label.
	 * 
	 * @param label
	 *            the label.
	 */
	public StrictCompoundCommand(String label) {
		super(label);
		resultIndex = LAST_COMMAND_ALL;
	}

	/**
	 * Creates an instance with the given label and description.
	 * 
	 * @param label
	 *            the label.
	 * @param description
	 *            the description.
	 */
	public StrictCompoundCommand(String label, String description) {
		super(label, description);
		resultIndex = LAST_COMMAND_ALL;
	}

	/**
	 * Creates an instance with the given command list.
	 * 
	 * @param commandList
	 *            the list of commands.
	 */
	public StrictCompoundCommand(List commandList) {
		super(commandList);
		resultIndex = LAST_COMMAND_ALL;
	}

	/**
	 * Creates an instance with the given label and command list.
	 * 
	 * @param label
	 *            the label.
	 * @param commandList
	 *            the list of commands.
	 */
	public StrictCompoundCommand(String label, List commandList) {
		super(label, commandList);
		resultIndex = LAST_COMMAND_ALL;
	}

	/**
	 * Creates an instance with the given label, description, and command
	 * list.
	 * 
	 * @param label
	 *            the label.
	 * @param description
	 *            the description.
	 * @param commandList
	 *            the list of commands.
	 */
	public StrictCompoundCommand(String label, String description, List commandList) {
		super(label, description, commandList);
		resultIndex = LAST_COMMAND_ALL;
	}

	/**
	 * Returns <code>false</code> if any command on the list returns
	 * <code>false</code> for {@link Command#canExecute}, or if some
	 * command before the last one can't be undone and hence we can't test all
	 * the commands for executability.
	 * 
	 * @return whether the command can execute.
	 */
	protected boolean prepare() {
		// Go through the commands of the list.
		//
		ListIterator commands = commandList.listIterator();

		// If there are some...
		//
		if (commands.hasNext()) {
			boolean result = true;

			// The termination guard is in the body.
			//
			for (;;) {
				Command command = (Command) commands.next();
				if (command.canExecute()) {
					if (commands.hasNext()) {
						if (command.canUndo()) {
							try {
								if (commands.previousIndex() <= rightMostExecutedCommandIndex) {
									command.redo();
								}
								else {
									++rightMostExecutedCommandIndex;
									command.execute();
								}
							}
							catch (RuntimeException exception) {
								Logger.logException("_UI_IgnoreException_exception", exception);

								result = false;
								break;
							}
						}
						else {
							// We can't undo it, so we'd better give up.
							//
							result = false;
							break;
						}
					}
					else {
						// Now is the best time to record isUndoable because
						// later we would have to do all the executes again!
						// This makes canUndo very simple!
						//
						isUndoable = command.canUndo();
						break;
					}
				}
				else {
					// If we can't execute this one, we just can't do it at
					// all.
					//
					result = false;
					break;
				}
			}

			// If we are pessimistic, then we need to undo all the commands
			// that we have executed so far.
			//
			if (isPessimistic) {
				// The most recently processed command will never have been
				// executed.
				//
				commands.previous();

				// We want to unroll all the effects of the previous commands.
				//
				while (commands.hasPrevious()) {
					Command command = (Command) commands.previous();
					command.undo();
				}
			}

			return result;
		}
		else {
			isUndoable = false;
			return false;
		}
	}

	/**
	 * Calls {@link Command#execute} for each command in the list, but makes
	 * sure to call redo for any commands that were previously executed to
	 * compute canExecute. In the case that {@link #isPessimistic} is false,
	 * only the last command will be executed since the others will have been
	 * executed but not undone during {@link #prepare}.
	 */
	public void execute() {
		if (isPessimistic) {
			for (ListIterator commands = commandList.listIterator(); commands.hasNext();) {
				try {
					// Either execute or redo the command, as appropriate.
					//
					Command command = (Command) commands.next();
					if (commands.previousIndex() <= rightMostExecutedCommandIndex) {
						command.redo();
					}
					else {
						command.execute();
					}
				}
				catch (RuntimeException exception) {
					// Skip over the command that threw the exception.
					//
					commands.previous();

					// Iterate back over the executed commands to undo them.
					//
					while (commands.hasPrevious()) {
						commands.previous();
						Command command = (Command) commands.previous();
						if (command.canUndo()) {
							command.undo();
						}
						else {
							break;
						}
					}

					throw exception;
				}
			}
		}
		else if (!commandList.isEmpty()) {
			Command command = (Command) commandList.get(commandList.size() - 1);
			command.execute();
		}
	}

	/**
	 * Calls {@link Command#undo} for each command in the list. In the case
	 * that {@link #isPessimistic} is false, only the last command will be
	 * undone since the others will have been executed and not undo during
	 * {@link #prepare}.
	 */
	public void undo() {
		if (isPessimistic) {
			super.undo();
		}
		else if (!commandList.isEmpty()) {
			Command command = (Command) commandList.get(commandList.size() - 1);
			command.undo();
		}
	}

	/**
	 * Calls {@link Command#redo} for each command in the list. In the case
	 * that {@link #isPessimistic} is false, only the last command will be
	 * redone since the others will have been executed and not undo during
	 * {@link #prepare}.
	 */
	public void redo() {
		if (isPessimistic) {
			super.redo();
		}
		else if (!commandList.isEmpty()) {
			Command command = (Command) commandList.get(commandList.size() - 1);
			command.redo();
		}
	}

	/**
	 * Checks if the command can execute; if so, it is executed, appended to
	 * the list, and <code>true</code> is returned, if not, it is just
	 * disposed and <code>false</code> is returned. A typical use for this
	 * is to execute commands created during the execution of another command,
	 * e.g.,
	 * 
	 * <pre>
	 * class MyCommand extends AbstractCommand {
	 * 	protected Command subcommand;
	 * 
	 * 	//...
	 * 
	 * public void execute()
	 *       {
	 *         // ...
	 *         StrictCompoundCommand subcommands = new StrictCompoundCommand();
	 *         subcommands.appendAndExecute(new AddCommand(...));
	 *         if (condition) subcommands.appendAndExecute(new AddCommand(...));
	 *         subcommand = subcommands.unwrap();
	 *       }	public void undo() {
	 * 		// ...
	 * 		subcommand.undo();
	 * 	}
	 * 
	 * 	public void redo() {
	 * 		// ...
	 * 		subcommand.redo();
	 * 	}
	 * 
	 * 	public void dispose() {
	 * 		// ...
	 * 		if (subcommand != null) {
	 * 			subcommand.dispose();
	 * 		}
	 * 	}
	 * }
	 * 
	 * </pre>
	 * 
	 * @return whether the command was successfully executed and appended.
	 */
	public boolean appendAndExecute(Command command) {
		if (command != null) {
			if (!isPrepared) {
				if (commandList.isEmpty()) {
					isPrepared = true;
					isExecutable = true;
				}
				else {
					isExecutable = prepare();
					isPrepared = true;
					isPessimistic = true;
					if (isExecutable) {
						execute();
					}
				}
			}

			if (command.canExecute()) {
				try {
					command.execute();
					commandList.add(command);
					++rightMostExecutedCommandIndex;
					isUndoable = command.canUndo();
					return true;
				}
				catch (RuntimeException exception) {
					Logger.logException("_UI_IgnoreException_exception", exception);
				}
			}

			command.dispose();
		}

		return false;
	}

	/*
	 * Javadoc copied from base class.
	 */
	public String toString() {
		StringBuffer result = new StringBuffer(super.toString());
		result.append(" (isUndoable: " + isUndoable + ")");
		result.append(" (isPessimistic: " + isPessimistic + ")");
		result.append(" (rightMostExecutedCommandIndex: " + rightMostExecutedCommandIndex + ")");

		return result.toString();
	}
}
