/*******************************************************************************
 * 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.core.resources.IFile;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Path;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
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) {
		setNodeValue(node, value, null);
	}

	/**
	 * Checks that the resource backing the model is writeable utilizing <code>validateEdit</code>
	 * on a given <tt>IWorkspace</tt>.
	 * 
	 * @param model the model to be checked
	 * @param context the shell context for which <code>validateEdit</code> will be run
	 * @return IStatus result of checking <code>validateEdit</code>. If the resource is unwriteable, <code>status.isOK()</code>
	 * will return true; otherwise, false.
	 */
	private boolean validateEdit(IStructuredModel model, Shell context) {
		if (model != null && model.getBaseLocation() != null) {
			IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(model.getBaseLocation()));
			if (!file.isAccessible())
				return true;
			return ResourcesPlugin.getWorkspace().validateEdit(new IFile[] {file}, context).isOK();
		}
		return false;
	}

	/**
	 * 
	 */
	public void setNodeValue(Node node, String value, Shell context) {
		// Model should not be edited because base location is read-only
		if (node instanceof IDOMNode && !validateEdit(((IDOMNode) node).getModel(), context)) {
			return;
		}
		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;
	}
}