package org.eclipse.wst.html.ui.internal.hyperlink;

import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.hyperlink.IHyperlink;
import org.eclipse.jface.text.hyperlink.IHyperlinkDetector;
import org.eclipse.jface.text.hyperlink.URLHyperlink;
import org.eclipse.wst.common.contentmodel.CMAttributeDeclaration;
import org.eclipse.wst.common.contentmodel.CMDataType;
import org.eclipse.wst.common.contentmodel.CMElementDeclaration;
import org.eclipse.wst.common.contentmodel.modelquery.ModelQuery;
import org.eclipse.wst.common.contentmodel.util.DOMNamespaceHelper;
import org.eclipse.wst.common.uriresolver.URIResolverPlugin;
import org.eclipse.wst.sse.core.IStructuredModel;
import org.eclipse.wst.sse.core.IndexedRegion;
import org.eclipse.wst.sse.core.StructuredModelManager;
import org.eclipse.wst.sse.core.util.StringUtils;
import org.eclipse.wst.xml.core.document.XMLAttr;
import org.eclipse.wst.xml.core.document.XMLNode;
import org.eclipse.wst.xml.core.modelquery.ModelQueryUtil;
import org.w3c.dom.Attr;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;

/**
 * Detects hyperlinks in XML tags. Includes detection in DOCTYPE and attribute
 * values. Resolves references to schemas, dtds, etc using the Common URI
 * Resolver.
 * 
 */
class XMLHyperlinkDetector implements IHyperlinkDetector {
	// copies of this class exist in:
	// org.eclipse.wst.xml.ui.internal.hyperlink
	// org.eclipse.wst.html.ui.internal.hyperlink
	// org.eclipse.jst.jsp.ui.internal.hyperlink
	
	private final String NO_NAMESPACE_SCHEMA_LOCATION = "noNamespaceSchemaLocation"; //$NON-NLS-1$
	private final String SCHEMA_LOCATION = "schemaLocation"; //$NON-NLS-1$
	private final String XMLNS = "xmlns"; //$NON-NLS-1$
	private final String XSI_NAMESPACE_URI = "http://www.w3.org/2001/XMLSchema-instance"; //$NON-NLS-1$
	private final String HTTP_PROTOCOL = "http://";//$NON-NLS-1$

