/*******************************************************************************
 * Copyright (c) 2006, 2015 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.text.undo;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.operations.AbstractOperation;
import org.eclipse.core.commands.operations.IContextReplacingOperation;
import org.eclipse.core.commands.operations.IOperationHistory;
import org.eclipse.core.commands.operations.IOperationHistoryListener;
import org.eclipse.core.commands.operations.IUndoContext;
import org.eclipse.core.commands.operations.IUndoableOperation;
import org.eclipse.core.commands.operations.ObjectUndoContext;
import org.eclipse.core.commands.operations.OperationHistoryEvent;
import org.eclipse.core.commands.operations.OperationHistoryFactory;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.core.runtime.Status;

import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentExtension4;
import org.eclipse.jface.text.IDocumentListener;
import org.eclipse.jface.text.TextUtilities;

/**
 * A standard implementation of a document-based undo manager that
 * creates an undo history based on changes to its document.
 * <p>
 * Based on the 3.1 implementation of DefaultUndoManager, it was implemented
 * using the document-related manipulations defined in the original
 * DefaultUndoManager, by separating the document manipulations from the
 * viewer-specific processing.</p>
 * <p>
 * The classes representing individual text edits (formerly text commands)
 * were promoted from inner types to their own classes in order to support
 * reassignment to a different undo manager.<p>
 * <p>
 * This class is not intended to be subclassed.
 * </p>
 *
 * @see IDocumentUndoManager
 * @see DocumentUndoManagerRegistry
 * @see IDocumentUndoListener
 * @see org.eclipse.jface.text.IDocument
 * @since 3.2
 * @noextend This class is not intended to be subclassed by clients.
 */
public class DocumentUndoManager implements IDocumentUndoManager {


	/**
	 * Represents an undo-able text change, described as the
	 * replacement of some preserved text with new text.
	 * <p>
	 * Based on the DefaultUndoManager.TextCommand from R3.1.
	 * </p>
	 */
	private static class UndoableTextChange extends AbstractOperation {

		/** The start index of the replaced text. */
		protected int fStart= -1;

		/** The end index of the replaced text. */
		protected int fEnd= -1;

		/** The newly inserted text. */
		protected String fText;

		/** The replaced text. */
		protected String fPreservedText;

		/** The undo modification stamp. */
		protected long fUndoModificationStamp= IDocumentExtension4.UNKNOWN_MODIFICATION_STAMP;

		/** The redo modification stamp. */
		protected long fRedoModificationStamp= IDocumentExtension4.UNKNOWN_MODIFICATION_STAMP;

		/** The undo manager that generated the change. */
		protected DocumentUndoManager fDocumentUndoManager;

		/**
		 * Creates a new text change.
		 *
		 * @param manager the undo manager for this change
		 */
		UndoableTextChange(DocumentUndoManager manager) {
			super(UndoMessages.getString("DocumentUndoManager.operationLabel")); //$NON-NLS-1$
			this.fDocumentUndoManager= manager;
			addContext(manager.getUndoContext());
		}

		/**
		 * Re-initializes this text change.
		 */
		protected void reinitialize() {
			fStart= fEnd= -1;
			fText= fPreservedText= null;
			fUndoModificationStamp= IDocumentExtension4.UNKNOWN_MODIFICATION_STAMP;
			fRedoModificationStamp= IDocumentExtension4.UNKNOWN_MODIFICATION_STAMP;
		}

		/**
		 * Sets the start and the end index of this change.
		 *
		 * @param start the start index
		 * @param end the end index
		 */
		protected void set(int start, int end) {
			fStart= start;
			fEnd= end;
			fText= null;
			fPreservedText= null;
		}

		@Override
		public void dispose() {
			reinitialize();
		}

		/**
		 * Undo the change described by this change.
		 */
		protected void undoTextChange() {
			try {
				if (fDocumentUndoManager.fDocument instanceof IDocumentExtension4)
					((IDocumentExtension4) fDocumentUndoManager.fDocument).replace(fStart, fText
							.length(), fPreservedText, fUndoModificationStamp);
				else
					fDocumentUndoManager.fDocument.replace(fStart, fText.length(),
							fPreservedText);
			} catch (BadLocationException x) {
			}
		}

