/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.    
 */
package org.apache.tuscany.sca.binding.ws.wsdlgen;

//FIXME: trim the import list down to what's really needed


import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.wsdl.Binding;
import javax.wsdl.Definition;
import javax.wsdl.Import;
import javax.wsdl.Port;
import javax.wsdl.PortType;
import javax.wsdl.Service;
import javax.wsdl.WSDLException;
import javax.wsdl.extensions.ExtensibilityElement;
import javax.wsdl.extensions.soap.SOAPAddress;
import javax.wsdl.extensions.soap.SOAPBinding;
import javax.wsdl.extensions.soap12.SOAP12Address;
import javax.wsdl.extensions.soap12.SOAP12Binding;
import javax.wsdl.factory.WSDLFactory;
import javax.wsdl.xml.WSDLWriter;
import javax.xml.namespace.QName;

import org.apache.tuscany.sca.assembly.AbstractContract;
import org.apache.tuscany.sca.assembly.Component;
import org.apache.tuscany.sca.assembly.CompositeService;
import org.apache.tuscany.sca.binding.ws.WebServiceBinding;
import org.apache.tuscany.sca.interfacedef.Interface;
import org.apache.tuscany.sca.interfacedef.wsdl.WSDLDefinition;
import org.apache.tuscany.sca.interfacedef.wsdl.WSDLInterface;
import org.apache.tuscany.sca.monitor.Monitor;
import org.apache.tuscany.sca.monitor.Problem;
import org.apache.tuscany.sca.monitor.Problem.Severity;
import org.apache.tuscany.sca.monitor.impl.ProblemImpl;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;

/**
 * WSDLServiceGenerator generates a binding WSDL service document.
 *
 * @version $Rev$ $Date$
 */
public class WSDLServiceGenerator {
    // the following switch is temporary for debugging
    public static boolean printWSDL;  // external code sets this to print generated WSDL
    
    private static final Logger logger = Logger.getLogger(WSDLServiceGenerator.class.getName());
    private static final QName TRANSPORT_JMS_QUALIFIED_INTENT =
        new QName("http://www.osoa.org/xmlns/sca/1.0", "transport.jms");
    private static final String DEFAULT_QUEUE_CONNECTION_FACTORY = "TuscanyQueueConnectionFactory";
    private static final String ADDRESS = "Address";

    private WSDLServiceGenerator() {
        // this class has static methods only and cannot be instantiated
    }

    /**
     * Log a warning message.
     * @param problem
     */
    private static void logWarning(Problem problem) {
        Logger problemLogger = Logger.getLogger(problem.getSourceClassName(), problem.getBundleName());
        if (problemLogger != null){
            problemLogger.logp(Level.WARNING, problem.getSourceClassName(), null, problem.getMessageId(), problem.getMessageParams());
        } else {
            logger.severe("Can't get logger " + problem.getSourceClassName()+ " with bundle " + problem.getBundleName());
        }
    }

    /**
     * Report a warning.
     * @param message
     * @param binding
     * @param parameters
     */
    private static void warning(Monitor monitor, String message, WebServiceBinding wsBinding, String... messageParameters) {
        Problem problem = new ProblemImpl(WSDLServiceGenerator.class.getName(), "wsdlgen-validation-messages", Severity.WARNING, wsBinding, message, (Object[])messageParameters);
        if (monitor != null) {
            monitor.problem(problem);
        } else {
            logWarning(problem);
        }
    }

    /**
     * Report an error.
     * @param message
     * @param binding
     * @param parameters
     */
    private static void error(Monitor monitor, String message, WebServiceBinding wsBinding, String... messageParameters) {
        Problem problem = new ProblemImpl(WSDLServiceGenerator.class.getName(), "wsdlgen-validation-messages", Severity.ERROR, wsBinding, message, (Object[])messageParameters);
        if (monitor != null) {
            monitor.problem(problem);
        } else {
            throw new WSDLGenerationException(problem.toString(), null, problem);
        }
    }

