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

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import org.eclipse.jst.jsf.common.ui.internal.logging.Logger;
import org.eclipse.jst.jsf.common.ui.internal.utils.ResourceUtils;
import org.eclipse.jst.pagedesigner.IJMTConstants;
import org.eclipse.jst.pagedesigner.PDPlugin;
import org.eclipse.jst.pagedesigner.css2.font.CSSFont;
import org.eclipse.jst.pagedesigner.css2.style.DefaultStyle;
import org.eclipse.swt.graphics.Color;
import org.eclipse.wst.css.core.internal.provisional.adapters.IStyleSheetListAdapter;
import org.eclipse.wst.css.core.internal.provisional.document.ICSSModel;
import org.eclipse.wst.css.core.internal.provisional.document.ICSSNode;
import org.eclipse.wst.css.core.internal.util.CSSClassTraverser;
import org.eclipse.wst.html.core.internal.htmlcss.CSSQueryTraverser;
import org.eclipse.wst.sse.core.StructuredModelManager;
import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.css.CSSStyleDeclaration;
import org.w3c.dom.stylesheets.StyleSheet;
import org.w3c.dom.stylesheets.StyleSheetList;

/**
 * @author mengbo
 */
public class CSSUtil {
	private static StyleSheet _userAgentDefault;

	public static String[] getCSSClasses(Document doc) {
		Collection c = Collections.EMPTY_SET;
		if (doc instanceof INodeNotifier) {
			IStyleSheetListAdapter adapter = (IStyleSheetListAdapter) ((INodeNotifier) doc)
					.getAdapterFor(IStyleSheetListAdapter.class);
			StyleSheetList ssl = (adapter == null ? null : adapter
					.getStyleSheets());

			CSSClassTraverser traverser = new CSSClassTraverser();
			if (ssl != null) {
				for (int i = 0, numStyles = ssl.getLength(); i < numStyles; i++) {
					// loop for styles (<style> and <link>)
					org.w3c.dom.stylesheets.StyleSheet ss = ssl.item(i);

					try {
						traverser.apply((ICSSNode) ss);
					} catch (ClassCastException ex) {
						Logger log = PDPlugin
								.getLogger(CSSStyleDeclaration.class);
						log.error("Error.CSSUtil.0", ex); //$NON-NLS-1$
						// FIXME: should this continue to be processed?
					}
				}
				c = traverser.getClassNames();
			}
		}
		String[] result = new String[c.size()];
		c.toArray(result);
		return result;
	}

	/**
	 * Get the css style of a node.
	 * 
	 * @param node
	 * @return
	 */
	public static ICSSStyle getCSSStyle(Element node) {
		ICSSStyle style = null;
		if (node instanceof IDOMElement) {
			style = (ICSSStyle) ((IDOMElement) node)
					.getAdapterFor(ICSSStyle.class);
		}
		if (style == null) {
			return DefaultStyle.getInstance();
		}
        return style;
	}

	/**
	 * Resolve the css style string from css style elements.
	 * 
	 * @param node
	 * @return
	 */
	public static String resolveCSSStyle(ICSSStyle style) {
		StringBuffer sb = new StringBuffer();
		Object object1 = style.getColor();
		if (object1 instanceof Color) {
			sb.append("color:");

			sb.append("#").append(
					Integer.toHexString(((Color) object1).getRed()));
			sb.append("#").append(
					Integer.toHexString(((Color) object1).getGreen()));
			sb.append("#").append(
					Integer.toHexString(((Color) object1).getBlue()));
			sb.append(";");
		}
		Object object2 = style.getCSSFont();
		if (object2 instanceof CSSFont) {
			sb.append(((CSSFont) object2).getCSSString());
		}
		return sb.toString();
	}