		@Override
		public boolean canUndo() {
			if (isValid()) {
				if (fDocumentUndoManager.fDocument instanceof IDocumentExtension4) {
					long docStamp= ((IDocumentExtension4) fDocumentUndoManager.fDocument)
							.getModificationStamp();

					// Normal case: an undo is valid if its redo will restore
					// document to its current modification stamp
					boolean canUndo= docStamp == IDocumentExtension4.UNKNOWN_MODIFICATION_STAMP
							|| docStamp >= getRedoModificationStamp();

					/*
					 * Special case to check if the answer is false. If the last
					 * document change was empty, then the document's modification
					 * stamp was incremented but nothing was committed. The
					 * operation being queried has an older stamp. In this case
					 * only, the comparison is different. A sequence of document
					 * changes that include an empty change is handled correctly
					 * when a valid commit follows the empty change, but when
					 * #canUndo() is queried just after an empty change, we must
					 * special case the check. The check is very specific to prevent
					 * false positives. see
					 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=98245
					 */
					if (!canUndo
							&& this == fDocumentUndoManager.fHistory
									.getUndoOperation(fDocumentUndoManager.fUndoContext)
								// this is the latest operation
							&& this != fDocumentUndoManager.fCurrent
								// there is a more current operation not on the stack
							&& !fDocumentUndoManager.fCurrent.isValid()
							// the current operation is not a valid document
							// modification
							&& fDocumentUndoManager.fCurrent.fUndoModificationStamp !=
							// the invalid current operation has a document stamp
							IDocumentExtension4.UNKNOWN_MODIFICATION_STAMP) {
						canUndo= fDocumentUndoManager.fCurrent.fRedoModificationStamp == docStamp;
					}
					/*
					 * When the composite is the current operation, it may hold the
					 * timestamp of a no-op change. We check this here rather than
					 * in an override of canUndo() in UndoableCompoundTextChange simply to
					 * keep all the special case checks in one place.
					 */
					if (!canUndo
							&& this == fDocumentUndoManager.fHistory
									.getUndoOperation(fDocumentUndoManager.fUndoContext)
							&& // this is the latest operation
							this instanceof UndoableCompoundTextChange
							&& this == fDocumentUndoManager.fCurrent
							&& // this is the current operation
							this.fStart == -1
							&& // the current operation text is not valid
							fDocumentUndoManager.fCurrent.fRedoModificationStamp != IDocumentExtension4.UNKNOWN_MODIFICATION_STAMP) {
							// but it has a redo stamp
						canUndo= fDocumentUndoManager.fCurrent.fRedoModificationStamp == docStamp;
					}
					return canUndo;

				}
				// if there is no timestamp to check, simply return true per the
				// 3.0.1 behavior
				return true;
			}
			return false;
		}

		@Override
		public boolean canRedo() {
			if (isValid()) {
				if (fDocumentUndoManager.fDocument instanceof IDocumentExtension4) {
					long docStamp= ((IDocumentExtension4) fDocumentUndoManager.fDocument)
							.getModificationStamp();
					return docStamp == IDocumentExtension4.UNKNOWN_MODIFICATION_STAMP
							|| docStamp == getUndoModificationStamp();
				}
				// if there is no timestamp to check, simply return true per the
				// 3.0.1 behavior
				return true;
			}
			return false;
		}

		@Override
		public boolean canExecute() {
			return fDocumentUndoManager.isConnected();
		}

		@Override
		public IStatus execute(IProgressMonitor monitor, IAdaptable uiInfo) {
			// Text changes execute as they are typed, so executing one has no
			// effect.
			return Status.OK_STATUS;
		}

		/**
		 * {@inheritDoc}
		 * Notifies clients about the undo.
		 */
		@Override
		public IStatus undo(IProgressMonitor monitor, IAdaptable uiInfo) {
			if (isValid()) {
				fDocumentUndoManager.fireDocumentUndo(fStart, fPreservedText, fText, uiInfo, DocumentUndoEvent.ABOUT_TO_UNDO, false);
				undoTextChange();
				fDocumentUndoManager.resetProcessChangeState();
				fDocumentUndoManager.fireDocumentUndo(fStart, fPreservedText, fText, uiInfo, DocumentUndoEvent.UNDONE, false);
				return Status.OK_STATUS;
			}
			return IOperationHistory.OPERATION_INVALID_STATUS;
		}

		/**
		 * Re-applies the change described by this change.
		 */
		protected void redoTextChange() {
			try {
				if (fDocumentUndoManager.fDocument instanceof IDocumentExtension4)
					((IDocumentExtension4) fDocumentUndoManager.fDocument).replace(fStart, fEnd - fStart, fText, fRedoModificationStamp);
				else
					fDocumentUndoManager.fDocument.replace(fStart, fEnd - fStart, fText);
			} catch (BadLocationException x) {
			}
		}

		/**
		 * Re-applies the change described by this change that was previously
		 * undone. Also notifies clients about the redo.
		 *
		 * @param monitor the progress monitor to use if necessary
		 * @param uiInfo an adaptable that can provide UI info if needed
		 * @return the status
		 */
		@Override
		public IStatus redo(IProgressMonitor monitor, IAdaptable uiInfo) {
			if (isValid()) {
				fDocumentUndoManager.fireDocumentUndo(fStart, fText, fPreservedText, uiInfo, DocumentUndoEvent.ABOUT_TO_REDO, false);
				redoTextChange();
				fDocumentUndoManager.resetProcessChangeState();
				fDocumentUndoManager.fireDocumentUndo(fStart, fText, fPreservedText, uiInfo, DocumentUndoEvent.REDONE, false);
				return Status.OK_STATUS;
			}
			return IOperationHistory.OPERATION_INVALID_STATUS;
		}

