/*******************************************************************************
 * Copyright (c) 2006 Sybase, Inc. 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:
 *     Sybase, Inc. - initial API and implementation
 *******************************************************************************/
package org.eclipse.jst.pagedesigner.commands.range;

import java.util.Stack;
import java.util.Vector;

import org.eclipse.core.runtime.Assert;
import org.eclipse.gef.GraphicalViewer;
import org.eclipse.gef.dnd.TemplateTransfer;
import org.eclipse.jst.pagedesigner.IHTMLConstants;
import org.eclipse.jst.pagedesigner.css2.CSSUtil;
import org.eclipse.jst.pagedesigner.css2.ICSSStyle;
import org.eclipse.jst.pagedesigner.dom.DOMRange;
import org.eclipse.jst.pagedesigner.dom.EditHelper;
import org.eclipse.jst.pagedesigner.dom.EditModelQuery;
import org.eclipse.jst.pagedesigner.dom.EditValidateUtil;
import org.eclipse.jst.pagedesigner.dom.IDOMPosition;
import org.eclipse.jst.pagedesigner.utils.DOMUtil;
import org.eclipse.swt.dnd.Clipboard;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.Text;

/**
 * @author mengbo
 */
public abstract class DesignEdit {
	public static final int DELETE_OPERATION = 1;

	public static final int INSERT_OPERATION = 2;

	private Stack _selections;

	private DOMRange _range;

	private GraphicalViewer _viewer;

	private IDOMPosition _operationPosition;

	protected Document _document;

	protected IDOMModel _model;

	protected Stack _processedResult;

	public DesignEdit(DOMRange range, GraphicalViewer viewer) {
		setRange(range);
		_viewer = viewer;
		_operationPosition = getRange().getStartPosition();
		_document = ((IDOMNode) _operationPosition.getContainerNode())
				.getModel().getDocument();
		_model = ((IDOMNode) _operationPosition.getContainerNode()).getModel();
	}

	protected abstract boolean operate();

	protected abstract Text processText(WorkNode node);

	protected abstract Node processNode(WorkNode node);

	protected abstract Node processContainer(WorkNode node);

	public DOMRange getRange() {
		return _range;
	}

	void setRange(DOMRange range) {
		range = EditHelper.normal(range);
		IDOMPosition start = EditHelper.ensureDOMPosition(range
				.getStartPosition());
		IDOMPosition end = EditHelper.ensureDOMPosition(range.getEndPosition());
		_range = new DOMRange(start, end);
		EditValidateUtil.validRange(range);
	}

	protected Clipboard getClipboard() {
		return new Clipboard(_viewer.getControl().getDisplay());
	}

	public IDOMPosition getOperationPosition() {
		// try
		// {
		// Assert.isTrue(_operationPosition != null &&
		// _operationPosition.getContainerNode() != null &&
		// _operationPosition.getOffset() > -1);
		// if (_operationPosition.isText())
		// {
		// int length = ((Text)
		// _operationPosition.getContainerNode()).getLength();
		// Assert.isTrue(_operationPosition.getOffset() >= 0 &&
		// _operationPosition.getOffset() <= length);
		// }
		// }
		// catch (Exception e)
		// {
		// // "Error", "Error in operation location move"
		// PDPlugin.getAlerts().confirm("Alert.DesignEdit.opLocationValidTitle",
		// "Alert.DesignEdit.opLocationValidMessage"); //$NON-NLS-1$
		// //$NON-NLS-2$
		// }

		return _operationPosition;
	}

	protected void setOperationPosition(IDOMPosition position) {
		if (!EditValidateUtil.validPosition(position)) {
			return;
		}
		position = EditHelper.ensureDOMPosition(position);
		_operationPosition = position;
	}

	public boolean perform() {
		boolean result = false;

		result = operate();
		return result;
	}

	/**
	 * @return Returns the _viewer.
	 */
	public GraphicalViewer getViewer() {
		return _viewer;
	}

