/**
 * <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.1 2005/04/15 23:31:25 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("_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("_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("_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 "_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 "_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 "_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 "_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("_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: #" + commandList.size() + ")");
		result.append(" (resultIndex: " + resultIndex + ")");

		return result.toString();
	}
}
