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

import org.eclipse.gef.EditPart;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.TextSelection;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jst.pagedesigner.dom.DOMPosition;
import org.eclipse.jst.pagedesigner.dom.DOMPositionHelper;
import org.eclipse.jst.pagedesigner.dom.DOMRefPosition;
import org.eclipse.jst.pagedesigner.dom.DOMRefPosition2;
import org.eclipse.jst.pagedesigner.dom.DOMUtil;
import org.eclipse.jst.pagedesigner.dom.EditValidateUtil;
import org.eclipse.jst.pagedesigner.dom.IDOMPosition;
import org.eclipse.jst.pagedesigner.parts.NodeEditPart;
import org.eclipse.jst.pagedesigner.viewer.DesignPosition;
import org.eclipse.jst.pagedesigner.viewer.DesignRange;
import org.eclipse.jst.pagedesigner.viewer.IHTMLGraphicalViewer;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
import org.w3c.dom.CharacterData;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.Text;

/**
 * @author mengbo
 * @version 1.5
 */
public class SelectionHelper {
	/**
	 * convert the text selection to a Node. Will use the start offset of the
	 * text selection.
	 * 
	 * @param model
	 * @param textSel
	 * @return
	 */
	public static Node toNode(IStructuredModel model, ITextSelection textSel) {
		// FIXME: currently always normalize to a single node. should also
		// consider change into DesignRange
		// on text selection, find the appropriate Node
		Object inode = model.getIndexedRegion(textSel.getOffset());
		if (inode instanceof Node) {
			return (Node) inode;
		} else {
			return null;
		}
	}

	/**
	 * convert a structured selection of NodeEditPart or Node into the first
	 * node.
	 * 
	 * @param selection
	 * @return
	 */
	public static Node toNode(IStructuredSelection selection) {
		if (selection.isEmpty()) {
			return null;
		}
		Object first = selection.getFirstElement();
		if (first instanceof Node) {
			return (Node) first;
		} else if (first instanceof NodeEditPart) {
			return ((NodeEditPart) first).getIDOMNode();
		} else {
			return null;
		}
	}

	/**
	 * convert a DesignRange into a single node.
	 * 
	 * @param range
	 * @return
	 */
	public static Node toNode(DesignRange range) {
		if (range.isValid()) {
			Node node1 = range.getStartPosition().getContainerNode();
			Node node2 = range.getEndPosition().getContainerNode();
			return DOMUtil.findCommonAncester(node1, node2);
		} else {
			return null;
		}
	}

