/*******************************************************************************
 * Copyright (c) 2001, 2004 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
 *     Jens Lukowski/Innoopract - initial renaming/restructuring
 *     
 *******************************************************************************/
package org.eclipse.wst.sse.core.internal.undo;

import java.util.EventObject;

import org.eclipse.emf.common.command.BasicCommandStack;
import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.common.command.CommandStack;
import org.eclipse.emf.common.command.CommandStackListener;
import org.eclipse.jface.text.IDocument;
import org.eclipse.wst.sse.core.internal.SSECoreMessages;
import org.eclipse.wst.sse.core.internal.provisional.IModelManager;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.eclipse.wst.sse.core.internal.provisional.StructuredModelManager;
import org.eclipse.wst.sse.core.internal.provisional.events.IStructuredDocumentListener;
import org.eclipse.wst.sse.core.internal.provisional.events.NewDocumentEvent;
import org.eclipse.wst.sse.core.internal.provisional.events.NoChangeEvent;
import org.eclipse.wst.sse.core.internal.provisional.events.RegionChangedEvent;
import org.eclipse.wst.sse.core.internal.provisional.events.RegionsReplacedEvent;
import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentEvent;
import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentRegionsReplacedEvent;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
import org.eclipse.wst.sse.core.internal.util.Assert;
import org.eclipse.wst.sse.core.internal.util.Utilities;

public class StructuredTextUndoManager implements IStructuredTextUndoManager {

	class InternalCommandStackListener implements CommandStackListener {
		public void commandStackChanged(EventObject event) {
			resetInternalCommands();
		}
	}

	class InternalStructuredDocumentListener implements IStructuredDocumentListener {

		public void newModel(NewDocumentEvent structuredDocumentEvent) {
			// Do nothing. Do not push the new model's structuredDocument
			// changes
			// onto the undo command stack, or else the user may be able to
			// undo
			// an existing file to an empty file.
		}

		public void noChange(NoChangeEvent structuredDocumentEvent) {
			// Since "no change", do nothing.
		}

		public void nodesReplaced(StructuredDocumentRegionsReplacedEvent structuredDocumentEvent) {
			processStructuredDocumentEvent(structuredDocumentEvent);
		}

		private void processStructuredDocumentEvent(String textDeleted, String textInserted, int textStart, int textEnd) {
			if (fTextCommand != null && textStart == fTextCommand.getTextEnd()) {
				// append to the text command
				fTextCommand.setTextDeleted(fTextCommand.getTextDeleted().concat(textDeleted));
				fTextCommand.setTextInserted(fTextCommand.getTextInserted().concat(textInserted));
				fTextCommand.setTextEnd(textEnd);
			}
			else if (fTextCommand != null && textStart == fTextCommand.getTextStart() - (textEnd - textStart + 1) && textEnd <= fTextCommand.getTextEnd() - (textEnd - textStart + 1) && textDeleted.length() == 1 && textInserted.length() == 0) {
				// backspace pressed

				// erase a character just inserted
				if (fTextCommand.getTextInserted().length() > 0) {
					fTextCommand.setTextInserted(fTextCommand.getTextInserted().substring(0, fTextCommand.getTextEnd() - fTextCommand.getTextStart() - 1));
					fTextCommand.setTextEnd(textEnd);
				}
				// erase a character in the file
				else {
					fTextCommand.setTextDeleted(textDeleted.concat(fTextCommand.getTextDeleted()));
					fTextCommand.setTextStart(textStart);
				}
			}
			else {
				createNewTextCommand(textDeleted, textInserted, textStart, textEnd);
			}

			// save cursor position
			fCursorPosition = textEnd;
		}