    /**
     * Generate a suitably configured WSDL definition
     */
    protected static Definition configureWSDLDefinition(WebServiceBinding wsBinding,
                                                        Component component,
                                                        AbstractContract contract,
                                                        Monitor monitor) {

        //[nash] changes to the builder sequence avoid calling this for a CompositeService
        assert !(contract instanceof CompositeService);
        /*
        // For every promoted composite service, the underlying component
        // gets a copy of the service with the name prefixed by "$promoted$."
        String contractName = (contract instanceof CompositeService ? "$promoted$." : "") + contract.getName();
        */
        String contractName = contract.getName();

        List<Port> ports = new ArrayList<Port>();
        WSDLDefinition wsdlDefinition = wsBinding.getWSDLDefinition();
        if (wsdlDefinition == null) {
            error(monitor, "NoWsdlInterface", wsBinding, component.getName(), contract.getName());
            return null;
        }
        Definition def = wsdlDefinition.getDefinition();
        
        boolean wsdlProvidedByUser = (wsdlDefinition.getBinding() == null);
        
        if (wsdlProvidedByUser) {
            // The WSDL document was provided by the user.  Generate a new
            // WSDL document with imports from the user-provided document.
            WSDLFactory factory = null;
            try {
                factory = WSDLFactory.newInstance();
            } catch (WSDLException e) {
                throw new WSDLGenerationException(e);
            }
            Definition newDef = factory.newDefinition();

            // Construct a target namespace from the base URI of the user's
            // WSDL document (is this what we should be using?) and a path
            // computed according to the SCA Web Service binding spec.
            String nsName = component.getName() + "/" + contractName;
            String namespaceURI = null;
            try {
                URI userTNS = new URI(def.getTargetNamespace());
                namespaceURI = userTNS.resolve("/" + nsName).toString();
            } catch (URISyntaxException e1) {
                throw new WSDLGenerationException(e1);
            } catch (IllegalArgumentException e2) {
                throw new WSDLGenerationException(e2);
            }

            // set name and targetNamespace attributes on the definition
            String defsName = component.getName() + "." + contractName;
            newDef.setQName(new QName(namespaceURI, defsName));
            newDef.setTargetNamespace(namespaceURI);
            newDef.addNamespace("tns", namespaceURI);

            // set wsdl namespace prefix on the definition
            newDef.addNamespace("wsdl", "http://schemas.xmlsoap.org/wsdl/");

            // import the service or reference interface portType
            List<WSDLDefinition> imports = new ArrayList<WSDLDefinition>();
            Interface interfaze = wsBinding.getBindingInterfaceContract().getInterface();
            if (interfaze instanceof WSDLInterface) {
                PortType portType = ((WSDLInterface)interfaze).getPortType();
                boolean ok = importPortType(portType, wsdlDefinition, newDef, imports);
                if (!ok) {
                    error(monitor, "PortTypeNotFound", wsBinding, portType.getQName().toString(),
                          component.getName(), contract.getName());
                }
            }

            // import an existing binding if specified
            Binding binding = wsBinding.getBinding();
            if (binding != null) {
                boolean ok = importBinding(binding, wsdlDefinition, newDef, imports);
                if (ok) {
                    boolean ok2 = importPortType(binding.getPortType(), wsdlDefinition, newDef, imports);
                    if (!ok2) {
                        error(monitor, "PortTypeNotFound", wsBinding, binding.getPortType().getQName().toString(),
                              component.getName(), contract.getName());
                    }
                } else {
                    error(monitor, "BindingNotFound", wsBinding, binding.getQName().toString(),
                          component.getName(), contract.getName());
                }
            }

            // import bindings and portTypes needed by services and ports 
            QName serviceQName = wsBinding.getServiceName();
            String portName = wsBinding.getPortName();
            if (serviceQName != null) {
                Service service = def.getService(serviceQName); 
                if (portName != null) {
                    Port port = service.getPort(portName);
                    Port newPort = copyPort(newDef, port, wsBinding);
                    if (newPort != null) {
                        importBinding(port.getBinding(), wsdlDefinition, newDef, imports);
                        ports.add(newPort);
                    } else {
                        error(monitor, "InvalidPort", wsBinding, serviceQName.toString(), portName,
                              component.getName(), contract.getName());
                    }
                } else {
                    for (Object port : service.getPorts().values()) {
                        Port newPort = copyPort(newDef, (Port)port, wsBinding);
                        if (newPort != null) {
                            importBinding(((Port)port).getBinding(), wsdlDefinition, newDef, imports);
                            ports.add(newPort);
                        } else {
                            // not an error, just ignore the port
                            warning(monitor, "IgnoringPort", wsBinding, serviceQName.toString(), ((Port)port).getName(),
                                    component.getName(), contract.getName());
                        }
                    }
                    if (ports.size() == 0) {
                        error(monitor, "NoValidPorts", wsBinding, serviceQName.toString(),
                              component.getName(), contract.getName());
                    }
                }
            }

            // replace original WSDL definition by the generated definition
            def = newDef;

        } else {
            // The WSDL definition was generated by Interface2WSDLGenerator.
            // Reuse it instead of creating a new definition here.
        }

        // add a service and ports to the generated definition  
        WSDLDefinitionGenerator helper =
                new WSDLDefinitionGenerator(BindingWSDLGenerator.requiresSOAP12(wsBinding),false);
        WSDLInterface wi = (WSDLInterface)wsBinding.getBindingInterfaceContract().getInterface();
        PortType portType = wi.getPortType();
        Service service = helper.createService(def, portType);
        if (wsBinding.getBinding() == null && ports.size() == 0) {
            Binding binding = helper.createBinding(def, portType);
            if (BindingWSDLGenerator.requiresSOAP12(wsBinding)) {
                def.addNamespace("SOAP12", "http://schemas.xmlsoap.org/wsdl/soap12/");
            } else {
                def.addNamespace("SOAP11", "http://schemas.xmlsoap.org/wsdl/soap/");
            }
            helper.createBindingOperations(def, binding, portType);
            binding.setUndefined(false);
            def.addBinding(binding);
            
            String endpointURI = computeActualURI(wsBinding, null);
            Port port = helper.createPort(def, binding, service, endpointURI);
            wsBinding.setService(service);
            wsBinding.setPort(port);
        } else {
            if (ports.size() > 0) {
                // there are one or more user-specified valid ports
                for (Port port : ports) {
                    service.addPort(port);
                }
                if (ports.size() == 1) {
                    // only one port, so use it
                    wsBinding.setPort(ports.get(0));
                } else {
                    // multiple ports, make them all available
                    wsBinding.setPort(null);
                }
            } else {
                // no valid user-specified ports, so create a suitably configured port
                String endpointURI = computeActualURI(wsBinding, null);
                Port port = helper.createPort(def, wsBinding.getBinding(), service, endpointURI);
                if (BindingWSDLGenerator.requiresSOAP12(wsBinding)) {
                    def.addNamespace("SOAP12", "http://schemas.xmlsoap.org/wsdl/soap12/");
                } else {
                    def.addNamespace("SOAP11", "http://schemas.xmlsoap.org/wsdl/soap/");
                }
                wsBinding.setPort(port);
            }
            wsBinding.setService(service);
        }
        
        // TUSCANY-2900 - add jms binding and service port if required
        // TODO - remove service/ports from any imported WSDL
        //      - find away to allow users to retrieve WSDL with JMS bindings
        //        as a jms binding on it's own provides not target for ?wsdl
        if ((!wsdlProvidedByUser) && 
            (wsBinding.getURI() != null) &&
            (wsBinding.getURI().startsWith("jms"))){
            
            // need to work out how to check if user has already specified a binding
            
            // create jms binding
            helper = new WSDLDefinitionGenerator(BindingWSDLGenerator.requiresSOAP12(wsBinding),true);
            Binding binding = helper.createBinding(def, portType);
            helper.createBindingOperations(def, binding, portType);
            binding.setUndefined(false);
            def.addBinding(binding);
            
            // create a jms port
            String endpointURI = computeActualURI(wsBinding, null);
            Port port = helper.createPort(def, binding, service, endpointURI);
            wsBinding.setService(service);
            wsBinding.setPort(port);
            
            //printWSDL = true;
        }

        // for debugging
        if (printWSDL) {
            try {
                System.out.println("Generated WSDL for " + component.getName() + "/" + contractName);
                WSDLWriter writer =  javax.wsdl.factory.WSDLFactory.newInstance().newWSDLWriter();
                writer.writeWSDL(def, System.out);
            } catch (WSDLException e) {
                throw new WSDLGenerationException(e);
            }
        }

        return def;
    }

