/*******************************************************************************
 * Copyright (c) 2004 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.css.core.internal.document;



import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import com.ibm.icu.util.StringTokenizer;

import org.eclipse.wst.css.core.internal.provisional.adapters.IStyleSelectorAdapter;
import org.eclipse.wst.css.core.internal.provisional.document.ICSSSelector;
import org.eclipse.wst.css.core.internal.provisional.document.ICSSSelectorCombinator;
import org.eclipse.wst.css.core.internal.provisional.document.ICSSSelectorItem;
import org.eclipse.wst.css.core.internal.provisional.document.ICSSSimpleSelector;
import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
import org.eclipse.wst.xml.core.internal.provisional.NameValidator;
import org.w3c.dom.Element;
import org.w3c.dom.Node;


/**
 * 
 */
class CSSSelector implements ICSSSelector {

	private int fSpecificity = -1;
	private String fCachedString = null;
	private List fTokens = null;
	private List fItems = null;
	private List fParseErrors = null;
	private List fNameErrors = null;

	CSSSelector(List tokens) {
		fTokens = new ArrayList(tokens);
	}

	/**
	 * @return boolean
	 * @param obj
	 *            java.lang.Object
	 */
	public boolean equals(Object obj) {
		if (this == obj)
			return true;

		if (obj == null || this.getClass() != obj.getClass())
			return false;

		CSSSelector foreign = (CSSSelector) obj;

		// if (fSpecificity != foreign.fSpecificity) return false;

		if (getLength() != foreign.getLength())
			return false;

		for (int i = 0; i < getLength(); i++) {
			if (!getItem(i).equals(foreign.getItem(i)))
				return false;
		}

		return true;
	}

	public ICSSSelectorItem getItem(int index) {
		if (fItems == null) {
			fItems = parseSelector(fTokens);
		}
		if (fItems != null && 0 <= index && index < fItems.size()) {
			return (ICSSSelectorItem) fItems.get(index);
		}
		else {
			return null;
		}
	}

	/**
	 * @return java.util.Iterator
	 */
	public Iterator getIterator() {
		if (fItems == null) {
			fItems = parseSelector(fTokens);
		}
		return (fItems != null) ? fItems.iterator() : null;
	}

	/**
	 * @return int
	 */
	public int getLength() {
		if (fItems == null) {
			fItems = parseSelector(fTokens);
		}
		return (fItems != null) ? fItems.size() : 0;
	}

	/**
	 * @return org.w3c.dom.Element
	 */
	private Element getParentElement(Element element) {
		try {
			element = (Element) element.getParentNode();
		}
		catch (Exception ex) {
			// cast error or null pointer ...
			element = null;
		}
		return element;
	}

	/**
	 * @return org.w3c.dom.Element
	 */
	private Element getPreviousElement(Element element) {
		Element p = null;
		for (Node node = element.getPreviousSibling(); node != null; node = node.getPreviousSibling()) {
			if (node.getNodeType() == Node.ELEMENT_NODE) {
				p = (Element) node;
				break;
			}
		}
		return p;
	}

	/**
	 * Calculate a selector's specificity a = the number of ID attributes in
	 * the selector b = the number of other attributes and pseudo-classes in
	 * the selector c = the number of element names in the selector (ignore
	 * pseudo-elements) Concatenating the three numbers a-b-c (in a number
	 * system with a large base) gives the specificity.
	 * 
	 * @return int
	 */
	public int getSpecificity() {
		if (fSpecificity < 0) {
			int nIDs = 0;
			int nAttributes = 0;
			int nElements = 0;
			Iterator i = getIterator();
			while (i.hasNext()) {
				ICSSSelectorItem item = (ICSSSelectorItem) i.next();
				if (item instanceof CSSSimpleSelector) {
					CSSSimpleSelector selector = (CSSSimpleSelector) item;
					nIDs += selector.getNumOfIDs();
					nAttributes += selector.getNumOfAttributes();
					nAttributes += selector.getNumOfClasses();
					nAttributes += selector.getNumOfPseudoNames();
					if (!selector.isUniversal()) {
						nElements++;
					}
				}
			}
			fSpecificity = nIDs * 10000 + nAttributes * 100 + nElements;
		}

		return fSpecificity;
	}