		private void processStructuredDocumentEvent(StructuredDocumentEvent structuredDocumentEvent) {
			// Note: fListening tells us if we should listen to the
			// StructuredDocumentEvent.
			// fListening is set to false right before the undo/redo process
			// and
			// then set to true again
			// right after the undo/redo process to block out and ignore all
			// StructuredDocumentEvents generated
			// by the undo/redo process.

			// Process StructuredDocumentEvent if fListening is true.
			//
			// We are executing a command from the command stack if the
			// requester
			// is a command (for example, undo/redo).
			// We should not process the flat model event when we are
			// executing a
			// command from the command stack.
			if (fUndoManagementEnabled && !(structuredDocumentEvent.getOriginalRequester() instanceof Command)) {
				// check requester if not recording
				if (!fRecording)
					checkRequester(structuredDocumentEvent.getOriginalRequester());

				// process the structuredDocumentEvent
				String textDeleted = structuredDocumentEvent.getDeletedText();
				String textInserted = structuredDocumentEvent.getText();
				int textStart = structuredDocumentEvent.getOffset();
				int textEnd = textStart + textInserted.length();
				processStructuredDocumentEvent(textDeleted, textInserted, textStart, textEnd);
			}
		}

		public void regionChanged(RegionChangedEvent structuredDocumentEvent) {
			processStructuredDocumentEvent(structuredDocumentEvent);
		}

		public void regionsReplaced(RegionsReplacedEvent structuredDocumentEvent) {
			processStructuredDocumentEvent(structuredDocumentEvent);
		}

	}

	private static final String TEXT_CHANGE_TEXT = SSECoreMessages.Text_Change_UI_; //$NON-NLS-1$
	private CommandStack fCommandStack = null;
	private StructuredTextCompoundCommandImpl fCompoundCommand = null;
	private String fCompoundCommandDescription = null;
	private String fCompoundCommandLabel = null;
	int fCursorPosition = 0;
	// private IStructuredModel fStructuredModel = null;
	private IDocument fDocument;
	private InternalCommandStackListener fInternalCommandStackListener;
	// private Map fTextViewerToListenerMap = new HashMap();
	private IStructuredDocumentListener fInternalStructuredDocumentListener;
	private IDocumentSelectionMediator[] fMediators = null;
	private boolean fRecording = false;
	private int fRecordingCount = 0;
	private Object fRequester;
	StructuredTextCommandImpl fTextCommand = null;
	private int fUndoCursorPosition = -1;
	boolean fUndoManagementEnabled = true;
	private int fUndoSelectionLength = 0;

	public StructuredTextUndoManager() {
		this(new BasicCommandStack());
	}

	public StructuredTextUndoManager(CommandStack commandStack) {
		setCommandStack(commandStack);
	}

	private void addDocumentSelectionMediator(IDocumentSelectionMediator mediator) {
		if (!Utilities.contains(fMediators, mediator)) {
			int oldSize = 0;

			if (fMediators != null) {
				// normally won't be null, but we need to be sure, for first
				// time through
				oldSize = fMediators.length;
			}

			int newSize = oldSize + 1;
			IDocumentSelectionMediator[] newMediators = new IDocumentSelectionMediator[newSize];
			if (fMediators != null) {
				System.arraycopy(fMediators, 0, newMediators, 0, oldSize);
			}

			// add the new undo mediator to last position
			newMediators[newSize - 1] = mediator;

			// now switch new for old
			fMediators = newMediators;
		}
		else {
			removeDocumentSelectionMediator(mediator);
			addDocumentSelectionMediator(mediator);
		}
	}

	public void beginRecording(Object requester) {
		beginRecording(requester, null, null);
	}

	public void beginRecording(Object requester, int cursorPosition, int selectionLength) {
		beginRecording(requester, null, null);

		fUndoCursorPosition = cursorPosition;
		fUndoSelectionLength = selectionLength;
	}

	public void beginRecording(Object requester, String label) {
		beginRecording(requester, label, null);
	}

	public void beginRecording(Object requester, String label, int cursorPosition, int selectionLength) {
		beginRecording(requester, label, null);

		fUndoCursorPosition = cursorPosition;
		fUndoSelectionLength = selectionLength;
	}

	public void beginRecording(Object requester, String label, String description) {
		// save the requester
		fRequester = requester;

		// update label and desc only on the first level when recording is
		// nested
		if (fRecordingCount == 0) {
			fCompoundCommandLabel = label;
			if (fCompoundCommandLabel == null)
				fCompoundCommandLabel = TEXT_CHANGE_TEXT;

			fCompoundCommandDescription = description;
			if (fCompoundCommandDescription == null)
				fCompoundCommandDescription = TEXT_CHANGE_TEXT;

			// clear commands
			fTextCommand = null;
			fCompoundCommand = null;
		}

		// update counter and flag
		fRecordingCount++;
		fRecording = true;

		// no undo cursor position and undo selection length specified
		// reset undo cursor position and undo selection length
		fUndoCursorPosition = -1;
		fUndoSelectionLength = 0;
	}