		/**
		 * Update the change in response to a commit.
		 */

		protected void updateTextChange() {
			fText= fDocumentUndoManager.fTextBuffer.toString();
			fDocumentUndoManager.fTextBuffer.setLength(0);
			fPreservedText= fDocumentUndoManager.fPreservedTextBuffer.toString();
			fDocumentUndoManager.fPreservedTextBuffer.setLength(0);
		}

		/**
		 * Creates a new uncommitted text change depending on whether a compound
		 * change is currently being executed.
		 *
		 * @return a new, uncommitted text change or a compound text change
		 */
		protected UndoableTextChange createCurrent() {
			if (fDocumentUndoManager.fFoldingIntoCompoundChange)
				return new UndoableCompoundTextChange(fDocumentUndoManager);
			return new UndoableTextChange(fDocumentUndoManager);
		}

		/**
		 * Commits the current change into this one.
		 */
		protected void commit() {
			if (fStart < 0) {
				if (fDocumentUndoManager.fFoldingIntoCompoundChange) {
					fDocumentUndoManager.fCurrent= createCurrent();
				} else {
					reinitialize();
				}
			} else {
				updateTextChange();
				fDocumentUndoManager.fCurrent= createCurrent();
			}
			fDocumentUndoManager.resetProcessChangeState();
		}

		/**
		 * Updates the text from the buffers without resetting the buffers or adding
		 * anything to the stack.
		 */
		protected void pretendCommit() {
			if (fStart > -1) {
				fText= fDocumentUndoManager.fTextBuffer.toString();
				fPreservedText= fDocumentUndoManager.fPreservedTextBuffer.toString();
			}
		}

		/**
		 * Attempt a commit of this change and answer true if a new fCurrent was
		 * created as a result of the commit.
		 *
		 * @return <code>true</code> if the change was committed and created
		 *			a new <code>fCurrent</code>, <code>false</code> if not
		 */
		protected boolean attemptCommit() {
			pretendCommit();
			if (isValid()) {
				fDocumentUndoManager.commit();
				return true;
			}
			return false;
		}

		/**
		 * Checks whether this text change is valid for undo or redo.
		 *
		 * @return <code>true</code> if the change is valid for undo or redo
		 */
		protected boolean isValid() {
			return fStart > -1 && fEnd > -1 && fText != null;
		}

		@Override
		public String toString() {
			String delimiter= ", "; //$NON-NLS-1$
			StringBuffer text= new StringBuffer(super.toString());
			text.append("\n"); //$NON-NLS-1$
			text.append(this.getClass().getName());
			text.append(" undo modification stamp: "); //$NON-NLS-1$
			text.append(fUndoModificationStamp);
			text.append(" redo modification stamp: "); //$NON-NLS-1$
			text.append(fRedoModificationStamp);
			text.append(" start: "); //$NON-NLS-1$
			text.append(fStart);
			text.append(delimiter);
			text.append("end: "); //$NON-NLS-1$
			text.append(fEnd);
			text.append(delimiter);
			text.append("text: '"); //$NON-NLS-1$
			text.append(fText);
			text.append('\'');
			text.append(delimiter);
			text.append("preservedText: '"); //$NON-NLS-1$
			text.append(fPreservedText);
			text.append('\'');
			return text.toString();
		}

		/**
		 * Return the undo modification stamp
		 *
		 * @return the undo modification stamp for this change
		 */
		protected long getUndoModificationStamp() {
			return fUndoModificationStamp;
		}

		/**
		 * Return the redo modification stamp
		 *
		 * @return the redo modification stamp for this change
		 */
		protected long getRedoModificationStamp() {
			return fRedoModificationStamp;
		}
	}


	/**
	 * Represents an undo-able text change consisting of several individual
	 * changes.
	 */
	private static class UndoableCompoundTextChange extends UndoableTextChange {

		/** The list of individual changes */
		private List<UndoableTextChange> fChanges= new ArrayList<>();

		/**
		 * Creates a new compound text change.
		 *
		 * @param manager the undo manager for this change
		 */
		UndoableCompoundTextChange(DocumentUndoManager manager) {
			super(manager);
		}

		/**
		 * Adds a new individual change to this compound change.
		 *
		 * @param change the change to be added
		 */
		protected void add(UndoableTextChange change) {
			fChanges.add(change);
		}

