/*******************************************************************************
 * Copyright (C) 2007 The University of Manchester   
 * 
 *  Modifications to the initial code base are copyright of their
 *  respective authors, or their employers as appropriate.
 * 
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public License
 *  as published by the Free Software Foundation; either version 2.1 of
 *  the License, or (at your option) any later version.
 *    
 *  This program is distributed in the hope that it will be useful, but
 *  WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *    
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 ******************************************************************************/
package net.sf.taverna.wsdl.soap;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.wsdl.WSDLException;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.soap.SOAPException;

import net.sf.taverna.wsdl.parser.ArrayTypeDescriptor;
import net.sf.taverna.wsdl.parser.BaseTypeDescriptor;
import net.sf.taverna.wsdl.parser.ComplexTypeDescriptor;
import net.sf.taverna.wsdl.parser.TypeDescriptor;
import net.sf.taverna.wsdl.parser.UnknownOperationException;
import net.sf.taverna.wsdl.parser.WSDLParser;

import org.apache.axis.encoding.Base64;
import org.apache.axis.message.SOAPBodyElement;
import org.apache.log4j.Logger;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;

@SuppressWarnings("unchecked")
public abstract class AbstractBodyBuilder implements BodyBuilder {
	
	private static Logger logger = Logger.getLogger(AbstractBodyBuilder.class);

	private String style;
	private WSDLParser parser;
	private String operationName;

	protected enum Style {
		DOCUMENT, RPC
	};

	protected enum Use {
		LITERAL, ENCODED
	};

	protected Map<String, String> namespaceMappings;
	protected List<TypeDescriptor> inputDescriptors;

	public AbstractBodyBuilder(String style, WSDLParser parser,
			String operationName, List<TypeDescriptor> inputDescriptors) {
		this.style = style;
		this.parser = parser;
		this.operationName = operationName;
		this.inputDescriptors = inputDescriptors;
	}

	protected Style getStyle() {
		Style result = Style.DOCUMENT;
		if (style.equalsIgnoreCase("rpc")) {
			result = Style.RPC;
		} else if (style.equalsIgnoreCase("document")) {
			result = Style.DOCUMENT;
		}
		return result;
	}

	protected abstract Use getUse();

	/**
	 * 
	 * @return the namespace for the operation
	 */
	private String getOperationNamespace() throws UnknownOperationException {
		return parser.getOperationNamespaceURI(operationName);
	}
	
	private QName getOperationQname() throws UnknownOperationException {
		return parser.getOperationQname(operationName);	
	}

	public SOAPBodyElement build(Map inputMap) throws WSDLException,
			ParserConfigurationException, SOAPException, IOException,
			SAXException, UnknownOperationException {

		List inputs = parser.getOperationInputParameters(operationName);

		namespaceMappings = generateNamespaceMappings(inputs);

		QName operationQname = getOperationQname();
		
		SOAPBodyElement body = new SOAPBodyElement(operationQname);

		// its important to preserve the order of the inputs!
		for (Iterator iterator = inputs.iterator(); iterator.hasNext();) {
			TypeDescriptor descriptor = (TypeDescriptor) iterator.next();
			String inputName = descriptor.getName();
			Object dataValue = inputMap.get(inputName);

			body = createBodyElementForData(operationName, namespaceMappings,
					operationQname.getNamespaceURI(), body, descriptor, inputName, dataValue);
		}

		return body;
	}



	protected SOAPBodyElement createBodyElementForData(String operationName,
			Map<String, String> namespaceMappings, String operationNamespace,
			SOAPBodyElement body, TypeDescriptor descriptor, String inputName,
			Object dataValue) throws ParserConfigurationException,
			SAXException, IOException, UnknownOperationException, SOAPException {
		if (dataValue != null) {
			String mimeType = getMimeTypeForInputName(inputName);
			String typeName = descriptor.getType();

			Element el = null;

			if (descriptor instanceof ArrayTypeDescriptor) {
				el = createElementForArrayType(namespaceMappings, inputName,
						dataValue, descriptor, mimeType, typeName);

			} else {
				el = createSkeletonElementForSingleItem(namespaceMappings,
						descriptor, inputName, typeName);
				populateElementWithObjectData(mimeType, el, dataValue, descriptor);
			}

			body = addElementToBody(operationNamespace, body, el);
		}
		return body;
	}

	protected abstract SOAPBodyElement addElementToBody(
			String operationNamespace, SOAPBodyElement body, Element el)
			throws SOAPException;

	protected abstract Element createSkeletonElementForSingleItem(
			Map<String, String> namespaceMappings, TypeDescriptor descriptor,
			String inputName, String typeName);

	/**
	 * generates an XML DOM Element for an array
	 * 
	 * @param namespaceMappings
	 * @param inputName
	 * @param dataValue
	 * @param descriptor
	 * @param mimeType
	 * @param typeName
	 * @return
	 * @throws ParserConfigurationException
	 * @throws SAXException
	 * @throws IOException
	 */
	protected abstract Element createElementForArrayType(
			Map<String, String> namespaceMappings, String inputName,
			Object dataValue, TypeDescriptor descriptor, String mimeType,
			String typeName) throws ParserConfigurationException, SAXException,
			IOException, UnknownOperationException;

