/*******************************************************************************
 * Copyright (c) 2004-2006 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;
	}

    public String getElementTextValue(Element element) 
    {
      List list = _getElementTextContent(element);
      return list != null ? getValueForTextContent(list) : null;
    }
    
    public void setElementTextValue(Element element, String value)
    {
      setElementNodeValue(element, value);      
    }
    
    private List _getElementTextContent(Element element) {
        List result = null;

        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;
    }

	/**
	 * 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()) {
			result = _getElementTextContent(element);
		}
		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;
	}
}