		@Override
		public IStatus undo(IProgressMonitor monitor, IAdaptable uiInfo) {

			int size= fChanges.size();
			if (size > 0) {
				UndoableTextChange c;

				c= fChanges.get(0);
				fDocumentUndoManager.fireDocumentUndo(c.fStart, c.fPreservedText, c.fText, uiInfo, DocumentUndoEvent.ABOUT_TO_UNDO, true);

				for (int i= size - 1; i >= 0; --i) {
					c= fChanges.get(i);
					c.undoTextChange();
				}
				fDocumentUndoManager.resetProcessChangeState();
				fDocumentUndoManager.fireDocumentUndo(c.fStart, c.fPreservedText, c.fText, uiInfo,
						DocumentUndoEvent.UNDONE, true);
			}
			return Status.OK_STATUS;
		}

		@Override
		public IStatus redo(IProgressMonitor monitor, IAdaptable uiInfo) {

			int size= fChanges.size();
			if (size > 0) {

				UndoableTextChange c;
				c= fChanges.get(size - 1);
				fDocumentUndoManager.fireDocumentUndo(c.fStart, c.fText, c.fPreservedText, uiInfo, DocumentUndoEvent.ABOUT_TO_REDO, true);

				for (int i= 0; i <= size - 1; ++i) {
					c= fChanges.get(i);
					c.redoTextChange();
				}
				fDocumentUndoManager.resetProcessChangeState();
				fDocumentUndoManager.fireDocumentUndo(c.fStart, c.fText, c.fPreservedText, uiInfo, DocumentUndoEvent.REDONE, true);
			}

			return Status.OK_STATUS;
		}

		@Override
		protected void updateTextChange() {
			// first gather the data from the buffers
			super.updateTextChange();

			// the result of the update is stored as a child change
			UndoableTextChange c= new UndoableTextChange(fDocumentUndoManager);
			c.fStart= fStart;
			c.fEnd= fEnd;
			c.fText= fText;
			c.fPreservedText= fPreservedText;
			c.fUndoModificationStamp= fUndoModificationStamp;
			c.fRedoModificationStamp= fRedoModificationStamp;
			add(c);

			// clear out all indexes now that the child is added
			reinitialize();
		}

		@Override
		protected UndoableTextChange createCurrent() {

			if (!fDocumentUndoManager.fFoldingIntoCompoundChange)
				return new UndoableTextChange(fDocumentUndoManager);

			reinitialize();
			return this;
		}

		@Override
		protected void commit() {
			// if there is pending data, update the text change
			if (fStart > -1)
				updateTextChange();
			fDocumentUndoManager.fCurrent= createCurrent();
			fDocumentUndoManager.resetProcessChangeState();
		}

		@Override
		protected boolean isValid() {
			return fStart > -1 || fChanges.size() > 0;
		}

		@Override
		protected long getUndoModificationStamp() {
			if (fStart > -1)
				return super.getUndoModificationStamp();
			else if (fChanges.size() > 0)
				return fChanges.get(0)
						.getUndoModificationStamp();

			return fUndoModificationStamp;
		}

		@Override
		protected long getRedoModificationStamp() {
			if (fStart > -1)
				return super.getRedoModificationStamp();
			else if (fChanges.size() > 0)
				return fChanges.get(fChanges.size() - 1)
						.getRedoModificationStamp();

			return fRedoModificationStamp;
		}
	}


	/**
	 * Internal listener to document changes.
	 */
	private class DocumentListener implements IDocumentListener {

		private String fReplacedText;

		@Override
		public void documentAboutToBeChanged(DocumentEvent event) {
			try {
				fReplacedText= event.getDocument().get(event.getOffset(),
						event.getLength());
				fPreservedUndoModificationStamp= event.getModificationStamp();
			} catch (BadLocationException x) {
				fReplacedText= null;
			}
		}

		@Override
		public void documentChanged(DocumentEvent event) {
			fPreservedRedoModificationStamp= event.getModificationStamp();

			// record the current valid state for the top operation in case it
			// remains the
			// top operation but changes state.
			IUndoableOperation op= fHistory.getUndoOperation(fUndoContext);
			boolean wasValid= false;
			if (op != null)
				wasValid= op.canUndo();
			// Process the change, providing the before and after timestamps
			processChange(event.getOffset(), event.getOffset()
					+ event.getLength(), event.getText(), fReplacedText,
					fPreservedUndoModificationStamp,
					fPreservedRedoModificationStamp);

			// now update fCurrent with the latest buffers from the document
			// change.
			fCurrent.pretendCommit();

			if (op == fCurrent) {
				// if the document change did not cause a new fCurrent to be
				// created, then we should
				// notify the history that the current operation changed if its
				// validity has changed.
				if (wasValid != fCurrent.isValid())
					fHistory.operationChanged(op);
			} else {
				// if the change created a new fCurrent that we did not yet add
				// to the
				// stack, do so if it's valid and we are not in the middle of a
				// compound change.
				if (fCurrent != fLastAddedTextEdit && fCurrent.isValid()) {
					addToOperationHistory(fCurrent);
				}
			}
		}
	}

