/**
 * Implements the CFML Function xmlelemnew
 */
package railo.runtime.functions.xml;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;

import railo.commons.lang.StringUtil;
import railo.runtime.PageContext;
import railo.runtime.exp.FunctionException;
import railo.runtime.ext.function.Function;
import railo.runtime.text.xml.XMLUtil;
import railo.runtime.text.xml.struct.XMLStructFactory;
import railo.runtime.type.util.ListUtil;

public final class XmlElemNew implements Function {
	
	private static final long serialVersionUID = -2601887739406776466L;

	public static Element call(PageContext pc , Node node, String childname) throws FunctionException {
		return call(pc, node, null, childname);
	}
	
	public static Element call(PageContext pc , Node node, String namespace, String childname) throws FunctionException {
		Document doc=XMLUtil.getDocument(node);
		
		if(StringUtil.isEmpty(childname)) {
			if(!StringUtil.isEmpty(namespace)) {
				childname=namespace;
				namespace=null;
			}
			else throw new FunctionException(pc, "XmlElemNew", 3, "childname", "argument is required");
		}
		
		Element el = null;
		
		// without namespace
		if(StringUtil.isEmpty(namespace)){
			if(childname.indexOf(':')!=-1) {
				String[] parts = ListUtil.listToStringArray(childname, ':');
				childname = parts[1];
				String prefix = parts[0];
				namespace = getNamespaceForPrefix(doc.getDocumentElement(),prefix);
				if(StringUtil.isEmpty(namespace)) {
					el=doc.createElement(childname);
				} else {
					el=doc.createElementNS(namespace,childname);
					el.setPrefix(prefix);
				}
				
			} else {
				el=doc.createElement(childname);	
			}
		}
		// with namespace
		else {
			el=doc.createElementNS(namespace, childname);
		}
		return (Element)XMLStructFactory.newInstance(el,false);
	}
	
	private static String getNamespaceForPrefix(Node node,String prefix) {
		if (node==null) return null;
		NamedNodeMap atts = node.getAttributes();

		if (atts != null) {
			String currLocalName,currPrefix;
			int len=atts.getLength();
			for (int i = 0; i < len; i++) {
				Node currAttr = atts.item(i);
				currLocalName = currAttr.getLocalName();
				currPrefix = currAttr.getPrefix();
				if (prefix.equals(currLocalName) && "xmlns".equals(currPrefix)) {
					return currAttr.getNodeValue();
				} 
				else if (StringUtil.isEmpty(prefix) && "xmlns".equals(currLocalName)
						&& StringUtil.isEmpty(currPrefix)) {
					return currAttr.getNodeValue();
				}
			}
		}
		return null;
	}
	
	
}