package org.eclipse.wst.jsdt.web.core.internal.java;

import java.util.Iterator;

import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList;
import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;

public class NodeHelper {

	protected static final char DOUBLE_QUOTE_CHAR = '\"';

	protected static final String DOUBLE_QUOTE_ENTITY = "&quot;"; //$NON-NLS-1$

	protected static final char SINGLE_QUOTE_CHAR = '\'';

	protected static final String SINGLE_QUOTE_ENTITY = "&#039;"; //$NON-NLS-1$

	public static boolean isInArray(String StringArray[], String text) {
		if (StringArray == null || text == null) {
			return false;
		}

		for (int i = 0; i < StringArray.length; i++) {
			if (StringArray[i].equalsIgnoreCase(text.trim())) {
				return true;
			}
		}
		return false;
	}

	public static boolean isQuoted(String string) {
		if ((string == null) || (string.length() < 2)) {
			return false;
		}

		int lastIndex = string.length() - 1;
		char firstChar = string.charAt(0);
		char lastChar = string.charAt(lastIndex);

		return (((firstChar == NodeHelper.SINGLE_QUOTE_CHAR) && (lastChar == NodeHelper.SINGLE_QUOTE_CHAR)) || ((firstChar == NodeHelper.DOUBLE_QUOTE_CHAR) && (lastChar == NodeHelper.DOUBLE_QUOTE_CHAR)));
	}

	protected final IStructuredDocumentRegion region;

	public NodeHelper(IStructuredDocumentRegion region) {
		this.region = region;
	}

	public boolean attrEquals(String attribute, String value) {
		return (new String(getAttributeValue(attribute))).equalsIgnoreCase(value);
	}

	public String AttrToString() {
		if (region == null) {
			return null;
		}
		// For debuging
		ITextRegionList t = region.getRegions();
		ITextRegion r;
		Iterator regionIterator = t.iterator();
		String StructuredValue = "Tag name:" + getTagName() + "\tAttribute\tValue\n";
		while (regionIterator.hasNext()) {
			r = (ITextRegion) regionIterator.next();
			if (r.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) {
				int start = r.getStart();
				int offset = r.getTextEnd();
				StructuredValue += "\t\t" + region.getText().substring(start, offset);
				/*
				 * Theres a XML_TAG_ATTRIBUTE_EQUALS after the
				 * XML_TAG_ATTRIBUTE_NAME we have to get rid of
				 */
				if (regionIterator.hasNext()) {
					regionIterator.next();
				}
				if (regionIterator.hasNext()) {
					r = ((ITextRegion) regionIterator.next());
				}
				System.out.println("attrib type");
				if (r.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
					int valStart = r.getStart();
					int valOffset = r.getTextEnd();
					StructuredValue += "\t\t" + stripEndQuotes(region.getText().substring(valStart, valOffset)) + "\n";
				}

			}

		}
		return StructuredValue;

	}

	public boolean containsAttribute(String name[]) {
		if (name == null) {
			return false;
		}
		if (region == null) {
			return false;
		}
		ITextRegionList t = region.getRegions();
		ITextRegion r;
		Iterator regionIterator = t.iterator();
		while (regionIterator.hasNext()) {
			r = (ITextRegion) regionIterator.next();
			if (r.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) {
				int start = r.getStart();
				int offset = r.getTextEnd();
				String tagname = region.getText().substring(start, offset).trim();
				/* Attribute values aren't case sensative */
				if (NodeHelper.isInArray(name, tagname)) {
					return true;
				}
			}
		}
		return false;
	}

	public String getAttributeValue(String name) {
		if (region == null) {
			return null;
		}
		if (name == null) {
			return null;
		}
		ITextRegionList t = region.getRegions();
		ITextRegion r;
		Iterator regionIterator = t.iterator();
		while (regionIterator.hasNext()) {
			r = (ITextRegion) regionIterator.next();
			if (r.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) {
				int start = r.getStart();
				int offset = r.getTextEnd();

				String tagname = region.getText().substring(start, offset).trim();
				/*
				 * Attribute values aren't case sensative, also make sure next
				 * region is attrib value
				 */
				if (tagname.equalsIgnoreCase(name)) {
					if (regionIterator.hasNext()) {
						regionIterator.next();
					}
					if (regionIterator.hasNext()) {
						r = ((ITextRegion) regionIterator.next());
					}

					if (r.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
						int valStart = r.getStart();
						int valOffset = r.getTextEnd();
						return stripEndQuotes(region.getText().substring(valStart, valOffset));
					}
				}
			}

		}
		return null;
	}

	public String getElementAsFlatString() {
		/*
		 * Returns a full string of this element minus and 'illegal' characters
		 * (usefull for identifying the HTML element in a generic JS function)
		 */
		if (region == null) {
			return null;
		}

		String fullRegionText = region.getFullText();

		if (fullRegionText == null) {
			return null;
		}

		return fullRegionText.replaceAll("[^a-zA-Z0-9]", "");
	}

	public String getTagName() {
		if (region == null) {
			return null;
		}
		ITextRegionList t = region.getRegions();
		ITextRegion r;
		Iterator regionIterator = t.iterator();
		while (regionIterator.hasNext()) {
			r = (ITextRegion) regionIterator.next();

			if (r.getType() == DOMRegionContext.XML_TAG_NAME) {
				int start = r.getStart();
				int offset = r.getTextEnd();
				return region.getText().substring(start, offset);
			}

		}

		return null;
	}

	public boolean isEndTag() {

		if (region == null) {
			return false;
		}
		ITextRegionList t = region.getRegions();
		ITextRegion r;
		Iterator regionIterator = t.iterator();
		while (regionIterator.hasNext()) {
			r = (ITextRegion) regionIterator.next();
			if (r.getType() == DOMRegionContext.XML_END_TAG_OPEN) {
				return true;
			}
		}
		return false;
	}

	public boolean isSelfClosingTag() {
		if (region == null) {
			return false;
		}

		if (region == null) {
			return false;
		}

		ITextRegionList regions = region.getRegions();
		ITextRegion r = regions.get(regions.size() - 1);
		return r.getType() == DOMRegionContext.XML_EMPTY_TAG_CLOSE;
	}

	public boolean nameEquals(String name) {
		if (region == null) {
			return false;
		}
		return (getTagName().equalsIgnoreCase(name));
	}

	public String stripEndQuotes(String text) {
		if (text == null) {
			return null;
		}
		if (NodeHelper.isQuoted(text)) {
			return text.substring(1, text.length() - 1);
		}

		return text;

	}

	@Override
	public String toString() {
		ITextRegionList t = region.getRegions();

		Iterator regionIterator = t.iterator();
		String nodeText = new String();

		while (regionIterator.hasNext()) {

			ITextRegion r = (ITextRegion) regionIterator.next();
			String nodeType = r.getType();
			nodeText += ("\tNode Type:" + nodeType + " \t\tValue:" + region.getText().substring(r.getStart(), r.getTextEnd()) + "\n");
		}
		return nodeText;
	}

}