/*
 * 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.camel.component.spring.ws.bean;

import java.net.URISyntaxException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.xml.XMLConstants;
import javax.xml.namespace.QName;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;

import org.w3c.dom.Node;

import org.apache.camel.CamelContext;
import org.apache.camel.CamelContextAware;
import org.apache.camel.RuntimeCamelException;
import org.apache.camel.component.spring.ws.type.EndpointMappingKey;
import org.apache.camel.component.spring.ws.type.EndpointMappingType;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.server.EndpointInterceptor;
import org.springframework.ws.server.EndpointInvocationChain;
import org.springframework.ws.server.EndpointMapping;
import org.springframework.ws.server.endpoint.MessageEndpoint;
import org.springframework.ws.server.endpoint.mapping.AbstractEndpointMapping;
import org.springframework.ws.server.endpoint.support.PayloadRootUtils;
import org.springframework.ws.soap.SoapMessage;
import org.springframework.ws.soap.server.SoapEndpointInvocationChain;
import org.springframework.ws.soap.server.SoapEndpointMapping;
import org.springframework.ws.transport.WebServiceConnection;
import org.springframework.ws.transport.context.TransportContext;
import org.springframework.ws.transport.context.TransportContextHolder;
import org.springframework.xml.xpath.XPathExpression;

/**
 * Spring {@link EndpointMapping} for mapping messages to corresponding Camel
 * endpoints. This class needs to be registered in the Spring
 * <tt>ApplicationContext</tt> when consuming messages using any of the
 * following URI schemes:
 * <p/>
 * <ul>
 * <li><tt>spring-ws:rootqname:</tt><br/>
 * Equivalent to endpoint mappings specified through
 * {@link org.springframework.ws.server.endpoint.mapping.PayloadRootQNameEndpointMapping}
 * <p/>
 * <li><tt>spring-ws:soapaction:</tt><br/>
 * Equivalent to endpoint mappings specified through
 * {@link org.springframework.ws.soap.server.endpoint.mapping.SoapActionEndpointMapping}
 * <p/>
 * <li><tt>spring-ws:uri:</tt><br/>
 * Equivalent to endpoint mappings specified through
 * {@link org.springframework.ws.server.endpoint.mapping.UriEndpointMapping}
 * <p/>
 * <li><tt>spring-ws:xpathresult:</tt><br/>
 * Equivalent to endpoint mappings specified through
 * {@link org.springframework.ws.server.endpoint.mapping.XPathPayloadEndpointMapping}
 * </ul>
 * 
 * @see org.springframework.ws.server.endpoint.mapping.AbstractEndpointMapping
 * @see org.springframework.ws.server.endpoint.mapping.PayloadRootQNameEndpointMapping
 * @see org.springframework.ws.server.endpoint.mapping.UriEndpointMapping
 * @see org.springframework.ws.server.endpoint.mapping.XPathPayloadEndpointMapping
 * @see org.springframework.ws.soap.server.endpoint.mapping.SoapActionEndpointMapping
 */
public class CamelEndpointMapping extends AbstractEndpointMapping implements InitializingBean, CamelSpringWSEndpointMapping, SoapEndpointMapping, CamelContextAware {

    private static final String DOUBLE_QUOTE = "\"";
    private static final String URI_PATH_WILDCARD = "*";
    private Map<EndpointMappingKey, MessageEndpoint> endpoints = new ConcurrentHashMap<>();
    private TransformerFactory transformerFactory;
    private CamelContext camelContext;

    private String[] actorsOrRoles;

    private boolean isUltimateReceiver = true;

    @Override
    public CamelContext getCamelContext() {
        return camelContext;
    }

    @Override
    public void setCamelContext(CamelContext camelContext) {
        this.camelContext = camelContext;
    }

    @Override
    protected Object getEndpointInternal(MessageContext messageContext) throws Exception {
        for (EndpointMappingKey key : endpoints.keySet()) {
            String messageKey;
            switch (key.getType()) {
            case ROOT_QNAME:
                messageKey = getRootQName(messageContext);
                break;
            case SOAP_ACTION:
                messageKey = getSoapAction(messageContext);
                break;
            case XPATHRESULT:
                messageKey = getXPathResult(messageContext, key.getExpression());
                break;
            case URI:
                messageKey = getUri();
                break;
            case URI_PATH:
                messageKey = getUriPath();

                if (messageKey != null && key.getLookupKey().endsWith(URI_PATH_WILDCARD)) {
                    String lookupKey = key.getLookupKey().substring(0, key.getLookupKey().length() - 1);

                    if (messageKey.startsWith(lookupKey)) {
                        return endpoints.get(key);
                    }
                }

                break;
            default:
                throw new RuntimeCamelException("Invalid mapping type specified. Supported types are: root QName, SOAP action, XPath expression and URI");
            }
            if (key.getLookupKey().equals(messageKey)) {
                return endpoints.get(key);
            }
        }
        return null;
    }

