/**
 * <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: CompoundCommand.java,v 1.3 2005/06/06 05:36:11 david_williams Exp $
 */
package org.eclipse.emf.common.command;


import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

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


/**
 * A command that comprises a sequence of subcommands. Derived classes can
 * control the way results are accumulated from the individual commands; the
 * default behaviour is to return the result of the last command.
 */
public class CompoundCommand extends AbstractCommand {
	/**
	 * The list of subcommands.
	 */
	protected List commandList;

	/**
	 * When {@link #resultIndex} is set to this, {@link #getResult} and
	 * {@link #getAffectedObjects} are delegated to the last command, if any,
	 * in the list.
	 */
	public static final int LAST_COMMAND_ALL = Integer.MIN_VALUE;

	/**
	 * When {@link #resultIndex} is set to this, {@link #getResult} and
	 * {@link #getAffectedObjects} are set to the result of merging the
	 * corresponding collection of each command in the list.
	 */
	public static final int MERGE_COMMAND_ALL = Integer.MIN_VALUE - 1;

	/**
	 * The index of the command whose result and affected objects are
	 * forwarded. Negative values have special meaning, as defined by the
	 * static constants. A value of -1 indicates that the last command in the
	 * list should be used. We could have more special behaviours implemented
	 * for other negative values.
	 */
	protected int resultIndex = MERGE_COMMAND_ALL;

	/**
	 * Creates an empty instance.
	 */
	public CompoundCommand() {
		super();
		commandList = new ArrayList();
	}

	/**
	 * Creates an instance with the given label.
	 * 
	 * @param label
	 *            the label.
	 */
	public CompoundCommand(String label) {
		super(label);
		commandList = new ArrayList();
	}

	/**
	 * Creates an instance with the given label and description.
	 * 
	 * @param label
	 *            the label.
	 * @param description
	 *            the description.
	 */
	public CompoundCommand(String label, String description) {
		super(label, description);
		commandList = new ArrayList();
	}

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

	/**
	 * Creates instance with the given label and list.
	 * 
	 * @param label
	 *            the label.
	 * @param commandList
	 *            the list of commands.
	 */
	public CompoundCommand(String label, List commandList) {
		super(label);
		this.commandList = commandList;
	}

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

	/**
	 * Creates an empty instance with the given result index.
	 * 
	 * @param resultIndex
	 *            the {@link #resultIndex}.
	 */
	public CompoundCommand(int resultIndex) {
		super();
		this.resultIndex = resultIndex;
		commandList = new ArrayList();
	}

	/**
	 * Creates an instance with the given result index and label.
	 * 
	 * @param resultIndex
	 *            the {@link #resultIndex}.
	 * @param label
	 *            the label.
	 */
	public CompoundCommand(int resultIndex, String label) {
		super(label);
		this.resultIndex = resultIndex;
		commandList = new ArrayList();
	}

	/**
	 * Creates an instance with the given result index, label, and
	 * description.
	 * 
	 * @param resultIndex
	 *            the {@link #resultIndex}.
	 * @param label
	 *            the label.
	 * @param description
	 *            the description.
	 */
	public CompoundCommand(int resultIndex, String label, String description) {
		super(label, description);
		this.resultIndex = resultIndex;
		commandList = new ArrayList();
	}

	/**
	 * Creates an instance with the given result index and list.
	 * 
	 * @param resultIndex
	 *            the {@link #resultIndex}.
	 * @param commandList
	 *            the list of commands.
	 */
	public CompoundCommand(int resultIndex, List commandList) {
		super();
		this.resultIndex = resultIndex;
		this.commandList = commandList;
	}

	/**
	 * Creates an instance with the given resultIndex, label, and list.
	 * 
	 * @param resultIndex
	 *            the {@link #resultIndex}.
	 * @param label
	 *            the label.
	 * @param commandList
	 *            the list of commands.
	 */
	public CompoundCommand(int resultIndex, String label, List commandList) {
		super(label);
		this.resultIndex = resultIndex;
		this.commandList = commandList;
	}