	/*
	 * @see IOperationHistoryListener
	 */
	private class HistoryListener implements IOperationHistoryListener {

		private IUndoableOperation fOperation;

		@Override
		public void historyNotification(final OperationHistoryEvent event) {
			final int type= event.getEventType();
			switch (type) {
			case OperationHistoryEvent.ABOUT_TO_UNDO:
			case OperationHistoryEvent.ABOUT_TO_REDO:
				// if this is one of our operations
				if (event.getOperation().hasContext(fUndoContext)) {
					// if we are undoing/redoing an operation we generated, then
					// ignore
					// the document changes associated with this undo or redo.
					if (event.getOperation() instanceof UndoableTextChange) {
						listenToTextChanges(false);

						// in the undo case only, make sure compounds are closed
						if (type == OperationHistoryEvent.ABOUT_TO_UNDO) {
							if (fFoldingIntoCompoundChange) {
								endCompoundChange();
							}
						}
					} else {
						// the undo or redo has our context, but it is not one
						// of our edits. We will listen to the changes, but will
						// reset the state that tracks the undo/redo history.
						commit();
						fLastAddedTextEdit= null;
					}
					fOperation= event.getOperation();
				}
				break;
			case OperationHistoryEvent.UNDONE:
			case OperationHistoryEvent.REDONE:
			case OperationHistoryEvent.OPERATION_NOT_OK:
				if (event.getOperation() == fOperation) {
					listenToTextChanges(true);
					fOperation= null;
				}
				break;
			}
		}

	}


	/**
	 * The undo context for this document undo manager.
	 */
	private ObjectUndoContext fUndoContext;

	/**
	 * The document whose changes are being tracked.
	 */
	private IDocument fDocument;

	/**
	 * The currently constructed edit.
	 */
	private UndoableTextChange fCurrent;

	/**
	 * The internal document listener.
	 */
	private DocumentListener fDocumentListener;

	/**
	 * Indicates whether the current change belongs to a compound change.
	 */
	private boolean fFoldingIntoCompoundChange= false;

	/**
	 * The operation history being used to store the undo history.
	 */
	private IOperationHistory fHistory;

	/**
	 * The operation history listener used for managing undo and redo before and
	 * after the individual edits are performed.
	 */
	private IOperationHistoryListener fHistoryListener;

	/**
	 * The text edit last added to the operation history. This must be tracked
	 * internally instead of asking the history, since outside parties may be
	 * placing items on our undo/redo history.
	 */
	private UndoableTextChange fLastAddedTextEdit= null;

	/**
	 * The document modification stamp for redo.
	 */
	private long fPreservedRedoModificationStamp= IDocumentExtension4.UNKNOWN_MODIFICATION_STAMP;

	/**
	 * Text buffer to collect viewer content which has been replaced
	 */
	private StringBuffer fPreservedTextBuffer;

	/**
	 * The document modification stamp for undo.
	 */
	private long fPreservedUndoModificationStamp= IDocumentExtension4.UNKNOWN_MODIFICATION_STAMP;

	/**
	 * The last delete text edit.
	 */
	private UndoableTextChange fPreviousDelete;

	/**
	 * Text buffer to collect text which is inserted into the viewer
	 */
	private StringBuffer fTextBuffer;

	/** Indicates inserting state. */
	private boolean fInserting= false;

	/** Indicates overwriting state. */
	private boolean fOverwriting= false;

	/** The registered document listeners. */
	private ListenerList fDocumentUndoListeners;

	/** The list of clients connected. */
	private List<Object> fConnected;

	/**
	 *
	 * Create a DocumentUndoManager for the given document.
	 *
	 * @param document the document whose undo history is being managed.
	 */
	public DocumentUndoManager(IDocument document) {
		super();
		Assert.isNotNull(document);
		fDocument= document;
		fHistory= OperationHistoryFactory.getOperationHistory();
		fUndoContext= new ObjectUndoContext(fDocument);
		fConnected= new ArrayList<>();
		fDocumentUndoListeners= new ListenerList(ListenerList.IDENTITY);
	}

	@Override
	public void addDocumentUndoListener(IDocumentUndoListener listener) {
		fDocumentUndoListeners.add(listener);
	}

	@Override
	public void removeDocumentUndoListener(IDocumentUndoListener listener) {
		fDocumentUndoListeners.remove(listener);
	}

	@Override
	public IUndoContext getUndoContext() {
		return fUndoContext;
	}

