/*******************************************************************************
 * 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.utils;

import java.util.ArrayList;
import java.util.Comparator;

import javax.xml.namespace.QName;

import org.eclipse.jst.jsf.core.internal.tld.CMUtil;
import org.eclipse.jst.jsf.core.internal.tld.ITLDConstants;
import org.eclipse.jst.pagedesigner.adapters.IBodyInfo;
import org.eclipse.jst.pagedesigner.adapters.internal.BodyInfo;
import org.eclipse.jst.pagedesigner.dom.DOMPosition;
import org.eclipse.jst.pagedesigner.dom.DOMRefPosition;
import org.eclipse.jst.pagedesigner.dom.DOMRefPosition2;
import org.eclipse.jst.pagedesigner.dom.IDOMPosition;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMText;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * This class helps location insertion position to inside correct body or doc
 * prefix. NOTE: this class only doing limited support on doc level position
 * validation. Element specific position validation will be done in other
 * places.
 * 
 * @author mengbo
 */
public class BodyHelper {
	// bit flags used for child skipping.
	/**
	 * Bit flag for empty text node
	 */
	public static final int EMPTY_TEXT = 1;

	/**
	 * Bit flag for comment node
	 */
	public static final int COMMENT = 2;

	/**
	 * Bit flag for HEAD node
	 */
	public static final int HEADER = 3;

	/**
	 * 
	 * @param child
	 * @return boolean
	 */
	private static boolean isSkippableChild(Node parent, Node child, int flag) {
		if ((flag & COMMENT) != 0 && child.getNodeType() == Node.COMMENT_NODE)
			return true;
		if ((flag & EMPTY_TEXT) != 0 && child instanceof IDOMText
				&& ((IDOMText) child).isElementContentWhitespace())
			return true;

		if ((flag & HEADER) != 0 && child.getNodeType() == Node.ELEMENT_NODE) {
			String uri = CMUtil.getElementNamespaceURI((Element) child);
			IBodyInfo parentInfo = getBodyInfo((IDOMNode) parent);
			if (parentInfo != null
					&& parentInfo.isBodyHeader((IDOMNode) parent, uri,
							((Element) child).getLocalName()))
				return true;
		}
		return false;
	}

	/**
	 * check whether uri/tag should be header of any body container that is
	 * ancester of the start node.
	 * 
	 * @param start
	 * @param uri
	 * @param tag
	 * @return IDOMNode
	 */
	public static IDOMNode findHeaderContainer(IDOMNode start, String uri,
			String tag) {
		while (start != null) {
			IBodyInfo designInfo = getBodyInfo(start);
			if (designInfo != null && designInfo.isBodyContainer(start)) {
				if (designInfo.isBodyHeader(start, uri, tag))
					return start;
			}
			start = (IDOMNode) start.getParentNode();
		}
		return null;
	}

	/**
	 * find the closest body insertion point, to make it as deep as possible.
	 * (Move into as more body as possible)
	 * @param position 
	 * @return IDOMPosition
	 */
	public static IDOMPosition findBodyInsertLocation(IDOMPosition position) {
		// forward first.
		Node reference = position.getNextSiblingNode();
		Node container = position.getContainerNode();
		while (reference != null) {
			IBodyInfo info = getBodyInfo((IDOMNode) reference);
			if (info != null && info.isBodyContainer((IDOMNode) reference)) {
				// good, we find a body!
				position = new DOMPosition(reference, 0);
				return findBodyInsertLocation(position);
			}
			if (isSkippableChild(container, reference, EMPTY_TEXT | COMMENT
					| HEADER)) {
				reference = reference.getNextSibling();
				continue;
			}
            break;
		}

		// backward
		reference = position.getPreviousSiblingNode();
		while (reference != null) {
			IBodyInfo info = getBodyInfo((IDOMNode) reference);
			if (info != null && info.isBodyContainer((IDOMNode) reference)) {
				// good, we find a body!
				position = new DOMPosition(reference, reference.getChildNodes()
						.getLength());
				return findBodyInsertLocation(position);
			}
			// XXX: not skip header here. So if there is some header with wrong
			// location, we will respect user.
			if (isSkippableChild(container, reference, EMPTY_TEXT | COMMENT)) {
				reference = reference.getPreviousSibling();
				continue;
			}
            break;
		}

		// not find any body at same level as the insertion point.
		return position;
	}