	/**
	 * Creates an instance with the given result index, label, description,
	 * and list.
	 * 
	 * @param resultIndex
	 *            the {@link #resultIndex}.
	 * @param label
	 *            the label.
	 * @param description
	 *            the description.
	 * @param commandList
	 *            the list of commands.
	 */
	public CompoundCommand(int resultIndex, String label, String description, List commandList) {
		super(label, description);
		this.resultIndex = resultIndex;
		this.commandList = commandList;
	}

	/**
	 * Returns whether there are commands in the list.
	 * 
	 * @return whether there are commands in the list.
	 */
	public boolean isEmpty() {
		return commandList.isEmpty();
	}

	/**
	 * Returns an unmodifiable view of the commands in the list.
	 * 
	 * @return an unmodifiable view of the commands in the list.
	 */
	public List getCommandList() {
		return Collections.unmodifiableList(commandList);
	}

	/**
	 * Returns the index of the command whose result and affected objects are
	 * forwarded. Negative values have special meaning, as defined by the
	 * static constants.
	 * 
	 * @return the index of the command whose result and affected objects are
	 *         forwarded.
	 * @see #LAST_COMMAND_ALL
	 * @see #MERGE_COMMAND_ALL
	 */
	public int getResultIndex() {
		return resultIndex;
	}

	/**
	 * Returns whether all the commands can execute so that
	 * {@link #isExecutable} can be cached. An empty command list causes
	 * <code>false</code> to be returned.
	 * 
	 * @return whether all the commands can execute.
	 */
	protected boolean prepare() {
		if (commandList.isEmpty()) {
			return false;
		}
		else {
			for (Iterator commands = commandList.listIterator(); commands.hasNext();) {
				Command command = (Command) commands.next();
				if (!command.canExecute()) {
					return false;
				}
			}

			return true;
		}
	}

	/**
	 * Calls {@link Command#execute} for each command in the list.
	 */
	public void execute() {
		for (ListIterator commands = commandList.listIterator(); commands.hasNext();) {
			try {
				Command command = (Command) commands.next();
				command.execute();
			}
			catch (RuntimeException exception) {
				// Skip over the command that threw the exception.
				//
				commands.previous();

				try {
					// Iterate back over the executed commands to undo them.
					//
					while (commands.hasPrevious()) {
						Command command = (Command) commands.previous();
						if (command.canUndo()) {
							command.undo();
						}
						else {
							break;
						}
					}
				}
				catch (RuntimeException nestedException) {
					Logger.logException(UnDoCommonMessages._UI_IgnoreException_exception, nestedException);
				}

				throw exception;
			}
		}
	}

	/**
	 * Returns <code>false</code> if any of the commands return
	 * <code>false</code> for {@link Command#canUndo}.
	 * 
	 * @return <code>false</code> if any of the commands return
	 *         <code>false</code> for <code>canUndo</code>.
	 */
	public boolean canUndo() {
		for (Iterator commands = commandList.listIterator(); commands.hasNext();) {
			Command command = (Command) commands.next();
			if (!command.canUndo()) {
				return false;
			}
		}

		return true;
	}

	/**
	 * Calls {@link Command#undo} for each command in the list, in reverse
	 * order.
	 */
	public void undo() {
		for (ListIterator commands = commandList.listIterator(commandList.size()); commands.hasPrevious();) {
			try {
				Command command = (Command) commands.previous();
				command.undo();
			}
			catch (RuntimeException exception) {
				// Skip over the command that threw the exception.
				//
				commands.next();

				try {
					// Iterate forward over the undone commands to redo them.
					//
					while (commands.hasNext()) {
						Command command = (Command) commands.next();
						command.redo();
					}
				}
				catch (RuntimeException nestedException) {
					Logger.logException(UnDoCommonMessages._UI_IgnoreException_exception, exception);
				}


				throw exception;
			}
		}
	}

	/**
	 * Calls {@link Command#redo} for each command in the list.
	 */
	public void redo() {
		for (ListIterator commands = commandList.listIterator(); commands.hasNext();) {
			try {
				Command command = (Command) commands.next();
				command.redo();
			}
			catch (RuntimeException exception) {
				// Skip over the command that threw the exception.
				//
				commands.previous();

				try {
					// Iterate back over the executed commands to undo them.
					//
					while (commands.hasPrevious()) {
						Command command = (Command) commands.previous();
						command.undo();
					}
				}
				catch (RuntimeException nestedException) {
					Logger.logException(UnDoCommonMessages._UI_IgnoreException_exception, nestedException);
				}

				throw exception;
			}
		}
	}