	/**
	 * @param model
	 * @param region
	 *            if null, then will calculate it using offset.
	 * @param offset
	 *            offset in source.
	 * @return
	 */
	public static IDOMPosition toDOMPosition(IDOMModel model,
			IndexedRegion region, int offset) {
		if (region == null) {
			region = model.getIndexedRegion(offset);
		}
		if (region == null && offset > 0) {
			// in case this is at end of file.
			offset = offset - 1;
			region = model.getIndexedRegion(offset);
			if (region != null) {
				if (region.getEndOffset() >= offset + 1) {
					offset += 1; // restore offset.
				}
			}
		}
		if (region == null) {
			return new DOMPosition(model.getDocument(), 0);
		}
		IDOMNode node = (IDOMNode) region;
		int start = node.getStartOffset();
		if (offset <= start) {
			return new DOMRefPosition(node, false);
		}
		int end = node.getEndOffset();
		if (offset >= end) {
			return new DOMRefPosition(node, true);
		}
		if (node instanceof CharacterData) {
			String data = ((CharacterData) node).getData();
			String source = node.getSource();
			if (data.equals(source)) {
				return new DOMPosition(node, offset - start);
			}
			IStructuredDocumentRegion r = node
					.getFirstStructuredDocumentRegion();
			int countedData = 0;
			int offsetInNode = offset - start;
			while (r != null) {
				if (DOMRegionContext.XML_CHAR_REFERENCE.equals(r.getType())
						|| DOMRegionContext.XML_ENTITY_REFERENCE.equals(r
								.getType())) {
					countedData += 1; // FIXME: what if the entity reference's
					// corresponding data is more than 1
					// char?
					// where can we get that information?
					if (r.getEnd() >= offset) {
						return new DOMPosition(node, countedData);
					}
				} else {
					if (r.getEnd() >= offset) {
						return new DOMPosition(node, countedData + offset
								- r.getStart());
					}
					countedData += r.getLength();
				}
				r = r.getNext();
			}
			return new DOMRefPosition(node, true);
		} else if (node instanceof Element) {
			CMElementDeclaration cm = CMUtil
					.getElementDeclaration((Element) node);
			if (cm != null && cm.getContentType() == CMElementDeclaration.EMPTY) {
				// this node can't have children.
				return new DOMRefPosition(node, true);
			}
			IStructuredDocumentRegion startRegion = node
					.getStartStructuredDocumentRegion();
			if (startRegion == null) {
				return new DOMRefPosition(node, true);
			} else {
				int startRegionEnd = node.getStartStructuredDocumentRegion()
						.getEnd();
				if (offset <= startRegionEnd) {
					// it is in the start tag region. So put position at first
					// child position.
					return new DOMRefPosition2(node, false);
				} else {
					return new DOMRefPosition2(node, true);
				}
			}
		} else {
			return new DOMRefPosition(node, true);
		}
		// XXX: the implementation in EditModelQuery seemed to be very complex.
		// Need revisit that
		// and refactor the implementation to this class later. (lium)
	}

	/**
	 * Give a text selection with offset and length, convert it into a Designer
	 * selection (IStrucuturedSelection of editpart or DesignerRange). If the
	 * text selection include just a single element node, we'll create a
	 * IStructuredSelection, otherwise we'll create a DesignerRange.
	 * 
	 * @param graphicViewer
	 * @param offset
	 * @param length
	 */
	public static ISelection convertToDesignerSelection(
			IHTMLGraphicalViewer graphicViewer, int offset, int length) {
		IDOMModel model = graphicViewer.getModel();
		IndexedRegion region1 = model.getIndexedRegion(offset);
		IndexedRegion region2 = model.getIndexedRegion(offset + length);
		IDOMNode node1 = (IDOMNode) region1;

		if (node1 == null) {
			IDOMPosition endOfDoc = new DOMRefPosition2(model.getDocument(),
					true);
			DesignPosition p = DOMPositionHelper.toDesignPosition(endOfDoc);
			return new DesignRange(p, p);
		}

		if ((region1 == region2 || node1.getEndOffset() == offset + length)
				&& !(node1 instanceof Text)) {
			// ok, we selected a single node.
			EditPart part = (EditPart) node1.getAdapterFor(EditPart.class);
			if (part != null) {
				return new StructuredSelection(part);
			}
		}

		// when we reach here, we'll create a DesignerRange
		IDOMPosition position1 = toDOMPosition(model, region1, offset);
		IDOMPosition position2 = (length == 0 ? position1 : toDOMPosition(
				model, region2, offset + length));

		if (position1 == null || position2 == null) {
			return new DesignRange(null, null);
		}
		DesignPosition p1 = DOMPositionHelper.toDesignPosition(position1);
		DesignPosition p2 = (length == 0 ? p1 : DOMPositionHelper
				.toDesignPosition(position2));
		if (p1 == null || p2 == null) {
			return new DesignRange(null, null);
		}

		return new DesignRange(p1, p2);

	}