    @Override
    protected final EndpointInvocationChain createEndpointInvocationChain(MessageContext messageContext, Object endpoint, EndpointInterceptor[] interceptors) {
        for (EndpointMappingKey key : endpoints.keySet()) {
            if (EndpointMappingType.SOAP_ACTION.equals(key.getType())) {
                Object messageKey = getSoapAction(messageContext);
                if (key.getLookupKey().equals(messageKey)) {
                    return new SoapEndpointInvocationChain(endpoint, interceptors, actorsOrRoles, isUltimateReceiver);
                }
            }
        }
        return super.createEndpointInvocationChain(messageContext, endpoint, interceptors);
    }

    private String getSoapAction(MessageContext messageContext) {
        if (messageContext.getRequest() instanceof SoapMessage) {
            SoapMessage request = (SoapMessage)messageContext.getRequest();
            String soapAction = request.getSoapAction();
            if (StringUtils.hasLength(soapAction) && soapAction.startsWith(DOUBLE_QUOTE) && soapAction.endsWith(DOUBLE_QUOTE)) {
                return soapAction.substring(1, soapAction.length() - 1);
            }
            return soapAction;
        }
        return null;
    }

    private String getUri() throws URISyntaxException {
        WebServiceConnection webServiceConnection = getWeServiceConnection();
        if (webServiceConnection != null) {
            return webServiceConnection.getUri().toString();
        }
        return null;
    }

    private String getUriPath() throws URISyntaxException {
        WebServiceConnection webServiceConnection = getWeServiceConnection();
        if (webServiceConnection != null) {
            return webServiceConnection.getUri().getPath();
        }

        return null;
    }

    private WebServiceConnection getWeServiceConnection() {
        TransportContext transportContext = TransportContextHolder.getTransportContext();
        if (transportContext != null) {
            WebServiceConnection webServiceConnection = transportContext.getConnection();
            if (webServiceConnection != null) {
                return webServiceConnection;
            }
        }
        return null;
    }

    private String getRootQName(MessageContext messageContext) throws TransformerException {
        QName qName = PayloadRootUtils.getPayloadRootQName(messageContext.getRequest().getPayloadSource(), transformerFactory);
        return qName != null ? qName.toString() : null;
    }

    private String getXPathResult(MessageContext messageContext, XPathExpression expression) {
        if (expression != null) {
            Node domNode = camelContext.getTypeConverter().convertTo(Node.class, messageContext.getRequest().getPayloadSource());
            if (domNode != null) {
                return expression.evaluateAsString(domNode.getFirstChild());
            }
        }
        return null;
    }

    /**
     * Used by Camel Spring Web Services endpoint to register consumers
     */
    @Override
    public void addConsumer(EndpointMappingKey key, MessageEndpoint endpoint) {
        endpoints.put(key, endpoint);
    }

    /**
     * Used by Camel Spring Web Services endpoint to unregister consumers
     */
    @Override
    public void removeConsumer(Object key) {
        endpoints.remove(key);
    }

    /**
     * Gets the configured TransformerFactory
     */
    public TransformerFactory getTransformerFactory() {
        return transformerFactory;
    }

    /**
     * Optional setter to override default TransformerFactory
     */
    public void setTransformerFactory(TransformerFactory transformerFactory) {
        this.transformerFactory = transformerFactory;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        if (transformerFactory == null) {
            transformerFactory = TransformerFactory.newInstance();
            transformerFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, Boolean.TRUE);
        }
    }

    @Override
    public final void setActorOrRole(String actorOrRole) {
        Assert.notNull(actorOrRole, "actorOrRole must not be null");
        actorsOrRoles = new String[] {actorOrRole};
    }

    @Override
    public final void setActorsOrRoles(String[] actorsOrRoles) {
        Assert.notEmpty(actorsOrRoles, "actorsOrRoles must not be empty");
        this.actorsOrRoles = actorsOrRoles;
    }

    @Override
    public final void setUltimateReceiver(boolean ultimateReceiver) {
        this.isUltimateReceiver = ultimateReceiver;
    }

}