	/**
	 * Populates a DOM XML Element with the contents of a List of dataValues
	 * 
	 * @param mimeType -
	 *            the mime type of the data
	 * @param element -
	 *            the Element to be populated
	 * @param dataValues -
	 *            the List of Objects containing the data
	 * @param elementType -
	 *            the TypeDescriptor for the element being populated
	 * @throws ParserConfigurationException
	 * @throws SAXException
	 * @throws IOException
	 */
	protected void populateElementWithList(String mimeType, Element element,
			List dataValues, TypeDescriptor elementType)
			throws ParserConfigurationException, SAXException, IOException {
		for (Iterator dataIterator = dataValues.iterator(); dataIterator
				.hasNext();) {
			Object dataItem = dataIterator.next();
			String tag;
			if (elementType instanceof BaseTypeDescriptor) {
				tag = elementType.getType();
			} else {
				tag = elementType.getName();
			}

			Element item = element.getOwnerDocument().createElement(tag);
			populateElementWithObjectData(mimeType, item, dataItem, elementType);
			element.appendChild(item);
		}
	}

	/**
	 * Populates a DOM XML Element with dataValue according to its mimetype
	 * 
	 * @param mimeType
	 * @param element
	 * @param dataValue
	 * @param descriptor 
	 * @throws ParserConfigurationException
	 * @throws SAXException
	 * @throws IOException
	 */
	protected void populateElementWithObjectData(String mimeType,
			Element element, Object dataValue, TypeDescriptor descriptor)
			throws ParserConfigurationException, SAXException, IOException {
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		factory.setNamespaceAware(true);
		DocumentBuilder builder = factory.newDocumentBuilder();

		if (mimeType.equals("'text/xml'")) {
			Document doc = builder.parse(new ByteArrayInputStream(dataValue
					.toString().getBytes()));
			Element documentElement = doc.getDocumentElement();
			
			if (descriptor instanceof ComplexTypeDescriptor) {
				ComplexTypeDescriptor complexType = (ComplexTypeDescriptor) descriptor;
				NamedNodeMap attributes = documentElement.getAttributes();
				if (attributes != null) {
					for (int i = 0; i < attributes.getLength(); i++) {
						Node attributeNode = attributes.item(i);
						if (attributeNode instanceof Attr) {
							Attr attribute = (Attr) attributeNode;
							TypeDescriptor typeDescriptor = complexType.attributeForName(attribute.getName());
							if (typeDescriptor != null) {
								element.setAttributeNS(typeDescriptor.getNamespaceURI(), typeDescriptor.getName(), attribute.getValue());
							}
						}
					}
				}
			}
			
			Node child = documentElement.getFirstChild();

			while (child != null) {
				element.appendChild(element.getOwnerDocument().importNode(
						child, true));
				child = child.getNextSibling();
			}
		} else if (mimeType.equals("'application/octet-stream'")
				&& dataValue instanceof byte[]) {
			String encoded = Base64.encode((byte[]) dataValue);
			element.appendChild(element.getOwnerDocument().createTextNode(
					encoded));
		} else {
			element.appendChild(element.getOwnerDocument().createTextNode(
					dataValue.toString()));
		}
	}

	/**
	 * Provides the mime type for a given input
	 * 
	 * @param inputName
	 * @return
	 */
	protected String getMimeTypeForInputName(String inputName) {
		for (TypeDescriptor desc : inputDescriptors) {
			if (desc.getName().equals(inputName))
				return desc.getMimeType();
		}
		return "";
	}

	/**
	 * Generates a map of all the namespaces for the operation and all of the
	 * types required to call the operation. Namesspace prefixes (the key) start
	 * with ns1 representing the operation, and continue incrementally for all
	 * additional namespaces (ns2, ns3 ... etc).
	 * 
	 * @return
	 * @param inputs -
	 *            List of input TypeDescriptor's
	 * @throws UnknownOperationException
	 * @throws IOException
	 */
	protected Map<String, String> generateNamespaceMappings(List inputs)
			throws UnknownOperationException, IOException {
		Map<String, String> result = new HashMap<String, String>();
		int nsCount = 2;

		result.put(getOperationNamespace(), "ns1");
		result.put("http://www.w3.org/2001/XMLSchema", "xsd");
		result.put("http://www.w3.org/2001/XMLSchema-instance", "xsi");

		for (Iterator iterator = inputs.iterator(); iterator.hasNext();) {
			TypeDescriptor descriptor = (TypeDescriptor) iterator.next();
			nsCount = mapNamespace(descriptor, new ArrayList<TypeDescriptor>(),result, nsCount);

		}

		return result;
	}

	/**
	 * creates a namespace prefix and adds the namespace to the namespaceMap for
	 * a TypeDescriptor. Further recursive calls are made if this type contains
	 * addition inner elements that are not already mapped.
	 * 
	 * @param descriptor
	 * @param namespaceMap
	 * @param nsCount
	 * @return
	 */
	protected int mapNamespace(TypeDescriptor descriptor, List<TypeDescriptor> visitedDescriptors,
			Map<String, String> namespaceMap, int nsCount) {
		if (!visitedDescriptors.contains(descriptor)) {
			visitedDescriptors.add(descriptor);
			String namespace = descriptor.getNamespaceURI();
			if (namespace != null && namespace.length() > 0
					&& !namespaceMap.containsKey(namespace)) {
				namespaceMap.put(namespace, "ns" + nsCount);
				nsCount++;
			}
	
			if (descriptor instanceof ArrayTypeDescriptor) {
				nsCount = mapNamespace(((ArrayTypeDescriptor) descriptor)
						.getElementType(),visitedDescriptors, namespaceMap, nsCount);
			} else if (descriptor instanceof ComplexTypeDescriptor) {
				List elements = ((ComplexTypeDescriptor) descriptor).getElements();
				for (Iterator iterator = elements.iterator(); iterator.hasNext();) {
					nsCount = mapNamespace((TypeDescriptor) iterator.next(),visitedDescriptors,
							namespaceMap, nsCount);
				}
			}
		}
		else {
			logger.error("The descriptor: "+descriptor+" is appears to be part of a cyclic schema. Bailing out of mapping namespace.");
		}

		return nsCount;
	}
}