	@Override
	public void commit() {
		// if fCurrent has never been placed on the history, do so now.
		// this can happen when there are multiple programmatically commits in a
		// single document change.
		if (fLastAddedTextEdit != fCurrent) {
			fCurrent.pretendCommit();
			if (fCurrent.isValid())
				addToOperationHistory(fCurrent);
		}
		fCurrent.commit();
	}

	@Override
	public void reset() {
		if (isConnected()) {
			shutdown();
			initialize();
		}
	}

	@Override
	public boolean redoable() {
		return OperationHistoryFactory.getOperationHistory().canRedo(fUndoContext);
	}

	@Override
	public boolean undoable() {
		return OperationHistoryFactory.getOperationHistory().canUndo(fUndoContext);
	}

	/*
	 * @see org.eclipse.text.undo.IDocumentUndoManager#undo()
	 */
	@Override
	public void redo() throws ExecutionException {
		if (isConnected() && redoable())
			OperationHistoryFactory.getOperationHistory().redo(getUndoContext(), null, null);
	}

	@Override
	public void undo() throws ExecutionException {
		if (undoable())
			OperationHistoryFactory.getOperationHistory().undo(fUndoContext, null, null);
	}

	@Override
	public void connect(Object client) {
		if (!isConnected()) {
			initialize();
		}
		if (!fConnected.contains(client))
			fConnected.add(client);
	}

	@Override
	public void disconnect(Object client) {
		fConnected.remove(client);
		if (!isConnected()) {
			shutdown();
		}
	}

	@Override
	public void beginCompoundChange() {
		if (isConnected()) {
			fFoldingIntoCompoundChange= true;
			commit();
		}
	}

	@Override
	public void endCompoundChange() {
		if (isConnected()) {
			fFoldingIntoCompoundChange= false;
			commit();
		}
	}

	/*
	 * @see org.eclipse.jface.text.IDocumentUndoManager#setUndoLimit(int)
	 */
	@Override
	public void setMaximalUndoLevel(int undoLimit) {
		fHistory.setLimit(fUndoContext, undoLimit);
	}

	/**
	 * Fires a document undo event to all registered document undo listeners.
	 * Uses a robust iterator.
	 *
	 * @param offset the document offset
	 * @param text the text that was inserted
	 * @param preservedText the text being replaced
	 * @param source the source which triggered the event
	 * @param eventType the type of event causing the change
	 * @param isCompound a flag indicating whether the change is a compound change
	 * @see IDocumentUndoListener
	 */
	void fireDocumentUndo(int offset, String text, String preservedText, Object source, int eventType, boolean isCompound) {
		eventType= isCompound ? eventType | DocumentUndoEvent.COMPOUND : eventType;
		DocumentUndoEvent event= new DocumentUndoEvent(fDocument, offset, text, preservedText, eventType, source);
		Object[] listeners= fDocumentUndoListeners.getListeners();
		for (int i= 0; i < listeners.length; i++) {
			((IDocumentUndoListener)listeners[i]).documentUndoNotification(event);
		}
	}

	/**
	 * Adds any listeners needed to track the document and the operations
	 * history.
	 */
	private void addListeners() {
		fHistoryListener= new HistoryListener();
		fHistory.addOperationHistoryListener(fHistoryListener);
		listenToTextChanges(true);
	}

	/**
	 * Removes any listeners that were installed by the document.
	 */
	private void removeListeners() {
		listenToTextChanges(false);
		fHistory.removeOperationHistoryListener(fHistoryListener);
		fHistoryListener= null;
	}

	/**
	 * Adds the given text edit to the operation history if it is not part of a compound change.
	 *
	 * @param edit the edit to be added
	 */
	private void addToOperationHistory(UndoableTextChange edit) {
		if (!fFoldingIntoCompoundChange
				|| edit instanceof UndoableCompoundTextChange) {
			fHistory.add(edit);
			fLastAddedTextEdit= edit;
		}
	}

	/**
	 * Disposes the undo history.
	 */
	private void disposeUndoHistory() {
		fHistory.dispose(fUndoContext, true, true, true);
	}

	/**
	 * Initializes the undo history.
	 */
	private void initializeUndoHistory() {
		if (fHistory != null && fUndoContext != null)
			fHistory.dispose(fUndoContext, true, true, false);

	}

	/**
	 * Checks whether the given text starts with a line delimiter and
	 * subsequently contains a white space only.
	 *
	 * @param text the text to check
	 * @return <code>true</code> if the text is a line delimiter followed by
	 *         whitespace, <code>false</code> otherwise
	 */
	private boolean isWhitespaceText(String text) {

		if (text == null || text.length() == 0)
			return false;

		String[] delimiters= fDocument.getLegalLineDelimiters();
		int index= TextUtilities.startsWith(delimiters, text);
		if (index > -1) {
			char c;
			int length= text.length();
			for (int i= delimiters[index].length(); i < length; i++) {
				c= text.charAt(i);
				if (c != ' ' && c != '\t')
					return false;
			}
			return true;
		}

		return false;
	}

