/*******************************************************************************
 * Copyright (c) 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
 *******************************************************************************/


package org.eclipse.wst.xml.ui.internal.tabletree;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;

import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.PlatformUI;
import org.eclipse.wst.xml.core.internal.contentmodel.util.DOMWriter;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
import org.w3c.dom.Attr;
import org.w3c.dom.CharacterData;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.ProcessingInstruction;
import org.w3c.dom.Text;


/**
 * This performs the work of taking a DOM tree and converting it to a
 * displayable 'UI' tree.
 * 
 * For example : - white space text nodes are ommited from the 'UI' tree -
 * adjacent Text and EntityReference nodes are combined into a single 'UI'
 * node - Elements with 'text only' children are diplayed without children
 *  
 */
public class TreeContentHelper {

	public static final int HIDE_WHITE_SPACE_TEXT_NODES = 8;
	public static final int COMBINE_ADJACENT_TEXT_AND_ENTITY_REFERENCES = 16;
	public static final int HIDE_ELEMENT_CHILD_TEXT_NODES = 32;

	protected int style = HIDE_WHITE_SPACE_TEXT_NODES | COMBINE_ADJACENT_TEXT_AND_ENTITY_REFERENCES | HIDE_ELEMENT_CHILD_TEXT_NODES;

	/**
	 *  
	 */
	public boolean hasStyleFlag(int flag) {
		return (style & flag) != 0;
	}

	/**
	 *  
	 */
	public Object[] getChildren(Object element) {
		Object[] result = null;

		if (element instanceof Node) {
			Node node = (Node) element;
			List list = new ArrayList();
			boolean textContentOnly = true;

			NamedNodeMap map = node.getAttributes();
			if (map != null) {
				int length = map.getLength();
				for (int i = 0; i < length; i++) {
					list.add(map.item(i));
					textContentOnly = false;
				}
			}

			Node prevIncludedNode = null;
			for (Node childNode = node.getFirstChild(); childNode != null; childNode = childNode.getNextSibling()) {
				int childNodeType = childNode.getNodeType();
				boolean includeNode = true;

				if (includeNode && hasStyleFlag(HIDE_WHITE_SPACE_TEXT_NODES)) {
					if (isIgnorableText(childNode)) {
						// filter out the ignorable text node
						includeNode = false;
					}
				}

				if (includeNode && hasStyleFlag(COMBINE_ADJACENT_TEXT_AND_ENTITY_REFERENCES)) {
					if (isTextOrEntityReferenceNode(childNode) && prevIncludedNode != null && isTextOrEntityReferenceNode(prevIncludedNode)) {
						// we only show the first of a list of adjacent text
						// or entity reference node in the tree
						// so we filter out this subsequent one
						includeNode = false;
					}
				}

				if (hasStyleFlag(HIDE_ELEMENT_CHILD_TEXT_NODES)) {
					if (childNodeType != Node.TEXT_NODE && childNodeType != Node.ENTITY_REFERENCE_NODE) {
						textContentOnly = false;
					}
				}

				if (includeNode) {
					list.add(childNode);
					prevIncludedNode = childNode;
				}
			}

			if (hasStyleFlag(HIDE_ELEMENT_CHILD_TEXT_NODES) && textContentOnly) {
				result = new Object[0];
			} else {
				result = list.toArray();
			}
		}
		return result;
	}

	/**
	 *  
	 */
	protected boolean isTextOrEntityReferenceNode(Node node) {
		return node.getNodeType() == Node.TEXT_NODE || node.getNodeType() == Node.ENTITY_REFERENCE_NODE;
	}

	/**
	 *  
	 */
	public boolean isIgnorableText(Node node) {
		boolean result = false;
		if (node.getNodeType() == Node.TEXT_NODE) {
			String data = ((Text) node).getData();
			result = (data == null || data.trim().length() == 0);
		}
		return result;
	}

	/**
	 *  
	 */
	public boolean isCombinedTextNode(Node node) {
		boolean result = false;
		if (node.getNodeType() == Node.TEXT_NODE) {
			Node nextNode = node.getNextSibling();
			if (nextNode != null) {
				if (nextNode.getNodeType() == Node.ENTITY_REFERENCE_NODE) {
					result = true;
				}
			}
		} else if (node.getNodeType() == Node.ENTITY_REFERENCE_NODE) {
			result = true;
		}
		return result;
	}

	/**
	 *  
	 */
	public List getCombinedTextNodeList(Node theNode) {
		List list = new Vector();
		boolean prevIsEntity = false;
		for (Node node = theNode; node != null; node = node.getNextSibling()) {
			int nodeType = node.getNodeType();
			if (nodeType == Node.ENTITY_REFERENCE_NODE) {
				prevIsEntity = true;
				list.add(node);
			} else if (nodeType == Node.TEXT_NODE && (prevIsEntity || node == theNode)) {
				prevIsEntity = false;
				list.add(node);
			} else {
				break;
			}
		}
		return list;
	}

	/**
	 * If the element is has 'text only' content this method will return the
	 * list of elements that compose the text only content
	 */
	public List getElementTextContent(Element element) {
		List result = null;
		if (!element.hasAttributes()) {
			for (Node node = element.getFirstChild(); node != null; node = node.getNextSibling()) {
				if (node.getNodeType() == Node.TEXT_NODE || node.getNodeType() == Node.ENTITY_REFERENCE_NODE) {
					if (result == null) {
						result = new Vector();
					}
					result.add(node);
				} else {
					result = null;
					break;
				}
			}
		}
		return result;
	}