	public void beginRecording(Object requester, String label, String description, int cursorPosition, int selectionLength) {
		beginRecording(requester, label, description);

		fUndoCursorPosition = cursorPosition;
		fUndoSelectionLength = selectionLength;
	}

	void checkRequester(Object requester) {
		if (fRequester != null && !fRequester.equals(requester)) {
			// Force restart of recording so the last compound command is
			// closed.
			//
			// However, we should not force restart of recording when the
			// request came from StructuredDocumentToTextAdapter or
			// XMLModelImpl
			// because cut/paste requests and character inserts to the
			// textViewer are from StructuredDocumentToTextAdapter,
			// and requests to delete a node in the XMLTableTreeViewer are
			// from XMLModelImpl (which implements IStructuredModel).

			if (!(requester instanceof IStructuredModel || requester instanceof IStructuredDocument)) {
				resetInternalCommands();
			}
		}
	}



	public void connect(IDocumentSelectionMediator mediator) {
		Assert.isNotNull(mediator);
		if (fDocument == null) {
			// add this undo manager as structured document listener
			fDocument = mediator.getDocument();
			// future_TODO: eventually we want to refactor or allow either
			// type of document, but for now, we'll do instanceof check, and
			// fail
			// if not right type
			if (fDocument instanceof IStructuredDocument) {
				((IStructuredDocument) fDocument).addDocumentChangedListener(getInternalStructuredDocumentListener());
			}
			else {
				throw new IllegalArgumentException("only meditator with structured documents currently handled"); //$NON-NLS-1$
			}
		}
		else {
			// if we've already had our document set, we'll just do this fail
			// fast integrity check
			if (!fDocument.equals(mediator.getDocument()))
				throw new IllegalStateException("Connection to undo manager failed. Document for document selection mediator inconistent with undo manager."); //$NON-NLS-1$
		}

		addDocumentSelectionMediator(mediator);
	}

	void createNewTextCommand(String textDeleted, String textInserted, int textStart, int textEnd) {
		StructuredTextCommandImpl textCommand = new StructuredTextCommandImpl(fDocument);
		textCommand.setLabel(TEXT_CHANGE_TEXT);
		textCommand.setDescription(TEXT_CHANGE_TEXT);
		textCommand.setTextStart(textStart);
		textCommand.setTextEnd(textEnd);
		textCommand.setTextDeleted(textDeleted);
		textCommand.setTextInserted(textInserted);

		if (fRecording) {
			if (fCompoundCommand == null) {
				StructuredTextCompoundCommandImpl compoundCommand = new StructuredTextCompoundCommandImpl();
				compoundCommand.setUndoCursorPosition(fUndoCursorPosition);
				compoundCommand.setUndoSelectionLength(fUndoSelectionLength);

				compoundCommand.setLabel(fCompoundCommandLabel);
				compoundCommand.setDescription(fCompoundCommandDescription);
				compoundCommand.append(textCommand);
				fCommandStack.execute(compoundCommand);

				fCompoundCommand = compoundCommand;
			}
			else {
				fCompoundCommand.append(textCommand);
			}
		}
		else {
			fCommandStack.execute(textCommand);
		}

		fTextCommand = textCommand;
	}

	/**
	 * Disable undo management.
	 */
	public void disableUndoManagement() {
		fUndoManagementEnabled = false;
	}

	public void disconnect(IDocumentSelectionMediator mediator) {
		removeDocumentSelectionMediator(mediator);

		if (fMediators != null && fMediators.length == 0 && fDocument != null) {
			// remove this undo manager as structured document listener
			// future_TODO: eventually we want to refactor or allow either
			// type of document, but for now, we'll do instanceof check, and
			// fail
			// if not right type
			if (fDocument instanceof IStructuredDocument) {
				((IStructuredDocument) fDocument).removeDocumentChangedListener(getInternalStructuredDocumentListener());
			}
			else {
				throw new IllegalArgumentException("only meditator with structured documents currently handled"); //$NON-NLS-1$
			}
			// if no longer listening to document, then dont even track it
			// anymore
			// (this allows connect to reconnect to document again)
			fDocument = null;
		}
	}