    private static boolean importPortType(PortType portType,
                                          WSDLDefinition wsdlDef,
                                          Definition newDef,
                                          List<WSDLDefinition> imports) {
        return addImport(portType.getQName(), PortType.class, wsdlDef, newDef, imports);
    }
    
    private static boolean importBinding(Binding binding,
                                         WSDLDefinition wsdlDef,
                                         Definition newDef,
                                         List<WSDLDefinition> imports) {
        boolean ok = addImport(binding.getQName(), Binding.class, wsdlDef, newDef, imports);
        if (ok) {
            List bindingExtensions = binding.getExtensibilityElements();
            for (final Object extension : bindingExtensions) {
                if (extension instanceof SOAPBinding) {
                    newDef.addNamespace("SOAP11", "http://schemas.xmlsoap.org/wsdl/soap/");
                }
                if (extension instanceof SOAP12Binding) {
                    newDef.addNamespace("SOAP12", "http://schemas.xmlsoap.org/wsdl/soap12/");
                }
            }
        }
        return ok;
    }
    
    private static boolean addImport(QName name,
                                     Class type,
                                     WSDLDefinition wsdlDef,
                                     Definition newDef,
                                     List<WSDLDefinition> imports) {
        String namespace = name.getNamespaceURI();
        if (newDef.getImports(namespace) == null) {
            WSDLDefinition impDef = findDefinition(wsdlDef, name, type);
            if (impDef != null) {
                Import imp = newDef.createImport();
                imp.setNamespaceURI(namespace);
                imp.setLocationURI(impDef.getURI().toString());
                imp.setDefinition(impDef.getDefinition());
                newDef.addNamespace("ns" + imports.size(), namespace);
                newDef.addImport(imp);
                imports.add(impDef);
                return true;
            } else {
                // import was not added because element not found
                return false;
            }
        }
        return true;
    }

