/*
 * 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.axis2.engine;

import org.apache.axiom.om.OMElement;
import org.apache.axiom.soap.SOAPHeader;
import org.apache.axis2.AxisFault;
import org.apache.axis2.Constants;
import org.apache.axis2.addressing.AddressingHelper;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.context.OperationContext;
import org.apache.axis2.context.ServiceContext;
import org.apache.axis2.context.ServiceGroupContext;
import org.apache.axis2.context.SessionContext;
import org.apache.axis2.description.AxisOperation;
import org.apache.axis2.description.AxisService;
import org.apache.axis2.description.AxisServiceGroup;
import org.apache.axis2.description.Parameter;
import org.apache.axis2.description.WSDL2Constants;
import org.apache.axis2.i18n.Messages;
import org.apache.axis2.transport.RequestResponseTransport;
import org.apache.axis2.transport.TransportListener;
import org.apache.axis2.transport.http.HTTPConstants;
import org.apache.axis2.util.JavaUtils;
import org.apache.axis2.wsdl.WSDLConstants.WSDL20_2004_Constants;
import org.apache.axis2.wsdl.WSDLConstants.WSDL20_2006Constants;

import javax.xml.namespace.QName;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class DispatchPhase extends Phase {

    public DispatchPhase() {
    }

    public DispatchPhase(String phaseName) {
        super(phaseName);
    }
    
    
    private Boolean getDisableAck(MessageContext msgContext) throws AxisFault {
    
       // We should send an early ack to the transport whever possible, but some modules need
       // to use the backchannel, so we need to check if they have disabled this code.
       Boolean disableAck = (Boolean) msgContext.getProperty(Constants.Configuration.DISABLE_RESPONSE_ACK);
       if(disableAck == null) {
          disableAck = (Boolean) (msgContext.getAxisService() != null ? msgContext.getAxisService().getParameterValue(Constants.Configuration.DISABLE_RESPONSE_ACK) : null);
       }    
       
       return disableAck;
    }

    public void checkPostConditions(MessageContext msgContext) throws AxisFault {
        EndpointReference toEPR = msgContext.getTo();

        if (msgContext.getAxisService() == null) {
            AxisFault fault = new AxisFault(Messages.getMessage("servicenotfoundforepr",
                                                    ((toEPR != null) ? toEPR.getAddress() : "")));
            fault.setFaultCode(org.apache.axis2.namespace.Constants.FAULT_CLIENT);
            throw fault;
        }

        AxisService service = msgContext.getAxisService();
        AxisOperation operation = msgContext.getAxisOperation();
        
        // If operation is an excluded operation, throw an exception.
        // This code is needed to enable exclude operations for static WSDL files. 
        // Without this code, if one specifies excludeOperations in services.xml
        // file and a static WSDL is used that contains the operation, 
        // the operation would succeed.
        if (operation != null 
                && service.isExcludedOperation(operation.getName().getLocalPart())) {
            AxisFault fault = new AxisFault(Messages.getMessage("operationnotfoundforepr2",
                    ((toEPR != null) ? toEPR.getAddress()
                            : ""), msgContext.getWSAAction()));
            fault.setFaultCode(org.apache.axis2.namespace.Constants.FAULT_CLIENT);
            throw fault;
        }

        // If we're configured to do so, check the service for a single op...
        if (operation == null &&
                JavaUtils.isTrue(service.getParameterValue(AxisService.SUPPORT_SINGLE_OP))) {
            Iterator<AxisOperation> ops = service.getOperations();
            // If there's exactly one, that's the one we want.  If there's more, forget it.
            if (ops.hasNext()) {
                operation = (AxisOperation)ops.next();
                if (ops.hasNext()) {
                    operation = null;
                }
            }
            msgContext.setAxisOperation(operation);
        }

        // If we still don't have an operation, fault.
        if (operation == null) {
            AxisFault fault = new AxisFault(Messages.getMessage("operationnotfoundforepr2",
                                                    ((toEPR != null) ? toEPR.getAddress()
                                                            : ""), msgContext.getWSAAction()));
            fault.setFaultCode(org.apache.axis2.namespace.Constants.FAULT_CLIENT);
            throw fault;
        }

        validateTransport(msgContext);
        
        validateBindings(msgContext);

        loadContexts(service, msgContext);

        if (msgContext.getOperationContext() == null) {
            throw new AxisFault(Messages.getMessage("cannotBeNullOperationContext"));
        }

        if (msgContext.getServiceContext() == null) {
            throw new AxisFault(Messages.getMessage("cannotBeNullServiceContext"));
        }

        // TODO - review this
        if ((msgContext.getAxisOperation() == null) && (msgContext.getOperationContext() != null)) {
            msgContext.setAxisOperation(msgContext.getOperationContext().getAxisOperation());
        }

        if ((msgContext.getAxisService() == null) && (msgContext.getServiceContext() != null)) {
            msgContext.setAxisService(msgContext.getServiceContext().getAxisService());
        }

        // We should send an early ack to the transport whever possible, but some modules need
        // to use the backchannel, so we need to check if they have disabled this code.
        String mepString = msgContext.getAxisOperation().getMessageExchangePattern();

        if (isOneway(mepString)) {
            Object requestResponseTransport = msgContext.getProperty(RequestResponseTransport.TRANSPORT_CONTROL);
            if (requestResponseTransport != null) {

                Boolean disableAck = getDisableAck(msgContext);                    
                if (disableAck == null || disableAck.booleanValue() == false) {
                    ((RequestResponseTransport) requestResponseTransport).acknowledgeMessage(msgContext);
                }
            }
        } else if (AddressingHelper.isReplyRedirected(msgContext) && AddressingHelper.isFaultRedirected(msgContext)) {


            if (mepString.equals(WSDL20_2006Constants.MEP_URI_IN_OUT)
                    || mepString.equals(WSDL20_2004_Constants.MEP_URI_IN_OUT)
                    || mepString.equals(WSDL2Constants.MEP_URI_IN_OUT)) { 
                // OR, if 2 way operation but the response is intended to not use the response channel of a 2-way transport
                // then we don't need to keep the transport waiting.

                Object requestResponseTransport = msgContext.getProperty(RequestResponseTransport.TRANSPORT_CONTROL);
                if (requestResponseTransport != null) {

                    // We should send an early ack to the transport whever possible, but some modules need
                    // to use the backchannel, so we need to check if they have disabled this code.
                    Boolean disableAck = getDisableAck(msgContext);

                    if (disableAck == null || disableAck.booleanValue() == false) {
                        ((RequestResponseTransport) requestResponseTransport).acknowledgeMessage(msgContext);
                    }
                    
                }
            }        
        }
        

        ArrayList operationChain = msgContext.getAxisOperation().getRemainingPhasesInFlow();
        msgContext.setExecutionChain((ArrayList) operationChain.clone());
    }

    private void loadContexts(AxisService service, MessageContext msgContext) throws AxisFault {
        String scope = service == null ? null : service.getScope();
        ServiceContext serviceContext = msgContext.getServiceContext();

        if ((msgContext.getOperationContext() != null)
                && (serviceContext != null)) {
            msgContext.setServiceGroupContextId(
                    ((ServiceGroupContext)serviceContext.getParent()).getId());
            return;
        }
        if (Constants.SCOPE_TRANSPORT_SESSION.equals(scope)) {
            fillContextsFromSessionContext(msgContext);
        } else if (Constants.SCOPE_SOAP_SESSION.equals(scope)) {
            extractServiceGroupContextId(msgContext);
        }

        AxisOperation axisOperation = msgContext.getAxisOperation();
//        if (axisOperation == null) {
//            return;
//        }
        OperationContext operationContext =
                axisOperation.findForExistingOperationContext(msgContext);

        if (operationContext != null) {
            // register operation context and message context
//            axisOperation.registerOperationContext(msgContext, operationContext);
            axisOperation.registerMessageContext(msgContext, operationContext);

            serviceContext = (ServiceContext) operationContext.getParent();
            ServiceGroupContext serviceGroupContext =
                    (ServiceGroupContext) serviceContext.getParent();

            msgContext.setServiceContext(serviceContext);
            msgContext.setServiceGroupContext(serviceGroupContext);
            msgContext.setServiceGroupContextId(serviceGroupContext.getId());
        } else {    // 2. if null, create new opCtxt
            if (serviceContext == null) {
                // fill the service group context and service context info
                msgContext.getConfigurationContext().
                        fillServiceContextAndServiceGroupContext(msgContext);
                serviceContext = msgContext.getServiceContext();
            }
            operationContext = serviceContext.createOperationContext(axisOperation);
            axisOperation.registerMessageContext(msgContext, operationContext);
        }

        serviceContext.setMyEPR(msgContext.getTo());
    }

    /**
     * To check whether the incoming request has come in valid transport , simply the transports
     * that service author wants to expose
     *
     * @param msgctx the current MessageContext
     * @throws AxisFault in case of error
     */
    private void validateTransport(MessageContext msgctx) throws AxisFault {
        AxisService service = msgctx.getAxisService();
        if (service.isEnableAllTransports()) {
            return;
        } else {
            List trs = service.getExposedTransports();
            String incomingTrs = msgctx.getIncomingTransportName();

            //local transport is a special case, it need not be exposed.
            if (Constants.TRANSPORT_LOCAL.equals(incomingTrs)) {
                return;
            }

            for (int i = 0; i < trs.size(); i++) {
                String tr = (String) trs.get(i);
                if (incomingTrs != null && incomingTrs.equals(tr)) {
                    return;
                }
            }
        }
        EndpointReference toEPR = msgctx.getTo();
        throw new AxisFault(Messages.getMessage("servicenotfoundforepr",
                                                ((toEPR != null) ? toEPR.getAddress() : "")));
    }
    
    /**
     * To check whether the incoming request has come in valid binding , we check whether service
     * author has disabled any binding using parameters
     * <code>org.apache.axis2.Constants.Configuration.DISABLE_SOAP12</code>
     * <code>org.apache.axis2.Constants.Configuration.DISABLE_SOAP11</code>
     * <code>org.apache.axis2.Constants.Configuration.DISABLE_REST</code>
     * @param service msgctx the current MessageContext
     * @throws AxisFault in case of error
     */
    private void validateBindings(MessageContext msgctx) throws AxisFault {
        
        AxisService service = msgctx.getAxisService();        
   
        if (msgctx.isDoingREST()) {
            
            boolean disableREST = false;
            Parameter disableRESTParameter = service
                            .getParameter(org.apache.axis2.Constants.Configuration.DISABLE_REST);
            if (disableRESTParameter != null
                            && JavaUtils.isTrueExplicitly(disableRESTParameter.getValue())) {
                    disableREST = true;
            }         
            
            if (disableREST) {
                throw new AxisFault(Messages.getMessage("bindingDisabled","Http"));
            }
        } else if (msgctx.isSOAP11()) {

            boolean disableSOAP11 = false;
            Parameter disableSOAP11Parameter = service
                            .getParameter(org.apache.axis2.Constants.Configuration.DISABLE_SOAP11);
            if (disableSOAP11Parameter != null
                            && JavaUtils.isTrueExplicitly(disableSOAP11Parameter.getValue())) {
                    disableSOAP11 = true;
            }         
         
            if (disableSOAP11) {
                throw new AxisFault(Messages.getMessage("bindingDisabled","SOAP11"));
            }
        } else {
         
            boolean disableSOAP12 = false;
            Parameter disableSOAP12Parameter = service
                            .getParameter(org.apache.axis2.Constants.Configuration.DISABLE_SOAP12);
            if (disableSOAP12Parameter != null
                            && JavaUtils
                                            .isTrueExplicitly(disableSOAP12Parameter.getValue())) {
                    disableSOAP12 = true;
            }         
         
            if(disableSOAP12) {
                throw new AxisFault(Messages.getMessage("bindingDisabled","SOAP12"));  
            }
        }
    }

    private void fillContextsFromSessionContext(MessageContext msgContext) throws AxisFault {
        AxisService service = msgContext.getAxisService();
        if (service == null) {
            throw new AxisFault(Messages.getMessage("unabletofindservice"));
        }
        SessionContext sessionContext = msgContext.getSessionContext();
        if (sessionContext == null) {
            TransportListener listener = msgContext.getTransportIn().getReceiver();
            sessionContext = listener.getSessionContext(msgContext);
            if (sessionContext == null) {
                createAndFillContexts(service, msgContext, sessionContext);
                return;
            }
        }
        String serviceGroupName = msgContext.getAxisServiceGroup().getServiceGroupName();
        ServiceGroupContext serviceGroupContext =
                sessionContext.getServiceGroupContext(serviceGroupName);
        if (serviceGroupContext != null) {
            //setting service group context
            msgContext.setServiceGroupContext(serviceGroupContext);
            // setting Service context
            msgContext.setServiceContext(serviceGroupContext.getServiceContext(service));
        } else {
            createAndFillContexts(service, msgContext, sessionContext);
        }
        ServiceContext serviceContext = sessionContext.getServiceContext(service);
        //found the serviceContext from session context , so adding that into msgContext
        if (serviceContext != null) {
            msgContext.setServiceContext(serviceContext);
            serviceContext.setProperty(HTTPConstants.COOKIE_STRING, sessionContext.getCookieID());
        }
    }

    private void createAndFillContexts(AxisService service,
                                       MessageContext msgContext,
                                       SessionContext sessionContext) throws AxisFault {
        ServiceGroupContext serviceGroupContext;
        AxisServiceGroup axisServiceGroup = service.getAxisServiceGroup();
        ConfigurationContext configCtx = msgContext.getConfigurationContext();
        serviceGroupContext = configCtx.createServiceGroupContext(axisServiceGroup);

        msgContext.setServiceGroupContext(serviceGroupContext);
        ServiceContext serviceContext = serviceGroupContext.getServiceContext(service);
        msgContext.setServiceContext(serviceContext);
        if (sessionContext != null) {
            sessionContext.addServiceContext(serviceContext);
            sessionContext.addServiceGroupContext(serviceGroupContext);
        }
    }

    private static final QName SERVICE_GROUP_QNAME = new QName(Constants.AXIS2_NAMESPACE_URI,
                                                               Constants.SERVICE_GROUP_ID,
                                                               Constants.AXIS2_NAMESPACE_PREFIX);

    private void extractServiceGroupContextId(MessageContext msgContext) throws AxisFault {
        SOAPHeader soapHeader = msgContext.getEnvelope().getHeader();
        if (soapHeader != null) {
            OMElement serviceGroupId = soapHeader.getFirstChildWithName(SERVICE_GROUP_QNAME);
            if (serviceGroupId != null) {
                msgContext.setServiceGroupContextId(serviceGroupId.getText());
            }
        }
    }
    
    /**
     * This method will determine if the MEP indicated by 'mepString' specifies
     * a oneway MEP.
     */
    @SuppressWarnings("deprecation")
    boolean isOneway(String mepString) {
        return (mepString.equals(WSDL20_2006Constants.MEP_URI_IN_ONLY)
                || mepString.equals(WSDL20_2004_Constants.MEP_URI_IN_ONLY)
                || mepString.equals(WSDL2Constants.MEP_URI_IN_ONLY));
    }

}