/*******************************************************************************
 * 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.common.contentmodel.util.DOMWriter;
import org.eclipse.wst.xml.core.document.XMLModel;
import org.eclipse.wst.xml.core.document.XMLNode;
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) {
			XMLNode first = (XMLNode) list.get(0);
			XMLNode last = (XMLNode) list.get(list.size() - 1);
			XMLModel 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) {
			XMLNode first = (XMLNode) list.get(0);
			XMLNode last = (XMLNode) 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;
	}
}