	/**
	 *  
	 */
	public String getNodeValue(Node node) {
		String result = null;
		int nodeType = node.getNodeType();
		switch (nodeType) {
			case Node.ATTRIBUTE_NODE : {
				result = ((Attr) node).getValue();
				break;
			}
			case Node.CDATA_SECTION_NODE :
			// drop thru
			case Node.COMMENT_NODE : {
				result = ((CharacterData) node).getData();
				break;
			}
			case Node.DOCUMENT_TYPE_NODE : {
				result = getDocumentTypeValue((DocumentType) node);
				break;
			}
			case Node.ELEMENT_NODE : {
				result = getElementNodeValue((Element) node);
				break;
			}
			case Node.ENTITY_REFERENCE_NODE :
			// drop thru
			case Node.TEXT_NODE : {
				result = getTextNodeValue(node);
				break;
			}
			case Node.PROCESSING_INSTRUCTION_NODE : {
				result = ((ProcessingInstruction) node).getData();
				break;
			}
		}
		return result;
	}

	/**
	 *  
	 */
	public void setNodeValue(Node node, String value) {
		int nodeType = node.getNodeType();
		try {
			switch (nodeType) {
				case Node.ATTRIBUTE_NODE : {
					((Attr) node).setValue(value);
					break;
				}
				case Node.CDATA_SECTION_NODE :
				// drop thru
				case Node.COMMENT_NODE : {
					((CharacterData) node).setData(value);
					break;
				}
				case Node.ELEMENT_NODE : {
					setElementNodeValue((Element) node, value);
					break;
				}
				case Node.ENTITY_REFERENCE_NODE :
				// drop thru
				case Node.TEXT_NODE : {
					setTextNodeValue(node, value);
					break;
				}
				case Node.PROCESSING_INSTRUCTION_NODE : {
					((ProcessingInstruction) node).setData(value);
					break;
				}
			}
		} catch (DOMException e) {
			Display d = getDisplay();
			if (d != null)
				d.beep();
		}
	}

	private Display getDisplay() {

		return PlatformUI.getWorkbench().getDisplay();
	}


	/**
	 *  
	 */
	protected String getDocumentTypeValue(DocumentType documentType) {
		return DOMWriter.getDocumentTypeData(documentType);
	}

	/**
	 *  
	 */
	protected String getElementNodeValue(Element element) {
		String result = null;
		List list = getElementTextContent(element);
		if (list != null) {
			result = getValueForTextContent(list);
		}
		return result;
	}

	/**
	 *  
	 */
	protected void setElementNodeValue(Element element, String value) {
		List list = getElementTextContent(element);
		if (list != null) {
			setValueForTextContent(list, value);
		} else {
			Document document = element.getOwnerDocument();
			Text text = document.createTextNode(value);
			element.appendChild(text);
		}
	}

	/**
	 *  
	 */
	protected String getTextNodeValue(Node node) {
		String result = null;
		List list = null;
		if (isCombinedTextNode(node)) {
			list = getCombinedTextNodeList(node);
		} else {
			list = new Vector();
			list.add(node);
		}
		result = getValueForTextContent(list);
		return result;
	}

	/**
	 *  
	 */
	protected void setTextNodeValue(Node node, String value) {
		List list = null;
		if (isCombinedTextNode(node)) {
			list = getCombinedTextNodeList(node);
		} else {
			list = new Vector();
			list.add(node);
		}
		setValueForTextContent(list, value);
	}

	public Text getEffectiveTextNodeForCombinedNodeList(List list) {
		Text result = null;
		for (Iterator i = list.iterator(); i.hasNext();) {
			Node node = (Node) i.next();
			if (node.getNodeType() == Node.TEXT_NODE) {
				result = (Text) node;
				break;
			}
		}
		return result;
	}

	/**
	 *  
	 */
	protected String getValueForTextContent(List list) {
		String result = null;
		if (list.size() > 0) {
			IDOMNode first = (IDOMNode) list.get(0);
			IDOMNode last = (IDOMNode) list.get(list.size() - 1);
			IDOMModel model = first.getModel();
			int start = first.getStartOffset();
			int end = last.getEndOffset();
			try {
				result = model.getStructuredDocument().get(start, end - start);
			} catch (Exception e) {
			}
		}

		// we trim the content so that it looks nice when viewed
		// we need to be carfull to preserve the 'trimmed' text when the value
		// is set (see setValueForTextContent)
		if (result != null) {
			result = result.trim();
		}
		return result;
	}

	/**
	 *  
	 */
	protected void setValueForTextContent(List list, String value) {
		//String oldValue = getValueForTextContent();
		// we worry about preserving trimmed text
		if (list.size() > 0) {
			IDOMNode first = (IDOMNode) list.get(0);
			IDOMNode last = (IDOMNode) list.get(list.size() - 1);
			int start = first.getStartOffset();
			int end = last.getEndOffset();
			first.getModel().getStructuredDocument().replaceText(this, start, end - start, value);
		}
	}

	/**
	 *  
	 */
	public boolean isEditable(Node node) {
		int nodeType = node.getNodeType();
		boolean result = false;
		switch (nodeType) {
			case Node.ATTRIBUTE_NODE :
			// drop thru
			case Node.CDATA_SECTION_NODE :
			// drop thru
			case Node.COMMENT_NODE :
			// drop thru
			case Node.ENTITY_REFERENCE_NODE :
			// drop thru
			case Node.TEXT_NODE :
			// drop thru
			case Node.PROCESSING_INSTRUCTION_NODE : {
				result = true;
				break;
			}
			case Node.ELEMENT_NODE : {
				result = getElementTextContent((Element) node) != null || node.getChildNodes().getLength() == 0;
				break;
			}
		}
		return result;
	}
}