	/**
	 * The element type identified by "uri" and "tag" is going to be inserted
	 * into the document. This method is used to adjust the insert position so
	 * it can be put into correct body or header section.
	 * @param uri 
	 * @param tag 
	 * @param position 
	 * @return IDOMPosition
	 * 
	 */
	public static IDOMPosition adjustInsertPosition(String uri, String tag,
			IDOMPosition position) {
		IDOMNode parent = (IDOMNode) position.getContainerNode();
		IBodyInfo designInfo = getBodyInfo(parent);
		if (designInfo == null) {
			return position; // should not happen.
		}

		IDOMNode headerContainer = findHeaderContainer(parent, uri, tag);

		if (headerContainer == null) {
			// the new node is not header.
			if (shouldIgnoreAdjust(uri, tag)) {
				return position;
			}

			// new node is not body header. So should place inside the inner most
			// body.
			if (!designInfo.isBodyContainer(parent)) {
				return position; // it's parent is not body, so we suggest
				// it's parent already correctly located, and respect user's
				// choice.
			}

			// ok, we are inside some body, but we don't know whether we are in
			// the inner most body.
			// try to find a body container at same level and see whether we can
			// move into that body.
			return findBodyInsertLocation(position);
		}
        // good, we find a body container and the new node should be header
        // of it.
        Node child = headerContainer.getFirstChild();

        // if parent is different from headerContainer, then
        // child!=referenceHolder[0] will always be true
        while (child != null) // && child != refNode)
        {
        	Comparator comp = NodeLocationComparator.getInstance();
        	// Currently the comparator deels with tags like taglib and
        	// loadbundle particularly, comparasion result 0
        	// means it didn't compare the tags.
        	if (comp.compare(child, tag) < 0
        			|| (comp.compare(child, tag) == 0 && isSkippableChild(
        					headerContainer, child, COMMENT | EMPTY_TEXT
        							| HEADER))) {
        		child = child.getNextSibling();
        	} else {
        		break;
        	}
        }
        if (child != null) {
        	return new DOMRefPosition(child, false);
        }
        return new DOMPosition(parent, parent.getChildNodes()
        		.getLength());
	}

	/**
	 * Find the position to insert a header element into the specified parent.
	 * 
	 * @param uri
	 * @param tag
	 * @param parent
	 * @param ref 
	 */
	public static void findHeaderInsertPosition(String uri, String tag,
			Node parent, Node[] ref) {
		Node child = parent.getFirstChild();
		while (child != null) {
			Comparator comp = NodeLocationComparator.getInstance();
			if (comp.compare(child, tag) < 0
					|| (comp.compare(child, tag) == 0 && isSkippableChild(
							parent, child, COMMENT | EMPTY_TEXT | HEADER))) {
				child = child.getNextSibling();
			} else {
				break;
			}
		}
		ref[0] = child;
		return;
	}

	/**
	 * @param position
	 * @param body
	 * @param defaultPrefix
	 * @return the new dom position based on the insert.  May return null if
	 * insert fails.
	 */
	public static IDOMPosition insertBody(IDOMPosition position, QName body,
			String defaultPrefix) {
		IBodyInfo bodyInfo = getBodyInfo((IDOMNode) position.getContainerNode());

		Node node = position.getContainerNode();
		final Node originalContainer = node;
		final Node nextSibling = position.getNextSiblingNode();

		// create the body element first.
		Document ownerDoc;
		if (node instanceof Document) {
			ownerDoc = (Document) node;
		} else {
			ownerDoc = node.getOwnerDocument();
		}
		if (ownerDoc == null) {
			return null; // should not happen
		}

		final String prefix = JSPUtil.getOrCreatePrefix(((IDOMNode) node).getModel(),
				body.getNamespaceURI(), defaultPrefix);
		final Element ele = ownerDoc.createElement((prefix == null ? ""
				: (prefix + ":"))
				+ body.getLocalPart());

		// need to find out the insertion point
		while (node instanceof IDOMNode) {
			if (bodyInfo.isBodyContainer((IDOMNode) node)) {
				// ok, node is a body container.
				// we could create the new node as child of node and move all
				// node's none header children
				// as children of the new node.

				NodeList nl = node.getChildNodes();
				ArrayList list = new ArrayList();
				for (int i = 0; i < nl.getLength(); i++) {
					Node child = nl.item(i);
					if (isSkippableChild(node, child, HEADER | COMMENT
							| EMPTY_TEXT)) {
						continue;
					}
					list.add(nl.item(i));
				}
				for (int i = 0; i < list.size(); i++) {
					ele.appendChild((Node) list.get(i));
				}
				node.appendChild(ele);

				if (node == originalContainer) {
					if (nextSibling == null) {
						return new DOMRefPosition2(ele, true);
					} else if (nextSibling.getParentNode() == ele) {
						// next sibling is not in header part
						return new DOMRefPosition(nextSibling, false);
					} else {
						return new DOMPosition(ele, 0);
					}
				}
                return position;
			}
			node = node.getParentNode();
		}
		// should not happen, because document and documentfragment node will
		// always be body node
		// so if reach here, means the position is not in document.
		return null;
	}

	/**
	 * For certain special tags, do not following the "header"/"body" separation
	 * and can't fit into the relocation process.
	 * 
	 * @param uri
	 * @param tag
	 * @return true if tag is an element that should be moved in response to 
	 * body insert.
	 */
	public static boolean shouldIgnoreAdjust(String uri, String tag) {
		// FIXME:
		return (ITLDConstants.URI_HTML.equalsIgnoreCase(uri) && "script"
				.equalsIgnoreCase(tag))
				|| (ITLDConstants.URI_JSP.equals(uri));
	}

	/**
	 * @param node
	 * @return the body info corresponding to node (should we use a node adapter?)
	 */
	public static IBodyInfo getBodyInfo(IDOMNode node) {
		// TODO: in the future, when bodyinfo is no longer singleton, we'll use
		// adapter mechanism.
		return BodyInfo.getInstance();
	}
}
