/*
 * 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.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

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

public class DispatchPhase extends Phase {
    private static final Log log = LogFactory.getLog(DispatchPhase.class);

    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);
            Integer not_found = HttpServletResponse.SC_NOT_FOUND;
            msgContext.setProperty(Constants.HTTP_RESPONSE_STATE, not_found.toString());
            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(WSDL2Constants.MEP_URI_IN_OUT)
                    || mepString.equals(WSDL2Constants.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;
            }

            if (log.isDebugEnabled()) {
                log.debug("Incoming transport: " + incomingTrs + "; allowed transports: " + trs);
            }
            
            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(WSDL2Constants.MEP_URI_IN_ONLY)
                || mepString.equals(WSDL2Constants.MEP_URI_IN_ONLY)
                || mepString.equals(WSDL2Constants.MEP_URI_IN_ONLY));
    }

}