    private static WSDLDefinition findDefinition(WSDLDefinition wsdlDef, QName name, Class type) {
        if (wsdlDef == null || name == null) {
            return wsdlDef;
        }
        if (wsdlDef.getURI() != null) {  // not a facade
            Definition def = wsdlDef.getDefinition();
            Map types = type == PortType.class ? def.getPortTypes() : def.getBindings();
            if (types.get(name) != null) {
                return wsdlDef;
            }
        }
        for (WSDLDefinition impDef : wsdlDef.getImportedDefinitions()) {
            WSDLDefinition d = findDefinition(impDef, name, type);
            if (d != null) {
                return d;
            }
        }
        return null;
    }

    private static Port copyPort(Definition def, Port port, WebServiceBinding wsBinding) {
        Port newPort = def.createPort();
        newPort.setName(port.getName());
        newPort.setBinding(port.getBinding());
        List portExtensions = port.getExtensibilityElements();
        for (final Object extension : portExtensions) {
            ExtensibilityElement newExt = null;
            if (extension instanceof SOAPAddress) {
                def.addNamespace("SOAP11", "http://schemas.xmlsoap.org/wsdl/soap/");
                try {
                    newExt = def.getExtensionRegistry().createExtension(
                             Port.class, WSDLDefinitionGenerator.SOAP_ADDRESS);
                } catch (WSDLException e) {
                }
                String uri = computeActualURI(wsBinding, port);
                ((SOAPAddress)newExt).setLocationURI(uri);
                newPort.addExtensibilityElement(newExt);
            } else if (extension instanceof SOAP12Address) {
                def.addNamespace("SOAP12", "http://schemas.xmlsoap.org/wsdl/soap12/");
                try {
                    newExt = def.getExtensionRegistry().createExtension(
                             Port.class, WSDLDefinitionGenerator.SOAP12_ADDRESS);
                } catch (WSDLException e) {
                }
                String uri = computeActualURI(wsBinding, port);
                ((SOAP12Address)newExt).setLocationURI(uri);
                newPort.addExtensibilityElement(newExt);
            } else {
                // we don't support ports with other extensibility elements such as HTTPAddress
                return null;
            }
        }
        return newPort;
    }