	/**
	 * Switches the state of whether there is a text listener or not.
	 *
	 * @param listen the state which should be established
	 */
	private void listenToTextChanges(boolean listen) {
		if (listen) {
			if (fDocumentListener == null && fDocument != null) {
				fDocumentListener= new DocumentListener();
				fDocument.addDocumentListener(fDocumentListener);
			}
		} else if (!listen) {
			if (fDocumentListener != null && fDocument != null) {
				fDocument.removeDocumentListener(fDocumentListener);
				fDocumentListener= null;
			}
		}
	}

	private void processChange(int modelStart, int modelEnd,
			String insertedText, String replacedText,
			final long beforeChangeModificationStamp,
			final long afterChangeModificationStamp) {

		if (insertedText == null)
			insertedText= ""; //$NON-NLS-1$

		if (replacedText == null)
			replacedText= ""; //$NON-NLS-1$

		int length= insertedText.length();
		int diff= modelEnd - modelStart;

		if (fCurrent.fUndoModificationStamp == IDocumentExtension4.UNKNOWN_MODIFICATION_STAMP)
			fCurrent.fUndoModificationStamp= beforeChangeModificationStamp;

		// normalize
		if (diff < 0) {
			int tmp= modelEnd;
			modelEnd= modelStart;
			modelStart= tmp;
		}

		if (modelStart == modelEnd) {
			// text will be inserted
			if ((length == 1) || isWhitespaceText(insertedText)) {
				// by typing or whitespace
				if (!fInserting
						|| (modelStart != fCurrent.fStart
								+ fTextBuffer.length())) {
					fCurrent.fRedoModificationStamp= beforeChangeModificationStamp;
					if (fCurrent.attemptCommit())
						fCurrent.fUndoModificationStamp= beforeChangeModificationStamp;

					fInserting= true;
				}
				if (fCurrent.fStart < 0)
					fCurrent.fStart= fCurrent.fEnd= modelStart;
				if (length > 0)
					fTextBuffer.append(insertedText);
			} else if (length > 0) {
				// by pasting or model manipulation
				fCurrent.fRedoModificationStamp= beforeChangeModificationStamp;
				if (fCurrent.attemptCommit())
					fCurrent.fUndoModificationStamp= beforeChangeModificationStamp;

				fCurrent.fStart= fCurrent.fEnd= modelStart;
				fTextBuffer.append(insertedText);
				fCurrent.fRedoModificationStamp= afterChangeModificationStamp;
				if (fCurrent.attemptCommit())
					fCurrent.fUndoModificationStamp= afterChangeModificationStamp;

			}
		} else {
			if (length == 0) {
				// text will be deleted by backspace or DEL key or empty
				// clipboard
				length= replacedText.length();
				String[] delimiters= fDocument.getLegalLineDelimiters();

				if ((length == 1)
						|| TextUtilities.equals(delimiters, replacedText) > -1) {

					// whereby selection is empty

					if (fPreviousDelete.fStart == modelStart
							&& fPreviousDelete.fEnd == modelEnd) {
						// repeated DEL

						// correct wrong settings of fCurrent
						if (fCurrent.fStart == modelEnd
								&& fCurrent.fEnd == modelStart) {
							fCurrent.fStart= modelStart;
							fCurrent.fEnd= modelEnd;
						}
						// append to buffer && extend edit range
						fPreservedTextBuffer.append(replacedText);
						++fCurrent.fEnd;

					} else if (fPreviousDelete.fStart == modelEnd) {
						// repeated backspace

						// insert in buffer and extend edit range
						fPreservedTextBuffer.insert(0, replacedText);
						fCurrent.fStart= modelStart;

					} else {
						// either DEL or backspace for the first time

						fCurrent.fRedoModificationStamp= beforeChangeModificationStamp;
						if (fCurrent.attemptCommit())
							fCurrent.fUndoModificationStamp= beforeChangeModificationStamp;

						// as we can not decide whether it was DEL or backspace
						// we initialize for backspace
						fPreservedTextBuffer.append(replacedText);
						fCurrent.fStart= modelStart;
						fCurrent.fEnd= modelEnd;
					}

					fPreviousDelete.set(modelStart, modelEnd);

				} else if (length > 0) {
					// whereby selection is not empty
					fCurrent.fRedoModificationStamp= beforeChangeModificationStamp;
					if (fCurrent.attemptCommit())
						fCurrent.fUndoModificationStamp= beforeChangeModificationStamp;

					fCurrent.fStart= modelStart;
					fCurrent.fEnd= modelEnd;
					fPreservedTextBuffer.append(replacedText);
				}
			} else {
				// text will be replaced

				if (length == 1) {
					length= replacedText.length();
					String[] delimiters= fDocument.getLegalLineDelimiters();

					if ((length == 1)
							|| TextUtilities.equals(delimiters, replacedText) > -1) {
						// because of overwrite mode or model manipulation
						if (!fOverwriting
								|| (modelStart != fCurrent.fStart
										+ fTextBuffer.length())) {
							fCurrent.fRedoModificationStamp= beforeChangeModificationStamp;
							if (fCurrent.attemptCommit())
								fCurrent.fUndoModificationStamp= beforeChangeModificationStamp;

							fOverwriting= true;
						}

						if (fCurrent.fStart < 0)
							fCurrent.fStart= modelStart;

						fCurrent.fEnd= modelEnd;
						fTextBuffer.append(insertedText);
						fPreservedTextBuffer.append(replacedText);
						fCurrent.fRedoModificationStamp= afterChangeModificationStamp;
						return;
					}
				}
				// because of typing or pasting whereby selection is not empty
				fCurrent.fRedoModificationStamp= beforeChangeModificationStamp;
				if (fCurrent.attemptCommit())
					fCurrent.fUndoModificationStamp= beforeChangeModificationStamp;

				fCurrent.fStart= modelStart;
				fCurrent.fEnd= modelEnd;
				fTextBuffer.append(insertedText);
				fPreservedTextBuffer.append(replacedText);
			}
		}
		// in all cases, the redo modification stamp is updated on the open
		// text edit
		fCurrent.fRedoModificationStamp= afterChangeModificationStamp;
	}

