/*******************************************************************************
 * 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.ArrayList;
import java.util.List;

import org.eclipse.jst.pagedesigner.IHTMLConstants;
import org.eclipse.jst.pagedesigner.commands.CommandResources;
import org.eclipse.jst.pagedesigner.dom.DOMRange;
import org.eclipse.jst.pagedesigner.dom.DOMRefPosition;
import org.eclipse.jst.pagedesigner.dom.DOMUtil;
import org.eclipse.jst.pagedesigner.dom.EditModelQuery;
import org.eclipse.jst.pagedesigner.dom.IDOMPosition;
import org.eclipse.jst.pagedesigner.viewer.IHTMLGraphicalViewer;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMText;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.Text;

/**
 * @author mengbo
 */
public class ApplyStyleCommand extends RangeModeCommand {
	private String _tag;

	private String _cssProperty;

	private String _cssPropertyValue;

	protected Element _applyingNode;

	/**
	 * @param label
	 * @param viewer
	 */
	public ApplyStyleCommand(IHTMLGraphicalViewer viewer, String tag,
			String property, String value) {
		super(
				CommandResources
						.getString("ApplyStyleCommand.Label.ApplyStyle"), viewer); //$NON-NLS-1$
		this._tag = tag;
		this._cssProperty = property;
		this._cssPropertyValue = value;
	}