	private Stack collectNodes() {
		Node node;
		Stack result = new Stack();
		IDOMPosition start = getRange().getStartPosition(), end = getRange()
				.getEndPosition();
		int pos[] = new int[] { EditModelQuery.getIndexedRegionLocation(start),
				EditModelQuery.getIndexedRegionLocation(end), };
		if (!EditModelQuery.isSame(start, end)) {
			Node ancestor = EditModelQuery.getInstance().getCommonAncestor(
					start, end);
			WorkNode rootWorkNode = new WorkNode(ancestor, pos[0], pos[1]);
			rootWorkNode.setRoot(true);
			result.push(rootWorkNode);
			try {
				// Loop all the children of the ancestor, and and the result
				// will be collected
				if (EditModelQuery.isText(ancestor)) {
					Stack temp = new Stack();
					EditHelper.getInstance().collectNodes(ancestor, pos[0],
							pos[1], ancestor, temp);
					WorkNode wNode = (WorkNode) temp.remove(0);
					wNode.setParent(rootWorkNode);
					result.push(wNode);
				} else {
					node = ancestor.getFirstChild();
					Stack temp = new Stack();
					while (node != null) {
						EditHelper.getInstance().collectNodes(node, pos[0],
								pos[1], ancestor, temp);
						while (temp.size() > 0) {
							WorkNode wNode = (WorkNode) temp.remove(0);
							if (wNode.getNode().getParentNode() == ancestor) {
								wNode.setParent(rootWorkNode);
							}
							result.push(wNode);
						}
						node = node.getNextSibling();
					}
				}
			} catch (Exception e) {
				result.clear();
			}
		}
		return result;
	}

	/**
	 * @return Returns the result.
	 */
	public Stack getSelections() {
		if (_selections == null) {
			_selections = collectNodes();
		}
		return _selections;
	}

	public Stack getProcessedResult() {
		if (_processedResult == null) {
			_processedResult = new Stack();
			WorkNode rootNode = getRootWorkNode();
			if (rootNode != null) {
				processNodes(rootNode, _processedResult);
			}
		}
		return _processedResult;
	}

	protected final WorkNode getRootWorkNode() {
		WorkNode result = null;
		if (getSelections().size() > 0) {
			WorkNode node = (WorkNode) getSelections().get(0);
			while (node.getParent() != null) {
				node = node.getParent();
			}
			result = node;
			Assert.isTrue(node.isRoot());
		}
		return result;
	}

	protected final boolean processText(WorkNode node, Stack result) {
		boolean done = false;
		if (EditModelQuery.isText(node.getNode())) {
			Node text = processText(node);
			if (text != null) {
				result.add(text);
			}
			getSelections().remove(node);
			done = true;
		}
		return done;
	}

	protected final boolean processContainer(WorkNode node, Stack result) {
		processContainer(node);
		getSelections().remove(node);
		return true;
	}

	protected final boolean processChildren(WorkNode node, Stack result) {
		boolean done = false;
		if (getFirstSelectedChild(node) != null) {
			Stack myResult = new Stack();
			{
				WorkNode child = null;
				while ((child = getFirstSelectedChild(node)) != null) {
					{
						processNodes(child, myResult);
					}
				}
				Node newParent = processContainer(node);
				newParent = toBeParent(newParent, myResult);
				result.push(newParent);
			}
			getSelections().remove(node);
			done = true;
		}
		return done;
	}

	protected final boolean processChildren1(WorkNode node, Stack result) {
		boolean done = false;
		if (node.getNode().hasChildNodes()) {
			Stack myResult = new Stack();
			{
				Node childNode = node.getNode().getFirstChild();
				Node next = null;
				while (childNode != null) {
					next = childNode.getNextSibling();
					int x1 = EditModelQuery.getNodeStartIndex(childNode) - 1;
					int x2 = EditModelQuery.getNodeEndIndex(childNode) + 1;
					processNodes(new WorkNode(childNode, x1, x2), myResult);
					childNode = next;
				}
				Node newParent = processContainer(node);
				newParent = toBeParent(newParent, myResult);
				result.push(newParent);
			}
			getSelections().remove(node);
			done = true;
		}
		return done;
	}