	/**
	 * convert a IDOMPosition into index in the source.
	 * 
	 * @param p
	 * @return
	 */
	private static int getIndexedRegionLocation(IDOMPosition p) {
		if (!EditValidateUtil.validPosition(p)) {
			return 0;
		}

		IDOMNode parent = (IDOMNode) p.getContainerNode();
		if (p.isText()) {
			String text = ((CharacterData) parent).getData();
			String source = parent.getSource();
			if (text.length() == source.length()) {
				// no entity reference.
				return parent.getStartOffset() + p.getOffset();
			}
			// CR404708. Need to handle entity reference in the text.
			int offset = p.getOffset();
			int counted = 0;
			IStructuredDocumentRegion r = parent
					.getFirstStructuredDocumentRegion();
			while (r != null && counted < offset) {
				if (DOMRegionContext.XML_CHAR_REFERENCE.equals(r.getType())
						|| DOMRegionContext.XML_ENTITY_REFERENCE.equals(r
								.getType())) {
					counted++;
					if (counted >= offset) {
						return r.getEndOffset();
					}
				} else {
					int length = r.getLength();
					if (counted + length >= offset) {
						return r.getStartOffset() + offset - counted;
					}
					counted += length;
				}
				r = r.getNext();
			}
			return parent.getStartOffset() + p.getOffset();
		} else {
			IDOMNode previous = (IDOMNode) p.getPreviousSiblingNode();
			if (previous != null) {
				return previous.getEndOffset();
			}
			IDOMNode next = (IDOMNode) p.getNextSiblingNode();
			if (next != null) {
				return next.getStartOffset();
			}
			IStructuredDocumentRegion r = parent
					.getStartStructuredDocumentRegion();
			if (r != null) {
				return r.getEnd();
			} else {
				// r == null normally means the parent is the document node.
				return parent.getEndOffset();
			}
		}
	}

	/**
	 * convert design selection of structured selection of NodeEditPart into
	 * structured selection of Node
	 * 
	 * @param sel
	 * @return
	 */
	public static IStructuredSelection convertFromDesignSelection(
			IStructuredSelection sel) {
		List list = sel.toList();
		if (list != null) {
			List result = new ArrayList(list.size());
			for (int i = 0, size = list.size(); i < size; i++) {
				NodeEditPart part = (NodeEditPart) list.get(i);
				result.add(part.getIDOMNode());
			}
			return new StructuredSelection(result);
		} else {
			return new StructuredSelection();
		}
	}

	/**
	 * 
	 * @param selection
	 *            selection from designer, could be IStructuredSelection of
	 *            NodeEditPart, or DesignRange.
	 * @return
	 */
	public static ITextSelection convertFromDesignSelection(DesignRange range) {
		if (range.isValid()) {
			IDOMPosition start = DOMPositionHelper.toDOMPosition(range
					.getStartPosition());
			IDOMPosition end = DOMPositionHelper.toDOMPosition(range
					.getEndPosition());
			// We should not encounter invalid position.
			if (EditValidateUtil.validPosition(start)
					&& EditValidateUtil.validPosition(end)) {
				int offset = getIndexedRegionLocation(start);
				int endoffset = getIndexedRegionLocation(end);
				if (offset > endoffset) {
					int temp = offset;
					offset = endoffset;
					endoffset = temp;
				}
				return new TextSelection(offset, endoffset - offset);
			} else {
				return new TextSelection(0, 0);
			}
		} else {
			return new TextSelection(0, 0);
		}
	}

	public static ITextSelection convertFromDesignSelectionToTextSelection(
			ISelection selection) {
		if (selection instanceof IStructuredSelection) {
			IStructuredSelection nodes = convertFromDesignSelection((IStructuredSelection) selection);
			IDOMNode node = (IDOMNode) nodes.getFirstElement();
			if (node != null && node.getNodeType() != Node.DOCUMENT_NODE) {
				return new TextSelection(node.getStartOffset(), node
						.getEndOffset()
						- node.getStartOffset());
			} else {
				return new TextSelection(0, 0);
			}
		} else if (selection instanceof DesignRange) {
			return convertFromDesignSelection((DesignRange) selection);
		} else {
			return new TextSelection(0, 0);
		}
	}
}
