package org.ow2.jonas.ws.axis2.util;


import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.wsdl.Definition;
import javax.wsdl.Port;
import javax.wsdl.Service;
import javax.wsdl.extensions.http.HTTPAddress;
import javax.wsdl.extensions.soap.SOAPAddress;
import javax.wsdl.extensions.soap12.SOAP12Address;
import javax.xml.namespace.QName;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class WSDLUtils {

    private static final Log LOG = LogFactory.getLog(WSDLUtils.class);

    public static void trimDefinition(final Definition def,
                                      final String serviceName,
                                      final String portName) {
        Map services = def.getServices();
        if (services != null) {
            ArrayList<QName> servicesToRemove = new ArrayList<QName>(services.size());

            Iterator serviceIterator = services.entrySet().iterator();
            while (serviceIterator.hasNext()) {
                Map.Entry serviceEntry = (Map.Entry) serviceIterator.next();
                QName currServiceName = (QName) serviceEntry.getKey();
                if (currServiceName.getLocalPart().equals(serviceName)) {
                    Service service = (Service) serviceEntry.getValue();
                    trimService(service, portName);
                } else {
                    servicesToRemove.add(currServiceName);
                }
            }

            for (QName serviceToRemove : servicesToRemove) {
                def.removeService(serviceToRemove);
            }
        }
    }

    public static void trimService(final Service service,
                                   final String portName) {
        Map ports = service.getPorts();
        if (ports != null) {
            ArrayList<String> portsToRemove = new ArrayList<String>(ports.size());

            Iterator portIterator = ports.entrySet().iterator();
            while (portIterator.hasNext()) {
                Map.Entry portEntry = (Map.Entry) portIterator.next();
                String currPortName = (String) portEntry.getKey();
                if (!currPortName.equals(portName)) {
                    portsToRemove.add(currPortName);
                }
            }

            for (String portToRemove : portsToRemove) {
                service.removePort(portToRemove);
            }
        }
    }

    public static void updateLocations(final Definition def,
                                       final String location) {
        Map services = def.getServices();
        if (services != null) {
            Iterator serviceIterator = services.entrySet().iterator();
            while (serviceIterator.hasNext()) {
                Map.Entry serviceEntry = (Map.Entry) serviceIterator.next();
                Service service = (Service) serviceEntry.getValue();
                updateLocations(service, location);
            }
        }
    }

    public static void updateLocations(final Service service,
                                       final String location) {
        boolean updated = false;
        Map ports = service.getPorts();
        if (ports != null) {
            Iterator portIterator = ports.entrySet().iterator();
            while (portIterator.hasNext()) {
                Map.Entry portEntry = (Map.Entry) portIterator.next();
                Port port = (Port) portEntry.getValue();
                updateLocations(port, location);
            }
        }
    }

    public static void updateLocations(final Port port,
                                       final String location) {
        List<?> exts = port.getExtensibilityElements();
        if (exts != null) {
            for (Object extension : exts) {
                if (extension instanceof SOAP12Address) {
                    ((SOAP12Address)extension).setLocationURI(location);
                } else if (extension instanceof SOAPAddress) {
                    ((SOAPAddress)extension).setLocationURI(location);
                } else if (extension instanceof HTTPAddress) {
                    ((HTTPAddress)extension).setLocationURI(location);
                }
            }
        }
    }

}