	/**
	 * Initialize the receiver.
	 */
	private void initialize() {
		initializeUndoHistory();

		// open up the current text edit
		fCurrent= new UndoableTextChange(this);
		fPreviousDelete= new UndoableTextChange(this);
		fTextBuffer= new StringBuffer();
		fPreservedTextBuffer= new StringBuffer();

		addListeners();
	}

	/**
	 * Reset processChange state.
	 *
	 * @since 3.2
	 */
	private void resetProcessChangeState() {
		fInserting= false;
		fOverwriting= false;
		fPreviousDelete.reinitialize();
	}

	/**
	 * Shutdown the receiver.
	 */
	private void shutdown() {
		removeListeners();

		fCurrent= null;
		fPreviousDelete= null;
		fTextBuffer= null;
		fPreservedTextBuffer= null;

		disposeUndoHistory();
	}

	/**
	 * Return whether or not any clients are connected to the receiver.
	 *
	 * @return <code>true</code> if the receiver is connected to
	 * 			clients, <code>false</code> if it is not
	 */
	boolean isConnected() {
		if (fConnected == null)
			return false;
		return !fConnected.isEmpty();
	}

	@Override
	public void transferUndoHistory(IDocumentUndoManager manager) {
		IUndoContext oldUndoContext= manager.getUndoContext();
		// Get the history for the old undo context.
		IUndoableOperation [] operations= OperationHistoryFactory.getOperationHistory().getUndoHistory(oldUndoContext);
		for (int i= 0; i < operations.length; i++) {
			// First replace the undo context
			IUndoableOperation op= operations[i];
			if (op instanceof IContextReplacingOperation) {
				((IContextReplacingOperation)op).replaceContext(oldUndoContext, getUndoContext());
			} else {
				op.addContext(getUndoContext());
				op.removeContext(oldUndoContext);
			}
			// Now update the manager that owns the text edit.
			if (op instanceof UndoableTextChange) {
				((UndoableTextChange)op).fDocumentUndoManager= this;
			}
		}

		IUndoableOperation op= OperationHistoryFactory.getOperationHistory().getUndoOperation(getUndoContext());
		if (op != null && !(op instanceof UndoableTextChange))
			return;

		// Record the transfer itself as an undoable change.
		// If the transfer results from some open operation, recording this change will
		// cause our undo context to be added to the outer operation.  If there is no
		// outer operation, there will be a local change to signify the transfer.
		// This also serves to synchronize the modification stamps with the documents.
		UndoableTextChange cmd= new UndoableTextChange(this);
		cmd.fStart= cmd.fEnd= 0;
		cmd.fText= cmd.fPreservedText= ""; //$NON-NLS-1$
		if (fDocument instanceof IDocumentExtension4) {
			cmd.fRedoModificationStamp= ((IDocumentExtension4)fDocument).getModificationStamp();
			if (op != null)
				cmd.fUndoModificationStamp= ((UndoableTextChange)op).fRedoModificationStamp;
		}
		addToOperationHistory(cmd);
	}


}