	public void enableUndoManagement() {
		fUndoManagementEnabled = true;
	}

	public void endRecording(Object requester) {
		int cursorPosition = (fTextCommand != null) ? fTextCommand.getTextEnd() : -1;
		int selectionLength = 0;

		endRecording(requester, cursorPosition, selectionLength);
	}

	public void endRecording(Object requester, int cursorPosition, int selectionLength) {
		// Recording could be stopped by forceEndOfPendingCommand(). Make sure
		// we are still recording before proceeding, or else fRecordingCount
		// may not be balanced.
		if (fRecording) {
			if (fCompoundCommand != null) {
				fCompoundCommand.setRedoCursorPosition(cursorPosition);
				fCompoundCommand.setRedoSelectionLength(selectionLength);
			}

			// end recording is a logical stopping point for text command,
			// even when fRecordingCount > 0 (in nested beginRecording)
			fTextCommand = null;

			// update counter and flag
			if (fRecordingCount > 0)
				fRecordingCount--;
			if (fRecordingCount == 0) {
				fRecording = false;

				// reset compound command only when fRecordingCount ==
				// 0
				fCompoundCommand = null;
				fCompoundCommandLabel = null;
				fCompoundCommandDescription = null;

				// Also reset fRequester
				fRequester = null;
			}
		}
	}