	/**
	 * @return java.lang.String
	 */
	public String getString() {
		if (fCachedString == null) {
			StringBuffer buf = new StringBuffer();
			Iterator i = getIterator();
			while (i.hasNext()) {
				ICSSSelectorItem item = (ICSSSelectorItem) i.next();
				if (item instanceof CSSSelectorCombinator) {
					// If item is DESCENDANT combinator, it is just single
					// space.
					// Then, you dont have to append string..
					if (((CSSSelectorCombinator) item).getCombinatorType() != ICSSSelectorCombinator.DESCENDANT) {
						buf.append(" ");//$NON-NLS-1$
						buf.append(item.getString());
					}
					buf.append(" ");//$NON-NLS-1$
				}
				else {
					buf.append(item.getString());
				}
			}
			fCachedString = buf.toString();
		}

		return fCachedString;
	}

	/**
	 * @return boolean
	 * @param element
	 *            org.w3c.dom.Element
	 */
	public boolean match(org.w3c.dom.Element element, java.lang.String pseudoName) {
		Element target = element;
		char combinatorType = ICSSSelectorCombinator.UNKNOWN;
		Element chunkStartElement = null; // for CHILD and ADJACENT
											// combinator
		int chunkStartItem = -1; // for CHILD and ADJACENT combinator
		int numItems = getLength();
		for (int iItem = numItems - 1; iItem >= 0; iItem--) {
			// Check Selector Items
			ICSSSelectorItem item = getItem(iItem);
			if (item instanceof ICSSSimpleSelector) {
				// Simple Selector
				if (target == null)
					return false;
				if (!matchExactly((ICSSSimpleSelector) item, target, pseudoName)) {
					switch (combinatorType) {
						case ICSSSelectorCombinator.DESCENDANT :
							do {
								target = getParentElement(target);
								if (target == null)
									return false;
							}
							while (!matchExactly((ICSSSimpleSelector) item, target, pseudoName));
							break;
						case ICSSSelectorCombinator.CHILD :
						case ICSSSelectorCombinator.ADJACENT :
							if (chunkStartElement != null && chunkStartElement != element) {
								// previous conbinator must be DESCENDENT.
								// goto parent
								target = getParentElement(chunkStartElement);
								iItem = chunkStartItem + 1;
								chunkStartElement = null;
								chunkStartItem = -1;
								break;
							}
						default :
							// other combinators are not supported yet.
							return false;
					}
				}
			}
			else if (item instanceof ICSSSelectorCombinator) {
				// Combinator ( "+", ">", " ", ...)
				if (iItem == numItems - 1)
					return false; // last item is combinator

				ICSSSelectorCombinator sc = (ICSSSelectorCombinator) item;
				combinatorType = sc.getCombinatorType();
				switch (combinatorType) {
					case ICSSSelectorCombinator.DESCENDANT :
						target = getParentElement(target);
						break;
					case ICSSSelectorCombinator.CHILD :
					case ICSSSelectorCombinator.ADJACENT :
						if (chunkStartElement == null) {
							chunkStartElement = target;
							chunkStartItem = iItem + 1; // safe because this
														// is not a last item.
						}
						if (combinatorType == ICSSSelectorCombinator.CHILD) {
							target = getParentElement(target);
						}
						else {
							target = getPreviousElement(target);
						}
						break;
				}
			}
			else {
				// what is this item ???
				return false;
			}
		}
		// OK this selector maches the element.
		return true;

	}