	public ApplyStyleCommand(IHTMLGraphicalViewer viewer, Element node,
			String property, String value) {
		super(
				CommandResources
						.getString("ApplyStyleCommand.Label.ApplyStyle"), viewer); //$NON-NLS-1$
		this._applyingNode = node;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jst.pagedesigner.commands.DesignerCommand#doExecute()
	 */
	protected DOMRange doRangeExecute(DOMRange range) {
		if (range == null || range.isEmpty()) {
			return null;
		}

		boolean ordered = range.isOrdered();
		IDOMPosition start = ordered ? range.getStartPosition() : range
				.getEndPosition();
		IDOMPosition end = ordered ? range.getEndPosition() : range
				.getStartPosition();

		Node startContainer = start.getContainerNode();
		Node endContainer = end.getContainerNode();

		Node common = DOMUtil.findCommonAncester(start.getContainerNode(), end
				.getContainerNode());
		if (common == null) {
			// should not happen.
			return null;
		}

		if (common instanceof Text) {
			// under the same Text scope
			range = doTextNodeStyleApply((Text) common, start.getOffset(), end
					.getOffset());

			return range;
		} else {

			if (startContainer instanceof Text) {
				// if the start offset is 0,then skip split the Text
				if (start.getOffset() > 0) {
					startContainer = ((Text) startContainer).splitText(start
							.getOffset());
					start = new DOMRefPosition(startContainer, false);
				}
			} else {
				startContainer = start.getNextSiblingNode();
			}
			if (endContainer instanceof Text) {
				if (end.getOffset() > 0) {
					endContainer = ((Text) endContainer).splitText(end
							.getOffset());
					endContainer = endContainer.getPreviousSibling();
				} else {
					endContainer = endContainer.getPreviousSibling();
				}
			} else {
				endContainer = end.getPreviousSiblingNode();
			}

			for (Node node = startContainer; node != endContainer; node = EditModelQuery
					.getInstance().getNextLeafNeighbor(node)) {
				if (EditModelQuery.hasAncestor(node, getTag(), true)) {
					continue;
				}
				Element newnode = createStyleElement();
				node.getParentNode().insertBefore(newnode, node);
				newnode.appendChild(node);
			}
			if (!EditModelQuery.hasAncestor(endContainer, getTag(), true)) {
				Element newnode = createStyleElement();
				endContainer.getParentNode()
						.insertBefore(newnode, endContainer);
				newnode.appendChild(endContainer);
			}

		}

		// merge the style tags

		for (Node node = startContainer; node != endContainer; node = EditModelQuery
				.getInstance().getNextLeafNeighbor(node)) {
			Node stylenode = node;
			while (stylenode != null
					&& !stylenode.getNodeName().equalsIgnoreCase(getTag())) {
				stylenode = stylenode.getParentNode();
			}
			if (stylenode == null) {
				continue;
			}
			if (stylenode.getNextSibling() != null
					&& stylenode.getNextSibling().getNodeName()
							.equalsIgnoreCase(getTag())) {
				Node sibling = stylenode.getNextSibling();
				while (sibling.getFirstChild() != null) {
					stylenode.appendChild(sibling.getFirstChild());
				}
				stylenode.getParentNode().removeChild(sibling);
				node = startContainer;
			}
		}

		return new DOMRange(start, end);

		/*
		 * boolean ordered = range.isOrdered(); IDOMPosition start = ordered ?
		 * range.getStartPosition() : range.getEndPosition(); IDOMPosition end =
		 * ordered ? range.getEndPosition() : range.getStartPosition();
		 * 
		 * Node common = DOMUtil.findCommonAncester(start.getContainerNode(),
		 * end.getContainerNode()); if (common == null) { // should not happen.
		 * return null; }
		 * 
		 * DOMRange result = null; if (common instanceof Text) { result =
		 * doTextNodeStyleApply((Text) common, start.getOffset(),
		 * end.getOffset()); } else { IDOMPosition startPosition = start;
		 * IDOMPosition endPosition = end; Node ancester = common; DOMRange[]
		 * leftRange = new DOMRange[1]; DOMRange[] rightRange = new DOMRange[1];
		 * 
		 * startPosition = partialApply(startPosition, ancester, true,
		 * leftRange); endPosition = partialApply(endPosition, ancester, false,
		 * rightRange); DOMRange middle = middleApply(ancester, startPosition,
		 * endPosition);
		 * 
		 * IDOMPosition startref = null; if (leftRange[0] != null &&
		 * leftRange[0].getStartPosition() != null) { startref =
		 * leftRange[0].getStartPosition(); } else if (middle != null &&
		 * middle.getStartPosition() != null) { startref =
		 * middle.getStartPosition(); } else if (rightRange[0] != null &&
		 * rightRange[0].getStartPosition() != null) { startref =
		 * rightRange[0].getStartPosition(); }
		 * 
		 * IDOMPosition endref = null; if (rightRange[0] != null &&
		 * rightRange[0].getEndPosition() != null) { endref =
		 * rightRange[0].getEndPosition(); } else if (middle != null &&
		 * middle.getEndPosition() != null) { endref = middle.getEndPosition(); }
		 * else if (leftRange[0] != null && leftRange[0].getEndPosition() !=
		 * null) { endref = leftRange[0].getEndPosition(); }
		 * 
		 * if (startref == null) { result = null; } else { startref = new
		 * DOMPosition(EditModelQuery.getInstance().getNextLeafNeighbor(startref.getContainerNode()),
		 * 0); System.out.println(startref.toString()); endref = new
		 * DOMPosition(endref.getContainerNode(), 0); result = new
		 * DOMRange(startref, endref); } }
		 * 
		 * if (result == null) { return null; }
		 * 
		 * if (ordered) { return result; } else { return new
		 * DOMRange(result.getEndPosition(), result.getStartPosition()); }
		 */
	}

	private DOMRange middleApply(Node ancester, IDOMPosition startPosition,
			IDOMPosition endPosition) {
		startPosition = skip(startPosition, true);
		if (startPosition.getNextSiblingNode() == null
				|| startPosition.getOffset() >= endPosition.getOffset()) {
			return null;
		} else {
			List needMove = new ArrayList();
			Node startNext = startPosition.getNextSiblingNode();
			Node endNext = endPosition.getNextSiblingNode();
			while (startNext != null && startNext != endNext) {
				needMove.add(startNext);
				startNext = startNext.getNextSibling();
			}
			Element newEle = createStyleElement();
			ancester.insertBefore(newEle, startPosition.getNextSiblingNode());
			for (int i = 0, n = needMove.size(); i < n; i++) {
				newEle.appendChild((Node) needMove.get(i));
			}
			return new DOMRange(new DOMRefPosition(newEle, false),
					new DOMRefPosition(newEle, true));
		}

	}

	private IDOMPosition partialApply(IDOMPosition position, Node ancester,
			boolean forward, DOMRange[] result) {
		IDOMPosition startRef = null, endRef = null;

		while (position != null && position.getContainerNode() != ancester) {
			Node container = position.getContainerNode();
			if (container instanceof Text) {
				// splitText will move the position up one level
				position = splitText(position);
			} else {
				// skip those nodes that can't have the style applied.
				position = skip(position, forward);
				Node sibling = position.getSibling(forward);
				if (sibling != null) {
					List needMove = new ArrayList();
					while (sibling != null) {
						needMove.add(sibling);
						sibling = forward ? sibling.getNextSibling() : sibling
								.getPreviousSibling();
					}

					// ok, there is nodes that need the style
					Element newEle = createStyleElement();
					container.insertBefore(newEle, position
							.getNextSiblingNode());
					for (int i = 0, size = needMove.size(); i < size; i++) {
						newEle.appendChild((Node) needMove.get(i));
					}
					if (startRef == null) {
						startRef = new DOMRefPosition(newEle, !forward);
					}
					endRef = new DOMRefPosition(newEle, forward);
				}
				// move the position up one level
				position = new DOMRefPosition(container, forward);
			}
		}
		if (startRef == null) {
			result[0] = null;
		} else {
			result[0] = forward ? new DOMRange(startRef, endRef)
					: new DOMRange(endRef, startRef);
		}
		return position;
	}

	/**
	 * @param position
	 * @return
	 */
	private IDOMPosition splitText(IDOMPosition position) {
		Text text = (Text) position.getContainerNode();
		int offset = position.getOffset();
		if (offset <= 0) {
			return new DOMRefPosition(text, false);
		} else if (offset >= text.getData().length()) {
			return new DOMRefPosition(text, true);
		} else {
			text.splitText(offset);
			return new DOMRefPosition(text, true);
		}
	}

	/**
	 * @param start
	 * @param end
	 * @param common
	 */
	private DOMRange doTextNodeStyleApply(Text textNode, int startOffset,
			int endOffset) {
		String data = textNode.getData();
		String before = data.substring(0, startOffset);
		String middle = data.substring(startOffset, endOffset);
		String tail = data.substring(endOffset);

		Text middleText = getModel().getDocument().createTextNode(middle);

		// case 1: normal one
		if (!isEmptyString(before) && !isEmptyString(tail)) {
			Node parent = textNode.getParentNode();
			parent.insertBefore(
					getModel().getDocument().createTextNode(before), textNode);
			Element bnode = createStyleElement();
			bnode.appendChild(middleText);
			parent.insertBefore(bnode, textNode);
			textNode.setNodeValue(tail);
		}

		if (isEmptyString(before) && !isEmptyString(tail)) {
			Node sibling = textNode.getPreviousSibling();
			if (sibling != null
					&& sibling.getNodeName().equalsIgnoreCase(getTag())) {
				sibling.appendChild(middleText);
			} else {
				Node parent = textNode.getParentNode();
				parent.insertBefore(getModel().getDocument().createTextNode(
						before), textNode);
				Element bnode = createStyleElement();
				bnode.appendChild(middleText);
				parent.insertBefore(bnode, textNode);
			}
			textNode.setNodeValue(tail);
		}

		if (!isEmptyString(before) && isEmptyString(tail)) {
			Node sibling = textNode.getNextSibling();
			textNode.setNodeValue(before);
			if (sibling != null
					&& sibling.getNodeName().equalsIgnoreCase(getTag())) {
				sibling.insertBefore(middleText, sibling.getFirstChild());
			} else {
				Element bnode = createStyleElement();
				bnode.appendChild(middleText);
				textNode.getParentNode().insertBefore(bnode, sibling);
			}
		}

		if (isEmptyString(before) && isEmptyString(tail)) {

			Node previousSibling = textNode.getPreviousSibling();
			Node nextSibling = textNode.getNextSibling();
			//
			if (getTag().equalsIgnoreCase(IHTMLConstants.TAG_P)) {
				Element bnode = createStyleElement();
				bnode.appendChild(middleText);
				textNode.getParentNode().insertBefore(bnode, textNode);
				textNode.getParentNode().removeChild(textNode);
			}
			//
			else {
				if (previousSibling != null
						&& previousSibling.getNodeName().equalsIgnoreCase(
								getTag()) && nextSibling != null
						&& nextSibling.getNodeName().equalsIgnoreCase(getTag())) {
					previousSibling.appendChild(middleText);
					while (nextSibling.getFirstChild() != null) {
						previousSibling
								.appendChild(nextSibling.getFirstChild());
					}
					nextSibling.getParentNode().removeChild(nextSibling);
				} else if (previousSibling != null
						&& previousSibling.getNodeName().equalsIgnoreCase(
								getTag())) {
					previousSibling.appendChild(middleText);
				} else if (nextSibling != null
						&& nextSibling.getNodeName().equalsIgnoreCase(getTag())) {
					nextSibling.insertBefore(middleText, nextSibling
							.getFirstChild());
				} else {
					Element bnode = createStyleElement();
					bnode.appendChild(middleText);
					textNode.getParentNode().insertBefore(bnode, textNode);
				}
				textNode.getParentNode().removeChild(textNode);
			}
		}

		return new DOMRange(new DOMRefPosition(middleText, false),
				new DOMRefPosition(middleText, true));
	}

	private boolean isEmptyString(String str) {
		if (str == null || str.length() == 0) {
			return true;
		}
		return false;
	}

	/**
	 * @return
	 */
	protected Element createStyleElement() {
		if (_applyingNode != null) {
			return _applyingNode;
		} else {
			Element element = getModel().getDocument().createElement(getTag());
			if (_cssProperty != null && _cssPropertyValue != null) {
				element.setAttribute(_cssProperty, _cssPropertyValue);
			}
			return element;
		}
	}

	/**
	 * @param position
	 * @param b
	 * @return
	 */
	private IDOMPosition skip(IDOMPosition position, boolean forward) {
		Node node = position.getSibling(forward);

		if (node == null) {
			return position;
		}
		boolean canSkip = false;
		if (node instanceof Text) {
			canSkip = ((IDOMText) node).isElementContentWhitespace();
		} else if (node instanceof Element) {
			if (getTag().equalsIgnoreCase(((Element) node).getTagName())) {
				canSkip = true;
			} else {
				canSkip = false;
			}
		} else {
			canSkip = true;
		}
		if (canSkip) {
			return new DOMRefPosition(node, forward);
		} else {
			return position;
		}
	}

	/**
	 * @return Returns the _cssProperty.
	 */
	public final String getCssProperty() {
		return _cssProperty;
	}

	/**
	 * @param property
	 *            The _cssProperty to set.
	 */
	public final void setCssProperty(String property) {
		_cssProperty = property;
	}

	/**
	 * @return Returns the _cssPropertyValue.
	 */
	public final String getCssPropertyValue() {
		return _cssPropertyValue;
	}

	/**
	 * @param propertyValue
	 *            The _cssPropertyValue to set.
	 */
	public final void setCssPropertyValue(String propertyValue) {
		_cssPropertyValue = propertyValue;
	}

	/**
	 * @return Returns the _tag.
	 */
	public final String getTag() {
		if (_tag != null) {
			return _tag;
		} else {
			return _applyingNode.getNodeName();
		}
	}

	/**
	 * @param _tag
	 *            The _tag to set.
	 */
	public final void setTag(String _tag) {
		this._tag = _tag;
	}

	private void updateStyleElement() {

	}
}