	public IHyperlink[] detectHyperlinks(ITextViewer textViewer, IRegion region, boolean canShowMultipleHyperlinks) {
		// for now, only capable of creating 1 hyperlink
		List hyperlinks = new ArrayList(0);

		if (region != null && textViewer != null) {
			IDocument document = textViewer.getDocument();
			Node currentNode = getCurrentNode(document, region.getOffset());
			if (currentNode != null) {
				String uriString = null;
				if (currentNode.getNodeType() == Node.DOCUMENT_TYPE_NODE) {
					// doctype nodes
					uriString = getURIString(currentNode, document);
				}
				else if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
					// element nodes
					Attr currentAttr = getCurrentAttrNode(currentNode, region.getOffset());
					if (currentAttr != null) {
						// try to find link for current attribute
						// resolve attribute value
						uriString = getURIString(currentAttr, document);
						// verify validity of uri string
						if (!isValidURI(uriString))
							// reset current attribute
							currentAttr = null;
					}
					if (currentAttr == null) {
						// try to find a linkable attribute within element
						currentAttr = getLinkableAttr((Element) currentNode);
						if (currentAttr != null) {
							uriString = getURIString(currentAttr, document);
						}
					}
					currentNode = currentAttr;
				}
				// try to create hyperlink from information gathered
				if (uriString != null && currentNode != null && isValidURI(uriString)) {
					IRegion hyperlinkRegion = getHyperlinkRegion(currentNode);
					IHyperlink hyperlink = createHyperlink(uriString, hyperlinkRegion, document, currentNode);
					if (hyperlink != null) {
						hyperlinks.add(hyperlink);
					}
				}
			}
		}
		if (hyperlinks.size() == 0)
			return null;
		return (IHyperlink[]) hyperlinks.toArray(new IHyperlink[0]);
	}

	/**
	 * Create the appropriate hyperlink
	 * 
	 * @param uriString
	 * @param hyperlinkRegion
	 * @return IHyperlink
	 */
	private IHyperlink createHyperlink(String uriString, IRegion hyperlinkRegion, IDocument document, Node node) {
		IHyperlink link = null;

		if (uriString != null) {
			String temp = uriString.toLowerCase();
			if (temp.startsWith(HTTP_PROTOCOL)) {
				// this is a URLHyperlink since this is a web address
				link = new URLHyperlink(hyperlinkRegion, uriString);
			}
			else {
				// try to locate the file in the workspace
				IFile file = getFile(uriString);
				if (file != null && file.exists()) {
					// this is a WorkspaceFileHyperlink since file exists in
					// workspace
					link = new WorkspaceFileHyperlink(hyperlinkRegion, file);
				}
				else {
					// this is an ExternalFileHyperlink since file does not
					// exist
					// in workspace
					File externalFile = new File(uriString);
					link = new ExternalFileHyperlink(hyperlinkRegion, externalFile);
				}
			}
		}

		return link;
	}

	private IRegion getHyperlinkRegion(Node node) {
		IRegion hyperRegion = null;

		if (node != null) {
			short nodeType = node.getNodeType();
			if (nodeType == Node.DOCUMENT_TYPE_NODE) {
				// handle doc type node
				XMLNode docNode = (XMLNode) node;
				hyperRegion = new Region(docNode.getStartOffset(), docNode.getEndOffset() - docNode.getStartOffset());
			}
			else if (nodeType == Node.ATTRIBUTE_NODE) {
				// handle attribute nodes
				XMLAttr att = (XMLAttr) node;
				// do not include quotes in attribute value region
				int regOffset = att.getValueRegionStartOffset();
				int regLength = att.getValueRegion().getTextLength();
				String attValue = att.getValueRegionText();
				if (StringUtils.isQuoted(attValue)) {
					regOffset = ++regOffset;
					regLength = regLength - 2;
				}
				hyperRegion = new Region(regOffset, regLength);
			}
		}
		return hyperRegion;
	}

	/**
	 * Returns the URI string
	 * 
	 * @param node -
	 *            assumes not null
	 */
	protected String getURIString(Node node, IDocument document) {
		String resolvedURI = null;
		// need the base location, publicId, and systemId for URIResolver
		String baseLoc = null;
		String publicId = null;
		String systemId = null;

		short nodeType = node.getNodeType();
		// handle doc type node
		if (nodeType == Node.DOCUMENT_TYPE_NODE) {
			baseLoc = getBaseLocation(document);
			publicId = ((DocumentType) node).getPublicId();
			systemId = ((DocumentType) node).getSystemId();
		}
		else if (nodeType == Node.ATTRIBUTE_NODE) {
			// handle attribute node
			Attr attrNode = (Attr) node;
			baseLoc = getBaseLocation(document);
			String attrName = attrNode.getName();
			String attrValue = attrNode.getValue();
			attrValue = StringUtils.strip(attrValue);

			// handle schemaLocation attribute
			String prefix = DOMNamespaceHelper.getPrefix(attrName);
			String unprefixedName = DOMNamespaceHelper.getUnprefixedName(attrName);
			if ((XMLNS.equals(prefix)) || (XMLNS.equals(unprefixedName))) {
				publicId = attrValue;
				systemId = getLocationHint(attrNode.getOwnerElement(), publicId);
			}
			else if ((XSI_NAMESPACE_URI.equals(DOMNamespaceHelper.getNamespaceURI(attrNode))) && (SCHEMA_LOCATION.equals(unprefixedName))) {
				// for now just use the first pair
				// need to look into being more precise
				StringTokenizer st = new StringTokenizer(attrValue);
				publicId = st.hasMoreTokens() ? st.nextToken() : null;
				systemId = st.hasMoreTokens() ? st.nextToken() : null;
				// else check if xmlns publicId = value
			}
			else {
				systemId = attrValue;
			}
		}

		resolvedURI = resolveURI(baseLoc, publicId, systemId);
		return resolvedURI;
	}

	/**
	 * Returns an IFile from the given uri if possible, null if cannot find
	 * file from uri.
	 * 
	 * @param fileString
	 *            file system path
	 * @return returns IFile if fileString exists in the workspace
	 */
	private IFile getFile(String fileString) {
		IFile file = null;

		if (fileString != null) {
			IFile[] files = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocation(new Path(fileString));
			for (int i = 0; i < files.length && file == null; i++)
				if (files[i].exists())
					file = files[i];
		}

		return file;
	}

	/**
	 * Checks to see if the given attribute is openable. Attribute is openable
	 * if it is a namespace declaration attribute or if the attribute value is
	 * of type URI.
	 * 
	 * @param attr
	 *            cannot be null
	 * @param cmElement
	 *            CMElementDeclaration associated with the attribute (can be
	 *            null)
	 * @return true if this attribute is "openOn-able" false otherwise
	 */
	private boolean isLinkableAttr(Attr attr, CMElementDeclaration cmElement) {
		String attrName = attr.getName();
		String prefix = DOMNamespaceHelper.getPrefix(attrName);
		String unprefixedName = DOMNamespaceHelper.getUnprefixedName(attrName);
		// determine if attribute is namespace declaration
		if ((XMLNS.equals(prefix)) || (XMLNS.equals(unprefixedName)))
			return true;

		// determine if attribute contains schema location
		if ((XSI_NAMESPACE_URI.equals(DOMNamespaceHelper.getNamespaceURI(attr))) && ((SCHEMA_LOCATION.equals(unprefixedName)) || (NO_NAMESPACE_SCHEMA_LOCATION.equals(unprefixedName))))
			return true;

		// determine if attribute value is of type URI
		if (cmElement != null) {
			CMAttributeDeclaration attrDecl = (CMAttributeDeclaration) cmElement.getAttributes().getNamedItem(attrName);
			if ((attrDecl != null) && (attrDecl.getAttrType() != null) && (CMDataType.URI.equals(attrDecl.getAttrType().getDataTypeName()))) {
				return true;
			}
		}
		return false;
	}

	/**
	 * Attempts to find an attribute within element that is openable.
	 * 
	 * @param element -
	 *            cannot be null
	 * @return Attr attribute that can be used for open on, null if no
	 *         attribute could be found
	 */
	private Attr getLinkableAttr(Element element) {
		CMElementDeclaration ed = getCMElementDeclaration(element);
		// get the list of attributes for this node
		NamedNodeMap attrs = element.getAttributes();
		for (int i = 0; i < attrs.getLength(); ++i) {
			// check if this attribute is "openOn-able"
			Attr att = (Attr) attrs.item(i);
			if (isLinkableAttr(att, ed)) {
				return att;
			}
		}
		return null;
	}

	/**
	 * Get the CMElementDeclaration for an element
	 * 
	 * @param element
	 * @return CMElementDeclaration
	 */
	private CMElementDeclaration getCMElementDeclaration(Element element) {
		CMElementDeclaration ed = null;

		ModelQuery mq = ModelQueryUtil.getModelQuery(element.getOwnerDocument());
		if (mq != null) {
			ed = mq.getCMElementDeclaration(element);
		}
		return ed;
	}

	/**
	 * Returns the attribute node within node at offset
	 * 
	 * @param node
	 * @param offset
	 * @return Attr
	 */
	private Attr getCurrentAttrNode(Node node, int offset) {
		if ((node instanceof IndexedRegion) && ((IndexedRegion) node).contains(offset) && (node.hasAttributes())) {
			NamedNodeMap attrs = node.getAttributes();
			// go through each attribute in node and if attribute contains
			// offset, return that attribute
			for (int i = 0; i < attrs.getLength(); ++i) {
				// assumption that if parent node is of type IndexedRegion,
				// then its attributes will also be of type IndexedRegion
				IndexedRegion attRegion = (IndexedRegion) attrs.item(i);
				if (attRegion.contains(offset)) {
					return (Attr) attrs.item(i);
				}
			}
		}
		return null;
	}

	/**
	 * Returns the node the cursor is currently on in the document. null if no
	 * node is selected
	 * 
	 * @param offset
	 * @return Node either element, doctype, text, or null
	 */
	private Node getCurrentNode(IDocument document, int offset) {
		// get the current node at the offset (returns either: element,
		// doctype, text)
		IndexedRegion inode = null;
		IStructuredModel sModel = null;
		try {
			sModel = StructuredModelManager.getModelManager().getExistingModelForRead(document);
			inode = sModel.getIndexedRegion(offset);
			if (inode == null)
				inode = sModel.getIndexedRegion(offset - 1);
		}
		finally {
			if (sModel != null)
				sModel.releaseFromRead();
		}

		if (inode instanceof Node) {
			return (Node) inode;
		}
		return null;
	}

	/**
	 * Get the base location from the current model (local file system)
	 */
	private String getBaseLocation(IDocument document) {
		String baseLoc = null;

		// get the base location from the current model
		IStructuredModel sModel = null;
		try {
			sModel = StructuredModelManager.getModelManager().getExistingModelForRead(document);
			if (sModel != null) {
				IPath location = new Path(sModel.getBaseLocation());
				if (location.toFile().exists()) {
					baseLoc = location.toString();
				}
				else {
					baseLoc = ResourcesPlugin.getWorkspace().getRoot().getLocation().append(sModel.getBaseLocation()).toString();
				}
			}
		}
		finally {
			if (sModel != null) {
				sModel.releaseFromRead();
			}
		}
		return baseLoc;
	}

	/**
	 * Checks whether the given uriString is really pointing to a file
	 * 
	 * @param uriString
	 * @return boolean
	 */
	private boolean isValidURI(String uriString) {
		// try to create a uri
		if (uriString != null) {
			URI uri = null;
			try {
				uri = new URI(uriString);
			}
			catch (URISyntaxException e) {
				// it is okay that this is not a uri
			}

			File file = null;
			// create a file from uri if it's not an absolute uri (ex:
			// http://myfile)
			if (uri != null && !uri.isAbsolute())
				file = new File(uri);
			else
				// create a file from uriString which is an absolute path (ex:
				// d:/myfile)
				file = new File(uriString);
			// check if the newly created file exists
			return file.exists();
		}
		return false;
	}

	/**
	 * Resolves the given URI information
	 * 
	 * @param baseLocation
	 * @param publicId
	 * @param systemId
	 * @return String resolved uri.
	 */
	private String resolveURI(String baseLocation, String publicId, String systemId) {
		// dont resolve if there's nothing to resolve
		if ((baseLocation == null) && (publicId == null) && (systemId == null))
			return null;
		return URIResolverPlugin.createResolver().resolve(baseLocation, publicId, systemId);
	}

	/**
	 * Find the location hint for the given namespaceURI if it exists
	 * 
	 * @param elementNode -
	 *            cannot be null
	 * @param namespaceURI -
	 *            cannot be null
	 * @return location hint (systemId) if it was found, null otherwise
	 */
	private String getLocationHint(Element elementNode, String namespaceURI) {
		Attr schemaLocNode = elementNode.getAttributeNodeNS(XSI_NAMESPACE_URI, SCHEMA_LOCATION);
		if (schemaLocNode != null) {
			StringTokenizer st = new StringTokenizer(schemaLocNode.getValue());
			while (st.hasMoreTokens()) {
				String publicId = st.hasMoreTokens() ? st.nextToken() : null;
				String systemId = st.hasMoreTokens() ? st.nextToken() : null;
				// found location hint
				if (namespaceURI.equalsIgnoreCase(publicId))
					return systemId;
			}
		}
		return null;
	}
}