	/**
	 * Process the nodes that are selected, the result is a collection of nodes
	 * that either are clones or the nodes cuted.
	 * 
	 * @param node
	 * @param result
	 */
	protected final void processNodes(WorkNode node, Stack result) {
		WorkNode child = null;
		if (node.isRoot()) {
			while ((child = getFirstSelectedChild(node)) != null) {
				processNodes(child, result);
			}
		} else {
			if (node.isWholeSelected()
					|| //
					(!EditModelQuery.isText(node.getNode()) && EditModelQuery
							.getInstance().isSingleRegionNode(node.getNode()))
					|| //
					EditModelQuery.isWidget(node.getNode())) {
				Node temp = processNode(node);
				if (temp != null) {
					result.push(temp);
					getSelections().remove(node);
				} else {
					if (!processText(node, result)) {
						if (!processChildren1(node, result)) {
							processContainer(node, result);
						}
					}
				}
			} else {
				if (!processText(node, result)) {
					if (!processChildren(node, result)) {
						processContainer(node, result);
					}
				}
			}
		}
	}

	protected void setClipboard(Stack result) {
		Node[] nodes = (Node[]) result.toArray(new Node[result.size()]);
		StringBuffer sb = new StringBuffer();
		for (int i = 0, size = nodes.length; i < size; i++) {
			DOMUtil.nodeToString(nodes[i], sb);
		}
		getClipboard().setContents(
				new Object[] { result, sb.toString() },
				new Transfer[] { TemplateTransfer.getInstance(),
						TextTransfer.getInstance() });
	}

	private Node toBeParent(Node parent, Stack children) {
		while (children.size() > 0) {
			parent.appendChild((Node) children.remove(0));
		}
		return parent;
	}

	private WorkNode getFirstSelectedChild(WorkNode node) {
		for (int i = 0, n = getSelections().size(); i < n; i++) {
			WorkNode wNode = (WorkNode) getSelections().get(i);
			if (wNode.getParent() == node) {
				return wNode;
			}
		}
		return null;
	}

	public Node collectStyleNodes(Node rootNode, Vector result) {
		Element element = null;
		if (rootNode instanceof Element) {
			element = (Element) rootNode;
		} else if (rootNode.getParentNode() != null) {
			element = (Element) rootNode.getParentNode();
		}
		ICSSStyle style = CSSUtil.getCSSStyle(element);

		Node node = EditModelQuery.getDocumentNode(rootNode).createElement(
				"span");
		for (int i = 0, n = result.size(); i < n; i++) {
			node.appendChild((Node) result.elementAt(i));
		}
		((Element) node).setAttribute(IHTMLConstants.ATTR_STYLE, CSSUtil
				.resolveCSSStyle(style));
		result.removeAllElements();
		result.add(node);
		return node;
	}

	public Node collectOtherStyles(Node rootNode, Vector result) {
		Node cur = rootNode, prev = null, appendPoint = null;
		if (EditValidateUtil.validNode(rootNode)) {
			while (!EditModelQuery.isDocument(cur)) {
				if (!EditValidateUtil.validNode(cur)) {
					return null;
				}
				String name = cur.getNodeName() != null ? cur.getNodeName()
						.toLowerCase() : "";
				if (EditModelQuery.HTML_STYLE_NODES.contains(name)) {
					if (prev != null) {
						Node newone = cur.cloneNode(false);
						newone.appendChild(prev);
						prev = newone;
					} else {
						prev = cur.cloneNode(false);
						appendPoint = prev;
					}
				}
				cur = cur.getParentNode();
			}
			if (appendPoint != null) {
				for (int i = 0, n = result.size(); i < n; i++) {
					appendPoint.appendChild((Node) result.elementAt(i));
				}
				result.removeAllElements();
				result.add(prev);
			}
		}
		return prev;
	}
}