	/**
	 * Utility method to find model given document
	 */
	private IStructuredModel findStructuredModel(IDocument document) {
		IModelManager modelManager = StructuredModelManager.getModelManager();
		IStructuredModel structuredModel = modelManager.getExistingModelForRead(document);
		return structuredModel;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.wst.sse.core.undo.IStructuredTextUndoManager#forceEndOfPendingCommand(java.lang.Object,
	 *      int, int)
	 */
	public void forceEndOfPendingCommand(Object requester, int currentPosition, int length) {
		if (fRecording)
			endRecording(requester, currentPosition, length);
		else
			resetInternalCommands();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.wst.sse.core.undo.IStructuredTextUndoManager#getCommandStack()
	 */
	public CommandStack getCommandStack() {
		return fCommandStack;
	}

	/**
	 * @return
	 */
	private CommandStackListener getInternalCommandStackListener() {
		if (fInternalCommandStackListener == null) {
			fInternalCommandStackListener = new InternalCommandStackListener();
		}
		return fInternalCommandStackListener;
	}

	/**
	 * @return
	 */
	private IStructuredDocumentListener getInternalStructuredDocumentListener() {
		if (fInternalStructuredDocumentListener == null) {
			fInternalStructuredDocumentListener = new InternalStructuredDocumentListener();
		}
		return fInternalStructuredDocumentListener;
	}

	public Command getRedoCommand() {
		return fCommandStack.getRedoCommand();
	}

	public Command getUndoCommand() {
		return fCommandStack.getUndoCommand();
	}

	public void redo() {
		redo(null);
	}

	public void redo(IDocumentSelectionMediator requester) {
		IStructuredModel model = findStructuredModel(fDocument);
		if (redoable()) {
			try {
				if (model != null)
					model.aboutToChangeModel();

				Command redoCommand = getRedoCommand();

				// make sure to redo before setting document selection
				fCommandStack.redo();

				// set document selection
				setRedoDocumentSelection(requester, redoCommand);
			}
			finally {
				if (model != null) {
					model.changedModel();
					model.releaseFromRead();
				}
			}
		}
	}

	public boolean redoable() {
		return fCommandStack.canRedo();
	}

	private void removeDocumentSelectionMediator(IDocumentSelectionMediator mediator) {
		if (fMediators != null && mediator != null) {
			// if its not in the array, we'll ignore the request
			if (Utilities.contains(fMediators, mediator)) {
				int oldSize = fMediators.length;
				int newSize = oldSize - 1;
				IDocumentSelectionMediator[] newMediators = new IDocumentSelectionMediator[newSize];
				int index = 0;
				for (int i = 0; i < oldSize; i++) {
					if (fMediators[i] == mediator) { // ignore
					}
					else {
						// copy old to new if its not the one we are removing
						newMediators[index++] = fMediators[i];
					}
				}
				// now that we have a new array, let's switch it for the old
				// one
				fMediators = newMediators;
			}
		}
	}

	void resetInternalCommands() {
		// Either the requester of the structured document change event is
		// changed, or the command stack is changed. Need to reset internal
		// commands so we won't continue to append changes.
		fCompoundCommand = null;
		fTextCommand = null;

		// Also reset fRequester
		fRequester = null;
	}

	public void setCommandStack(CommandStack commandStack) {
		if (fCommandStack != null)
			fCommandStack.removeCommandStackListener(getInternalCommandStackListener());

		fCommandStack = commandStack;

		if (fCommandStack != null)
			fCommandStack.addCommandStackListener(getInternalCommandStackListener());
	}

	private void setRedoDocumentSelection(IDocumentSelectionMediator requester, Command command) {
		int cursorPosition = -1;
		int selectionLength = 0;

		if (command instanceof CommandCursorPosition) {
			CommandCursorPosition commandCursorPosition = (CommandCursorPosition) command;
			cursorPosition = commandCursorPosition.getRedoCursorPosition();
			selectionLength = commandCursorPosition.getRedoSelectionLength();
		}
		else if (command instanceof StructuredTextCommand) {
			StructuredTextCommand structuredTextCommand = (StructuredTextCommand) command;
			cursorPosition = structuredTextCommand.getTextStart();
			selectionLength = structuredTextCommand.getTextInserted().length();
		}

		if (cursorPosition > -1 && fMediators != null && fMediators.length > 0) {
			for (int i = 0; i < fMediators.length; i++) {
				IDocument document = fMediators[i].getDocument();
				fMediators[i].undoOperationSelectionChanged(new UndoDocumentEvent(requester, document, cursorPosition, selectionLength));
			}
		}
	}

	private void setUndoDocumentSelection(IDocumentSelectionMediator requester, Command command) {
		int cursorPosition = -1;
		int selectionLength = 0;

		if (command instanceof CommandCursorPosition) {
			CommandCursorPosition commandCursorPosition = (CommandCursorPosition) command;
			cursorPosition = commandCursorPosition.getUndoCursorPosition();
			selectionLength = commandCursorPosition.getUndoSelectionLength();
		}
		else if (command instanceof StructuredTextCommand) {
			StructuredTextCommand structuredTextCommand = (StructuredTextCommand) command;
			cursorPosition = structuredTextCommand.getTextStart();
			selectionLength = structuredTextCommand.getTextDeleted().length();
		}

		if (cursorPosition > -1 && fMediators != null && fMediators.length > 0) {
			for (int i = 0; i < fMediators.length; i++) {
				IDocument document = fMediators[i].getDocument();
				fMediators[i].undoOperationSelectionChanged(new UndoDocumentEvent(requester, document, cursorPosition, selectionLength));
			}
		}
	}

	public void undo() {
		undo(null);
	}

	public void undo(IDocumentSelectionMediator requester) {
		// Force an endRecording before undo.
		//
		// For example, recording was turned on on the Design Page of
		// PageDesigner.
		// Then undo is invoked on the Source Page. Recording should be
		// stopped before we undo.
		// Note that redo should not be available when we switch to the Source
		// Page.
		// Therefore, this force ending of recording is not needed in redo.
		if (fRecording)
			endRecording(this);

		if (undoable()) {
			IStructuredModel model = findStructuredModel(fDocument);
			try {
				if (model != null)
					model.aboutToChangeModel();

				Command undoCommand = getUndoCommand();

				// make sure to undo before setting document selection
				fCommandStack.undo();

				// set document selection
				setUndoDocumentSelection(requester, undoCommand);
			}
			finally {
				if (model != null) {
					model.changedModel();
					model.releaseFromRead();
				}
			}
		}
	}

	public boolean undoable() {
		return fCommandStack.canUndo();
	}
}