	/**
	 * Determines the result by composing the results of the commands in the
	 * list; this is affected by the setting of {@link #resultIndex}.
	 * 
	 * @return the result.
	 */
	public Collection getResult() {
		if (commandList.isEmpty()) {
			return Collections.EMPTY_LIST;
		}
		else if (resultIndex == LAST_COMMAND_ALL) {
			return ((Command) commandList.get(commandList.size() - 1)).getResult();
		}
		else if (resultIndex == MERGE_COMMAND_ALL) {
			return getMergedResultCollection();
		}
		else if (resultIndex < commandList.size()) {
			return ((Command) commandList.get(resultIndex)).getResult();
		}
		else {
			return Collections.EMPTY_LIST;
		}
	}

	/**
	 * Returns the merged collection of all command results.
	 * 
	 * @return the merged collection of all command results.
	 */
	protected Collection getMergedResultCollection() {
		Collection result = new ArrayList();

		for (Iterator commands = commandList.iterator(); commands.hasNext();) {
			Command command = (Command) commands.next();
			result.addAll(command.getResult());
		}

		return result;
	}


	/**
	 * Determines the affected objects by composing the affected objects of
	 * the commands in the list; this is affected by the setting of
	 * {@link #resultIndex}.
	 * 
	 * @return the affected objects.
	 */
	public Collection getAffectedObjects() {
		if (commandList.isEmpty()) {
			return Collections.EMPTY_LIST;
		}
		else if (resultIndex == LAST_COMMAND_ALL) {
			return ((Command) commandList.get(commandList.size() - 1)).getAffectedObjects();
		}
		else if (resultIndex == MERGE_COMMAND_ALL) {
			return getMergedAffectedObjectsCollection();
		}
		else if (resultIndex < commandList.size()) {
			return ((Command) commandList.get(resultIndex)).getAffectedObjects();
		}
		else {
			return Collections.EMPTY_LIST;
		}
	}

	/**
	 * Returns the merged collection of all command affected objects.
	 * 
	 * @return the merged collection of all command affected objects.
	 */
	protected Collection getMergedAffectedObjectsCollection() {
		Collection result = new ArrayList();

		for (Iterator commands = commandList.iterator(); commands.hasNext();) {
			Command command = (Command) commands.next();
			result.addAll(command.getAffectedObjects());
		}

		return result;
	}

	/**
	 * Determines the label by composing the labels of the commands in the
	 * list; this is affected by the setting of {@link #resultIndex}.
	 * 
	 * @return the label.
	 */
	public String getLabel() {
		if (label != null) {
			return label;
		}
		else if (commandList.isEmpty()) {
			return UnDoCommonMessages._UI_CompoundCommand_label;
		}
		else if (resultIndex == LAST_COMMAND_ALL || resultIndex == MERGE_COMMAND_ALL) {
			return ((Command) commandList.get(commandList.size() - 1)).getLabel();
		}
		else if (resultIndex < commandList.size()) {
			return ((Command) commandList.get(resultIndex)).getLabel();
		}
		else {
			return UnDoCommonMessages._UI_CompoundCommand_label;
		}
	}

	/**
	 * Determines the description by composing the descriptions of the
	 * commands in the list; this is affected by the setting of
	 * {@link #resultIndex}.
	 * 
	 * @return the description.
	 */
	public String getDescription() {
		if (description != null) {
			return description;
		}
		else if (commandList.isEmpty()) {
			return UnDoCommonMessages._UI_CompoundCommand_description;
		}
		else if (resultIndex == LAST_COMMAND_ALL || resultIndex == MERGE_COMMAND_ALL) {
			return ((Command) commandList.get(commandList.size() - 1)).getDescription();
		}
		else if (resultIndex < commandList.size()) {
			return ((Command) commandList.get(resultIndex)).getDescription();
		}
		else {
			return UnDoCommonMessages._UI_CompoundCommand_description;
		}
	}

