package org.eclipse.cdt.internal.corext.textmanipulation;

/*
 * (c) Copyright IBM Corp. 2000, 2001.
 * All Rights Reserved.
 */
 
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;

import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.IDocumentListener;
import org.eclipse.jface.util.Assert;


/**
 * A helper class to arrange <code>TextEdit</code>s into a tree to optimize their
 * execution.
 */
/* package */ abstract class TextEditNode {

	/* package */ TextEditNode fParent;
	/* package */ List fChildren;
	/* package */ TextEdit fEdit;
	
	/* package */ static class DefaultNode extends TextEditNode {
		public DefaultNode(TextEdit edit) {
			super(edit);
		}
	}
	
	/* package */ static class RootNode extends TextEditNode {
		private int fUndoIndex;
		public RootNode(int length) {
			super(new NopTextEdit(new TextRange(0, length)));
			fEdit.isSynthetic= true;
		}
		public boolean covers(TextEditNode node) {
			return true;
		}
		public UndoMemento performDo(TextBuffer buffer, IProgressMonitor pm) throws CoreException {
			DoRangeUpdater updater= new DoRangeUpdater();
			UndoMemento undo= new UndoMemento(TextBufferEditor.UNDO);
			try {
				buffer.registerUpdater(updater);
				performDo(buffer, updater, undo, pm);
			} finally {
				buffer.unregisterUpdater(updater);
				updater.setActiveNode(null);
			}
			return undo;
		}
		public UndoMemento performUndo(TextBuffer buffer, IProgressMonitor pm) throws CoreException {
			UndoRangeUpdater updater= new UndoRangeUpdater(this);
			UndoMemento undo= new UndoMemento(TextBufferEditor.REDO);
			try {
				buffer.registerUpdater(updater);
				performUndo(buffer, updater, undo, pm);
			} finally {
				buffer.unregisterUpdater(updater);
				updater.setActiveNode(null);
			}
			return undo;
		}
		
		protected void setUndoIndex(int index) {
			fUndoIndex= index;
		}
		
		protected int getUndoIndex() {
			return fUndoIndex;
		}
	}
	
	/* package */ abstract static class AbstractMoveNode extends TextEditNode {
		private int state;		
		
		private int fTargetIndex;
		private int fSourceIndex;
		
		private List fAffectedChildren;
		
		public AbstractMoveNode(TextEdit edit) {
			super(edit);
			reset();
		}
		protected abstract TextRange getSourceRange();
		protected abstract TextRange getTargetRange();
		protected abstract boolean isUpMove();
		protected boolean isDownMove() {
			return !isUpMove();
		}
		public boolean isMove() {
			return true;
		}
		protected void checkRange(DocumentEvent event) {
			TextRange range= getChildRange();
			int eventOffset= event.getOffset();
			int eventLength= event.getLength();
			int eventEnd = eventOffset + eventLength - 1;
			// "Edit changes text that lies outside its defined range"
			Assert.isTrue(range.fOffset <= eventOffset && eventEnd <= range.getInclusiveEnd());
		}
		protected boolean activeNodeChanged(int delta) {
			TextRange targetRange= getTargetRange();
			TextRange sourceRange= getSourceRange();
			switch (state) {
				case 0: // the move delete
					init();
					Assert.isTrue(Math.abs(delta) == sourceRange.fLength);
					if (isUpMove()) {
						updateOffset(fAffectedChildren, delta);
						targetRange.fOffset+= delta;
					}
					sourceRange.fLength= 0;
					state= 1;
					break;
				case 1:
					TextEditNode target= (TextEditNode)fParent.fChildren.get(fTargetIndex);
					TextEditNode source= (TextEditNode)fParent.fChildren.get(fSourceIndex);
					updateOffset(source.fChildren, targetRange.fOffset - sourceRange.fOffset);
					target.fChildren= source.fChildren;
					if (target.fChildren != null) {
						for (Iterator iter= target.fChildren.iterator(); iter.hasNext();) {
							((TextEditNode)iter.next()).fParent= target;
						}
					}
					source.fChildren= null;				
					if (isDownMove()) {
						updateOffset(fAffectedChildren, delta);
						sourceRange.fOffset+= delta;
					}
					targetRange.fLength= delta;
					reset();
					break;
			}
			return true;
		}
		private static void updateOffset(List nodes, int delta) {
			if (nodes == null)
				return;
			for (int i= nodes.size() - 1; i >= 0; i--) {
				TextEditNode node= (TextEditNode)nodes.get(i);
				TextRange range= node.getTextRange();
				range.fOffset+= delta;
				updateOffset(node.fChildren, delta);
			}
		}
		private void init() {
			TextRange source= getSourceRange();
			TextRange target= getTargetRange();
			List children= fParent.fChildren;
			for (int i= children.size() - 1; i >= 0; i--) {
				TextEditNode child= (TextEditNode)children.get(i);
				TextRange range= child.fEdit.getTextRange();
				if (range == source)
					fSourceIndex= i;
				else if (range == target)
					fTargetIndex= i;
			}
			int start= Math.min(fTargetIndex, fSourceIndex);
			int end= Math.max(fTargetIndex, fSourceIndex);
			fAffectedChildren= new ArrayList(3);
			for (int i= start + 1; i < end; i++) {
				fAffectedChildren.add(children.get(i));
			}
		}
		private void reset() {
			state= 0;
			fSourceIndex= -1;
			fTargetIndex= -1;
		}
	}
	
	/* package */ static class MoveNode extends AbstractMoveNode {
		public MoveNode(TextEdit edit) {
			super(edit);
		}
		protected TextRange getChildRange() {
			return ((MoveTextEdit)fEdit).getChildRange();
		}
		protected TextRange getSourceRange() {
			return ((MoveTextEdit)fEdit).getSourceRange();
		}
		protected TextRange getTargetRange() {
			return ((MoveTextEdit)fEdit).getTargetRange();
		}
		protected boolean isUpMove() {
			return ((MoveTextEdit)fEdit).isUpMove();
		}
		public boolean isMovePartner(TextEditNode other) {
			if (!(other instanceof TargetMarkNode))
				return false;
			return fEdit == ((MoveTextEdit.TargetMark)other.fEdit).getMoveTextEdit();
		}
		public boolean covers(TextEditNode node) {
			if (node instanceof TargetMarkNode) {
				MoveTextEdit.TargetMark edit= (MoveTextEdit.TargetMark)node.fEdit;
				if (edit.getMoveTextEdit() == fEdit)
					return false;
			}
			return getParentRange().covers(node.getChildRange());
		}
	}
	
	/* package */ static class TargetMarkNode extends AbstractMoveNode {
		public TargetMarkNode(TextEdit edit) {
			super(edit);
		}
		protected TextRange getChildRange() {
			return ((MoveTextEdit.TargetMark)fEdit).getMoveTextEdit().getChildRange();
		}
		protected TextRange getSourceRange() {
			return ((MoveTextEdit.TargetMark)fEdit).getMoveTextEdit().getSourceRange();
		}
		protected TextRange getTargetRange() {
			return ((MoveTextEdit.TargetMark)fEdit).getMoveTextEdit().getTargetRange();
		}
		protected boolean isUpMove() {
			return ((MoveTextEdit.TargetMark)fEdit).getMoveTextEdit().isUpMove();
		}
		public boolean isMovePartner(TextEditNode other) {
			return ((MoveTextEdit.TargetMark)fEdit).getMoveTextEdit() == other.fEdit;
		}
	}

	//---- Range updating ---------------------------------------------------------------------------

	private static abstract class RangeUpdater implements IDocumentListener {
		protected TextEditNode fActiveNode;
		public void documentAboutToBeChanged(DocumentEvent event) {
		}
		public void setActiveNode(TextEditNode node) {
			fActiveNode= node;
		}
		public void updateParents(int delta) {
			TextEditNode node= fActiveNode.fParent;
			while (node != null) {
				node.childNodeChanged(delta);
				node= node.fParent;
			}
		}
		public static int getDelta(DocumentEvent event) {
			return (event.getText() == null ? 0 : event.getText().length()) - event.getLength();
		}
	}
	private static class DoRangeUpdater extends RangeUpdater {
		private List fProcessedNodes= new ArrayList(10);
		public void setActiveNode(TextEditNode node) {
			if (fActiveNode != null)
				fProcessedNodes.add(fActiveNode);
			super.setActiveNode(node);
		}
		public void documentChanged(DocumentEvent event) {
			fActiveNode.checkRange(event);
			int delta= getDelta(event);
			if (!fActiveNode.activeNodeChanged(delta)) {
				for (Iterator iter= fProcessedNodes.iterator(); iter.hasNext();) {
					((TextEditNode)iter.next()).previousNodeChanged(delta);
				}
			}
			updateParents(delta);
		}
	}
	private static class UndoRangeUpdater  extends RangeUpdater {
		private RootNode fRootNode;
		public UndoRangeUpdater(RootNode root) {
			fRootNode= root;
		}
		public void setActiveNode(TextEditNode node) {
			super.setActiveNode(node);
		}
		public void documentChanged(DocumentEvent event) {
			fActiveNode.checkRange(event);
			int delta= getDelta(event);
			if (!fActiveNode.activeNodeChanged(delta)) {
				int start= fRootNode.getUndoIndex() + 1;
				List children= fRootNode.fChildren;
				int size= children != null ? children.size() : 0;
				for (int i= start; i < size; i++) {
					updateUndo((TextEditNode)children.get(i), delta);
				}
			}
			updateParents(delta);
		}
		private void updateUndo(TextEditNode node, int delta) {
			node.previousNodeChanged(delta);
			List children= node.fChildren;
			int size= children != null ? children.size() : 0;
			for (int i= 0; i < size; i++) {
				updateUndo((TextEditNode)children.get(i), delta);
			}
		}
	}
	
	//---- Creating instances ---------------------------------------------------------------------------
	
	static TextEditNode create(TextEdit edit) {
		if (edit instanceof MoveTextEdit)
			return new MoveNode(edit);
		if (edit instanceof MoveTextEdit.TargetMark)
			return new TargetMarkNode(edit);
		return new DefaultNode(edit);
	}
	
	static RootNode createRoot(int length) {
		return new RootNode(length);
	}
	
	protected TextEditNode(TextEdit edit) {
		fEdit= edit;
	}
	
	//---- Adding children ---------------------------------------------------------------------------
	
	protected void add(TextEditNode node) {
		if (fChildren == null) {
			fChildren= new ArrayList(1);
			node.fParent= this;
			fChildren.add(node);
			return;
		}
		// Optimize using binary search
		for (Iterator iter= fChildren.iterator(); iter.hasNext();) {
			TextEditNode child= (TextEditNode)iter.next();
			if (child.covers(node)) {
				child.add(node);
				return;
			}
		}
		for (int i= 0; i < fChildren.size(); ) {
			TextEditNode child= (TextEditNode)fChildren.get(i);
			if (node.covers(child)) {
				fChildren.remove(i);
				node.add(child);
			} else {
				i++;
			}
		}
		node.fParent= this;
		fChildren.add(node);
	}
	
	public boolean covers(TextEditNode node) {
		return false; 
	}
	
	//---- Accessing --------------------------------------------------------------------------------------
	
	protected RootNode getRoot() {
		TextEditNode candidate= this;
		while(candidate.fParent != null)
			candidate= candidate.fParent;
		return (RootNode)candidate;
	}
	
	//---- Query interface --------------------------------------------------------------------------------
	
	protected boolean isSynthetic() {
		return fEdit.isSynthetic;
	}
	
	public boolean isMove() {
		return false;
	}
	
	//---- Accessing Ranges ------------------------------------------------------------------------------
	
	protected void checkRange(DocumentEvent event) {
		TextRange range= getTextRange();
		int eventOffset= event.getOffset();
		int eventLength= event.getLength();
		int eventEnd = eventOffset + eventLength - 1;
		// "Edit changes text that lies outside its defined range"
		Assert.isTrue(range.fOffset <= eventOffset && eventEnd <= range.getInclusiveEnd());
	}
	
	protected TextRange getTextRange() {
		return fEdit.getTextRange();
	}
	
	protected TextRange getChildRange() {
		return getTextRange();
	}
	
	protected TextRange getParentRange() {
		return getTextRange();
	}
		
	public boolean validate(int bufferLength) {
		if (fChildren == null)
			return true;
		// Only Moves and Nops can be parents	
		if (!(fEdit instanceof MoveTextEdit || fEdit instanceof NopTextEdit))
			return false;
		TextRange lastRange= null;
		for (Iterator iter= fChildren.iterator(); iter.hasNext(); ) {
			TextEditNode node= (TextEditNode)iter.next();
			if (!node.validate(bufferLength))
				return false;
			TextRange range= node.fEdit.getTextRange();
			if (!range.isValid() || range.fOffset + range.fLength > bufferLength)
				return false;
			if (lastRange != null && !(range.isInsertionPointAt(lastRange.fOffset) || range.liesBehind(lastRange)))
				return false;
			lastRange= range;
		}
		return true;
	}

	//---- Updating ----------------------------------------------------------------------------------------
	
	protected boolean activeNodeChanged(int delta) {
		TextRange range= getTextRange();
		range.fLength+= delta;
		// we didn't adjust any processed nodes.
		return false;
	}
	
	protected void previousNodeChanged(int delta) {
		TextRange range= getTextRange();
		range.fOffset+= delta;
	}
	
	protected void childNodeChanged(int delta) {
		getTextRange().fLength+= delta;
	}

	//---- Do it ---------------------------------------------------------------------------------------------
	
	protected void performDo(TextBuffer buffer, RangeUpdater updater, UndoMemento undo, IProgressMonitor pm) throws CoreException {
		int size= fChildren != null ? fChildren.size() : 0;
		for (int i= size - 1; i >= 0; i--) {
			TextEditNode child= (TextEditNode)fChildren.get(i);
			child.performDo(buffer, updater, undo, pm);
		}
		updater.setActiveNode(this);
		if (isSynthetic())
			fEdit.perform(buffer);
		else
			undo.add(fEdit.perform(buffer));
		pm.worked(1);
	}
	
	public void performedDo()  {
		int size= fChildren != null ? fChildren.size() : 0;
		for (int i= size - 1; i >= 0; i--) {
			TextEditNode child= (TextEditNode)fChildren.get(i);
			child.performedDo();
		}
		fEdit.performed();
	}
	
	//---- Undo it -------------------------------------------------------------------------------------------
	
	protected void performUndo(TextBuffer buffer, RangeUpdater updater, UndoMemento undo, IProgressMonitor pm) throws CoreException {
		int size= fChildren != null ? fChildren.size() : 0;
		for (int i= 0; i < size; i++) {
			setUndoIndex(i);
			TextEditNode child= (TextEditNode)fChildren.get(i);
			child.performUndo(buffer, updater, undo, pm);
		}
		updater.setActiveNode(this);
		if (isSynthetic())
			fEdit.perform(buffer);
		else
			undo.add(fEdit.perform(buffer));
		pm.worked(1);
	}
	
	protected void setUndoIndex(int index) {
	}
	
	public void performedUndo()  {
		int size= fChildren != null ? fChildren.size() : 0;
		for (int i= 0; i < size; i++) {
			TextEditNode child= (TextEditNode)fChildren.get(i);
			child.performedUndo();
		}
		fEdit.performed();
	}
	
//	protected void createUndoList(List list) {
//		int size= fChildren != null ? fChildren.size() : 0;
//		for (int i= 0; i < size; i++) {
//			TextEditNode child= (TextEditNode)fChildren.get(i);
//			child.createUndoList(list);
//		}
//		list.add(this);
//	}	
}