    /**
     * Compute the endpoint URI based on section 2.1.1 of the WS binding Specification 1.
     * The URIs in the endpoint(s) of the referenced WSDL, which may be relative
     * 2. The URI specified by the wsa:Address element of the
     * wsa:EndpointReference, which may be relative 3. The explicitly stated URI
     * in the "uri" attribute of the binding.ws element, which may be relative,
     * 4. The implicit URI as defined by in section 1.7 in the SCA Assembly Specification
     * If the <binding.ws> has no wsdlElement but does have a uri attribute then
     * the uri takes precedence over any implicitly used WSDL.
     * 
     */
    private static String computeActualURI(WebServiceBinding wsBinding, Port port) {

        URI eprURI = null;
        if (wsBinding.getEndPointReference() != null) {
            eprURI = getEPR(wsBinding); 
        }

        URI wsdlURI = null;
        if (wsBinding.getServiceName() != null && wsBinding.getBindingName() == null) {
            // <binding.ws> explicitly points at a WSDL port, may be a relative URI
            wsdlURI = getEndpoint(port);
        }

        // if the WSDL port/endpoint has an absolute URI use that
        if (wsdlURI != null && wsdlURI.isAbsolute()) {
            return wsdlURI.toString();
        }

        // if the wsa:EndpointReference has an address element with an absolute URI use that
        if (eprURI != null && eprURI.isAbsolute()) {
            return eprURI.toString();
        }
        
        // either there is no WSDL port endpoint URI or that URI is relative
        String actualURI = wsBinding.getURI();
        if (eprURI != null && eprURI.toString().length() != 0) {
            // there is a relative URI in the binding EPR
            actualURI = actualURI + "/" + eprURI;
        }

        if (wsdlURI != null && wsdlURI.toString().length() != 0) {
            // there is a relative URI in the WSDL port
            actualURI = actualURI + "/" + wsdlURI;
        }
        
        if (actualURI != null) {
            actualURI = URI.create(actualURI).normalize().toString();
        }
        
        return actualURI;
    }

    private static URI getEPR(WebServiceBinding wsBinding) {
        NodeList nodeList = wsBinding.getEndPointReference().getChildNodes();
        for (int i = 0; i < nodeList.getLength(); i++) {
            Node childNode = nodeList.item(i);
            if (childNode instanceof Element && ADDRESS.equals(childNode.getLocalName())) {
                NodeList addrNodes = childNode.getChildNodes();
                for (int j = 0; j < addrNodes.getLength(); j++) {
                    Node addrNode = addrNodes.item(j);
                    if (addrNode instanceof Text) {
                        return URI.create(((Text)addrNode).getWholeText());
                    }
                }
            }
        }
        return null;
    }

    /**
     * Returns the endpoint of a given port.
     */
    private static URI getEndpoint(Port wsdlPort) {
        if (wsdlPort != null) {
            List<?> wsdlPortExtensions = wsdlPort.getExtensibilityElements();
            for (Object extension : wsdlPortExtensions) {
                if (extension instanceof SOAPAddress) {
                    String uri = ((SOAPAddress)extension).getLocationURI();
                    return (uri == null || "".equals(uri)) ? null : URI.create(uri);
                }
                if (extension instanceof SOAP12Address) {
                    SOAP12Address address = (SOAP12Address)extension;
                    String uri = address.getLocationURI();
                    return (uri == null || "".equals(uri)) ? null : URI.create(uri);
                }
            }
        }
        return null;
    }

}