	/**
	 * Many of this method implementation copied from HTMLDocumentAdapter,
	 * mainly add support for user agent default style sheet.
	 * 
	 * @param element
	 *            the element.
	 * @param pseudoName
	 *            the pseudoname of the element
	 * @return
	 */
	public static CSSStyleDeclaration getCSSDeclaration(Element element,
			String pseudoName) {
		// please reference comments in CSSTempUtil.
		List styleSheets = CSSTempUtil.getStyleSheets(element);
		// INodeNotifier docnotifier = (INodeNotifier)
		// element.getOwnerDocument();
		// IStyleSheetListAdapter adapter = (IStyleSheetListAdapter)
		// docnotifier.getAdapterFor(IStyleSheetListAdapter.class);
		//
		// StyleSheetList ssl = (adapter == null ? null :
		// adapter.getStyleSheets());

		CSSQueryTraverser query = new CSSQueryTraverser();
		query.setTraverseImported(true);
		query.setTraverseImportFirst(true);
		query.setElement(element, pseudoName);

		// if (ssl != null)
		// {
		// for (int i = 0, numStyles = ssl.getLength(); i < numStyles; i++)
		// {
		// // loop for styles (<style> and <link>)
		// org.w3c.dom.stylesheets.StyleSheet ss = ssl.item(i);
		if (styleSheets != null) {
			for (int i = 0, numStyles = styleSheets.size(); i < numStyles; i++) {
				StyleSheet ss = (StyleSheet) styleSheets.get(i);
				try {
					query.apply((ICSSNode) ss);
				} catch (ClassCastException ex) {
					Logger log = PDPlugin.getLogger(CSSStyleDeclaration.class);
					log.error("Error.CSSUtil.0", ex); //$NON-NLS-1$
					// FIXME: should this continue to be processed?
				}
			}
		}
		CSSStyleDeclaration declare = query.getDeclaration();
		// FIXME: when do we need to apply the user agent style sheet?
		return declare;
	}

	/**
	 * Many of this method implementation copied from HTMLDocumentAdapter,
	 * mainly add support for user agent default style sheet.
	 * 
	 * @param element
	 *            the element.
	 * @param pseudoName
	 *            the pseudoname of the element
	 * @return
	 */
	public static CSSStyleDeclaration getDefaultCSSDeclaration(Element element,
			String pseudoName) {
		CSSQueryTraverser query = new CSSQueryTraverser();
		query.setTraverseImported(true);
		query.setTraverseImportFirst(true);

		query.setElement(element, pseudoName);

		// FIXME: when do we need to apply the user agent style sheet?
		try {
			getUserAgentDefaultStyleSheet(element);
		} catch (UnsupportedEncodingException e) {
			Logger log = PDPlugin.getLogger(CSSStyleDeclaration.class);
			log.error("Error.CSSUtil.1", e); //$NON-NLS-1$
		} catch (IOException e) {
			Logger log = PDPlugin.getLogger(CSSStyleDeclaration.class);
			log.error("Error.CSSUtil.2", e); //$NON-NLS-1$
		}
		if (_userAgentDefault != null) {
			try {
				query.apply((ICSSNode) _userAgentDefault);
			} catch (ClassCastException ex) {
				Logger log = PDPlugin.getLogger(CSSStyleDeclaration.class);
				log.error("Error.CSSUtil.3", ex); //$NON-NLS-1$
			}
		}
		CSSStyleDeclaration declare = query.getDeclaration();
		return declare;
	}

	/**
	 * Get the user agent default style sheet.
	 * 
	 * @param element
	 * @return
	 * @throws IOException
	 * @throws UnsupportedEncodingException
	 */
	// XXX: in the future, we may get user agent default style sheet based on
	// device type.
	private static StyleSheet getUserAgentDefaultStyleSheet(Element element)
			throws UnsupportedEncodingException, IOException {
		if (_userAgentDefault == null) {
			InputStream input = CSSUtil.class
					.getResourceAsStream(IJMTConstants.USERAGENT);
			IStructuredModel model = StructuredModelManager.getModelManager()
					.getModelForEdit(IJMTConstants.USERAGENT, input, null);
			ICSSModel cssmodel = (ICSSModel) model;
			_userAgentDefault = (StyleSheet) cssmodel.getDocument();

			ResourceUtils.ensureClosed(input);
		}

		return _userAgentDefault;
	}

}