	/**
	 * Adds a command to this compound command's list of commands.
	 * 
	 * @param command
	 *            the command to append.
	 */
	public void append(Command command) {
		if (command != null) {
			commandList.add(command);
		}
	}

	/**
	 * Checks if the command can execute; if so, it is executed, appended to
	 * the list, and true is returned, if not, it is just disposed and false
	 * is returned. A typical use for this is to execute commands created
	 * during the execution of another command, e.g.,
	 * 
	 * <pre>
	 * class MyCommand extends CommandBase {
	 * 	protected Command subcommand;
	 * 
	 * 	//...
	 * 
	 * public void execute()
	 *               {
	 *                 // ...
	 *                 Compound subcommands = new CompoundCommand();
	 *                 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>
	 * 
	 * Another use is in an execute override of compound command itself:
	 * 
	 * <pre>
	 * class MyCommand extends CompoundCommand {
	 * public void execute()
	 *               {
	 *                 // ...
	 *                 appendAndExecute(new AddCommand(...));
	 *                 if (condition) appendAndExecute(new AddCommand(...));
	 *               }}
	 * 
	 * </pre>
	 * 
	 * Note that appending commands will modify what getResult and
	 * getAffectedObjects return, so you may want to set the resultIndex flag.
	 * 
	 * @param command
	 *            the command.
	 * @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;
					if (isExecutable) {
						execute();
					}
				}
			}

			if (command.canExecute()) {
				try {
					command.execute();
					commandList.add(command);
					return true;
				}
				catch (RuntimeException exception) {
					Logger.logException(UnDoCommonMessages._UI_IgnoreException_exception, exception);
				}
			}

			command.dispose();
		}

		return false;
	}

	/**
	 * Adds a command to this compound command's the list of commands and
	 * returns <code>true</code>, if
	 * <code>command.{@link org.eclipse.emf.common.command.Command#canExecute() canExecute()}</code>
	 * returns true; otherwise, it simply calls
	 * <code>command.{@link org.eclipse.emf.common.command.Command#dispose() dispose()}</code>
	 * and returns <code>false</code>.
	 * 
	 * @param command
	 *            the command.
	 * @return whether the command was executed and appended.
	 */
	public boolean appendIfCanExecute(Command command) {
		if (command == null) {
			return false;
		}
		else if (command.canExecute()) {
			commandList.add(command);
			return true;
		}
		else {
			command.dispose();
			return false;
		}
	}

	/**
	 * Calls {@link Command#dispose} for each command in the list.
	 */
	public void dispose() {
		for (Iterator commands = commandList.listIterator(); commands.hasNext();) {
			Command command = (Command) commands.next();
			command.dispose();
		}
	}

	/**
	 * Returns one of three things:
	 * {@link org.eclipse.emf.common.command.UnexecutableCommand#INSTANCE},
	 * if there are no commands, the one command, if there is exactly one
	 * command, or <code>this</code>, if there are multiple commands; this
	 * command is {@link #dispose}d in the first two cases. You should only
	 * unwrap a compound command if you created it for that purpose, e.g.,
	 * 
	 * <pre>
	 * CompoundCommand subcommands = new CompoundCommand();
	 * subcommands.append(x);
	 * if (condition)
	 * 	subcommands.append(y);
	 * Command result = subcommands.unwrap();
	 * </pre>
	 * 
	 * is a good way to create an efficient accumulated result.
	 * 
	 * @return the unwapped command.
	 */
	public Command unwrap() {
		switch (commandList.size()) {
			case 0 : {
				dispose();
				return UnexecutableCommand.INSTANCE;
			}
			case 1 : {
				Command result = (Command) commandList.remove(0);
				dispose();
				return result;
			}
			default : {
				return this;
			}
		}
	}

	/*
	 * Javadoc copied from base class.
	 */
	public String toString() {
		StringBuffer result = new StringBuffer(super.toString());
		result.append("" + commandList.size() + ""); //$NON-NLS-1$ //$NON-NLS-2$
		result.append("" + resultIndex + ""); //$NON-NLS-1$ //$NON-NLS-2$

		return result.toString();
	}
}