	/**
	 * @return boolean
	 */
	private boolean matchExactly(ICSSSimpleSelector selector, Element element, String pseudoName) {
		IStyleSelectorAdapter adapter = (IStyleSelectorAdapter) ((INodeNotifier) element).getAdapterFor(IStyleSelectorAdapter.class);
		if (adapter != null) {
			return adapter.match(selector, element, pseudoName);
		}

		if (element == null)
			return false;
		int i;
		String key;

		// TODO: PseudoName

		// check tag name
		if (!selector.isUniversal() && !element.getNodeName().equals(selector.getName()))
			return false;

		// check id
		i = selector.getNumOfIDs();
		if (i > 0) {
			if (i > 1)
				return false;
			key = element.getAttribute("id");//$NON-NLS-1$
			if (key == null)
				return false;
			if (!selector.getID(0).equals(key))
				return false;
		}

		// check class
		i = selector.getNumOfClasses();
		if (i > 0) {
			key = element.getAttribute("class");//$NON-NLS-1$
			if (key == null)
				return false;
			StringTokenizer tokenizer = new StringTokenizer(key);
			for (i = i - 1; i >= 0; i--) {
				boolean ok = false;
				while (tokenizer.hasMoreTokens()) {
					if (selector.getClass(i).equals(tokenizer.nextToken())) {
						ok = true;
						break;
					}
				}
				if (!ok)
					return false;
			}
		}

		// check attributes
		for (i = selector.getNumOfAttributes() - 1; i >= 0; i--) {
			StringTokenizer tokenizer = new StringTokenizer(selector.getAttribute(i), "=~| \t\r\n\f");//$NON-NLS-1$
			int countTokens = tokenizer.countTokens();
			if (countTokens > 0) {
				String attrValue = element.getAttribute(tokenizer.nextToken());
				if (attrValue == null)
					return false;
				if (countTokens > 1) {
					String token = tokenizer.nextToken("= \t\r\n\f");//$NON-NLS-1$
					StringTokenizer attrValueTokenizer = null;
					if (token.equals("~")) {//$NON-NLS-1$
						attrValueTokenizer = new StringTokenizer(attrValue);
					}
					else if (token.equals("|")) {//$NON-NLS-1$
						attrValueTokenizer = new StringTokenizer(attrValue, "-");//$NON-NLS-1$
					}
					if (attrValueTokenizer != null) {
						if (tokenizer.hasMoreTokens()) {
							token = tokenizer.nextToken();
							boolean ok = false;
							while (attrValueTokenizer.hasMoreTokens()) {
								if (token.equals(attrValueTokenizer.nextToken())) {
									ok = true;
									break;
								}
							}
							if (!ok)
								return false;
						}
					}
					else {
						if (!attrValue.equals(token))
							return false;
					}
				}
			}
		}

		return true;
	}

	private List parseSelector(List tokens) {
		CSSSelectorParser parser = new CSSSelectorParser(tokens);
		List selector = parser.getSelector();
		Iterator i = parser.getErrors();
		fParseErrors = new ArrayList();
		while (i.hasNext()) {
			fParseErrors.add(i.next());
		}
		return selector;
	}

	public Iterator getErrors() {
		if (fNameErrors == null) {
			fNameErrors = new ArrayList();
			Iterator iItem = getIterator();
			while (iItem.hasNext()) {
				ICSSSelectorItem item = (ICSSSelectorItem) iItem.next();
				if (item instanceof ICSSSimpleSelector) {
					if (!((ICSSSimpleSelector) item).isUniversal()) {
						String name = ((ICSSSimpleSelector) item).getName();
						if (!NameValidator.isValid(name)) {
							fNameErrors.add(item);
						}
					}
				}
			}
		}
		List errors = new ArrayList(fParseErrors);
		errors.addAll(fNameErrors);
		return errors.iterator();
	}

	public String toString() {
		return getString();
	}

	/**
	 * @see ICSSSelector#getErrorCount()
	 */
	public int getErrorCount() {
		int nErrors = 0;
		Iterator i = getErrors();
		while (i.hasNext()) {
			nErrors++;
			i.next();
		}
		return nErrors;
	}
}