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

import java.util.HashMap;

import javax.xml.namespace.QName;

import org.apache.axiom.soap.SOAPBody;
import org.apache.axiom.soap.SOAPEnvelope;
import org.apache.axiom.util.UIDGenerator;
import org.apache.axis2.AxisFault;
import org.apache.axis2.Constants;
import org.apache.axis2.addressing.AddressingConstants;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.client.OperationClient;
import org.apache.axis2.client.Options;
import org.apache.axis2.client.async.AxisCallback;
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.engine.AxisEngine;
import org.apache.axis2.i18n.Messages;
import org.apache.axis2.transport.TransportUtils;
import org.apache.axis2.transport.http.HTTPConstants;
import org.apache.axis2.util.CallbackReceiver;
import org.apache.axis2.util.Utils;
import org.apache.axis2.wsdl.WSDLConstants;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class OutInAxisOperation extends TwoChannelAxisOperation {

    private static final Log log = LogFactory.getLog(OutInAxisOperation.class);

    public OutInAxisOperation() {
        super();
        //setup a temporary name
        QName tmpName = new QName(this.getClass().getName() + "_" + UIDGenerator.generateUID());
        this.setName(tmpName);
        setMessageExchangePattern(WSDL2Constants.MEP_URI_OUT_IN);
    }

    public OutInAxisOperation(QName name) {
        super(name);
        setMessageExchangePattern(WSDL2Constants.MEP_URI_OUT_IN);
    }

    public void addMessageContext(MessageContext msgContext,
                                  OperationContext opContext) throws AxisFault {
        HashMap<String, MessageContext> mep = opContext.getMessageContexts();
        MessageContext immsgContext = (MessageContext) mep
                .get(MESSAGE_LABEL_IN_VALUE);
        MessageContext outmsgContext = (MessageContext) mep
                .get(MESSAGE_LABEL_OUT_VALUE);

        if ((immsgContext != null) && (outmsgContext != null)) {
            throw new AxisFault(Messages.getMessage("mepcompleted"));
        }

        if (outmsgContext == null) {
            mep.put(MESSAGE_LABEL_OUT_VALUE, msgContext);
        } else {
            mep.put(MESSAGE_LABEL_IN_VALUE, msgContext);
            opContext.setComplete(true);
            opContext.cleanup();
        }
    }

    /**
     * Returns a MEP client for an Out-IN operation. This client can be used to
     * interact with a server which is offering an In-Out operation. To use the
     * client, you must call addMessageContext() with a message context and then
     * call execute() to execute the client.
     *
     * @param sc      The service context for this client to live within. Cannot be
     *                null.
     * @param options Options to use as defaults for this client. If any options are
     *                set specifically on the client then those override options
     *                here.
     */
    public OperationClient createClient(ServiceContext sc, Options options) {
        return new OutInAxisOperationClient(this, sc, options);
    }
}

/**
 * MEP client for moi.
 */
class OutInAxisOperationClient extends OperationClient {

    private static Log log = LogFactory.getLog(OutInAxisOperationClient.class);

    OutInAxisOperationClient(OutInAxisOperation axisOp, ServiceContext sc,
                             Options options) {
        super(axisOp, sc, options);
    }

    /**
     * Adds message context to operation context, so that it will handle the
     * logic correctly if the OperationContext is null then new one will be
     * created, and Operation Context will become null when some one calls reset().
     *
     * @param msgContext the MessageContext to add
     * @throws AxisFault
     */
    public void addMessageContext(MessageContext msgContext) throws AxisFault {
        msgContext.setServiceContext(sc);
        if (msgContext.getMessageID() == null) {
            setMessageID(msgContext);
        }
        axisOp.registerOperationContext(msgContext, oc);
    }

    /**
     * Returns the message context for a given message label.
     *
     * @param messageLabel :
     *                     label of the message and that can be either "Out" or "In" and
     *                     nothing else
     * @return Returns MessageContext.
     * @throws AxisFault
     */
    public MessageContext getMessageContext(String messageLabel)
            throws AxisFault {
        return oc.getMessageContext(messageLabel);
    }

    

    /**
     * Executes the MEP. What this does depends on the specific MEP client. The
     * basic idea is to have the MEP client execute and do something with the
     * messages that have been added to it so far. For example, if its an Out-In
     * MEP, then if the Out message has been set, then executing the client asks
     * it to send the message and get the In message, possibly using a different
     * thread.
     *
     * @param block Indicates whether execution should block or return ASAP. What
     *              block means is of course a function of the specific MEP
     *              client. IGNORED BY THIS MEP CLIENT.
     * @throws AxisFault if something goes wrong during the execution of the MEP.
     */
    public void executeImpl(boolean block) throws AxisFault {
        if (log.isDebugEnabled()) {
            log.debug("Entry: OutInAxisOperationClient::execute, " + block);
        }
        if (completed) {
            throw new AxisFault(Messages.getMessage("mepiscomplted"));
        }
        ConfigurationContext cc = sc.getConfigurationContext();

        // copy interesting info from options to message context.
        MessageContext mc = oc.getMessageContext(WSDLConstants.MESSAGE_LABEL_OUT_VALUE);
        if (mc == null) {
            throw new AxisFault(Messages.getMessage("outmsgctxnull"));
        }
        prepareMessageContext(cc, mc);

        if (options.getTransportIn() == null && mc.getTransportIn() == null) {
            mc.setTransportIn(ClientUtils.inferInTransport(cc
                    .getAxisConfiguration(), options, mc));
        } else if (mc.getTransportIn() == null) {
            mc.setTransportIn(options.getTransportIn());
        }

        /**
         * If a module has set the USE_ASYNC_OPERATIONS option then we override the behaviour
         * for sync calls, and effectively USE_CUSTOM_LISTENER too. However we leave real
         * async calls alone.
         */
        boolean useAsync = false;
        if (!mc.getOptions().isUseSeparateListener()) {
            Boolean useAsyncOption =
                    (Boolean) mc.getProperty(Constants.Configuration.USE_ASYNC_OPERATIONS);
            if (log.isDebugEnabled()) log.debug("OutInAxisOperationClient: useAsyncOption " + useAsyncOption);
            if (useAsyncOption != null) {
                useAsync = useAsyncOption.booleanValue();
            }
        }

        EndpointReference replyTo = mc.getReplyTo();
        if (replyTo != null) {
            if (replyTo.hasNoneAddress()) {
                throw new AxisFault( replyTo.getAddress() + "" +
                        " can not be used with OutInAxisOperationClient , user either "
                        + "fireAndForget or sendRobust)");
            }
            else if (replyTo.isWSAddressingAnonymous() &&
                     replyTo.getAllReferenceParameters() != null) {
                mc.setProperty(AddressingConstants.INCLUDE_OPTIONAL_HEADERS, Boolean.TRUE);
            }
            
            String customReplyTo = (String)options.getProperty(Options.CUSTOM_REPLYTO_ADDRESS);
            if ( ! (Options.CUSTOM_REPLYTO_ADDRESS_TRUE.equals(customReplyTo))) {
                if (!replyTo.hasAnonymousAddress()){
                    useAsync = true;
                }
            }
        }

        if (useAsync || mc.getOptions().isUseSeparateListener()) {
            sendAsync(useAsync, mc);
        } else {
            if (block) {
                // Send the SOAP Message and receive a response
                send(mc);
                completed = true;
            } else {
                sc.getConfigurationContext().getThreadPool().execute(
                        new NonBlockingInvocationWorker(mc, axisCallback));
            }
        }
    }

    private void sendAsync(boolean useAsync, MessageContext mc)
            throws AxisFault {
        if (log.isDebugEnabled()) {
            log.debug("useAsync=" + useAsync + ", seperateListener=" +
                    mc.getOptions().isUseSeparateListener());
        }
        /**
         * We are following the async path. If the user hasn't set a callback object then we must
         * block until the whole MEP is complete, as they have no other way to get their reply message.
         */
        // THREADSAFE issue: Multiple threads could be trying to initialize the callback receiver
        // so it is synchronized.  It is not done within the else clause to avoid the 
        // double-checked lock antipattern.
        CallbackReceiver callbackReceiver;
        synchronized (axisOp) {
            if (axisOp.getMessageReceiver() != null &&
                    axisOp.getMessageReceiver() instanceof CallbackReceiver) {
                callbackReceiver = (CallbackReceiver) axisOp.getMessageReceiver();
            } else {
                if (log.isDebugEnabled()) {
                    log.debug("Creating new callback receiver");
                }
                callbackReceiver = new CallbackReceiver();
                axisOp.setMessageReceiver(callbackReceiver);
                if (log.isDebugEnabled()) log.debug("OutInAxisOperation: callbackReceiver " + callbackReceiver + " : " + axisOp);
            }
        }

        SyncCallBack internalCallback = null;
        if (axisCallback != null) {
            callbackReceiver.addCallback(mc.getMessageID(), axisCallback);  
            if (log.isDebugEnabled()) log.debug("OutInAxisOperationClient: Creating axis callback");            
        } else {
            if (log.isDebugEnabled()) {
                log.debug("Creating internal callback");
            }
            internalCallback = new SyncCallBack();
            callbackReceiver.addCallback(mc.getMessageID(), internalCallback);
            if (log.isDebugEnabled()) log.debug("OutInAxisOperationClient: Creating internal callback");
        }

        /**
         * If USE_CUSTOM_LISTENER is set to 'true' the replyTo value will not be replaced and Axis2 will not
         * start its internal listner. Some other enntity (e.g. a module) should take care of obtaining the
         * response message.
         */
        Boolean useCustomListener =
                (Boolean) options.getProperty(Constants.Configuration.USE_CUSTOM_LISTENER);
        if (useAsync) {
            useCustomListener = Boolean.TRUE;
        }
        if (useCustomListener == null || !useCustomListener.booleanValue()) {
            EndpointReference replyTo = mc.getReplyTo();
            if (replyTo == null || replyTo.hasAnonymousAddress()){
                EndpointReference replyToFromTransport =
                        mc.getConfigurationContext().getListenerManager().
                                getEPRforService(sc.getAxisService().getName(),
                                        axisOp.getName().getLocalPart(), mc
                                        .getTransportIn().getName());

                if (replyTo == null) {
                    mc.setReplyTo(replyToFromTransport);
                } else {
                    replyTo.setAddress(replyToFromTransport.getAddress());
                }
            }
        }

        //if we don't do this , this guy will wait till it gets HTTP 202 in the HTTP case
        mc.setProperty(MessageContext.CLIENT_API_NON_BLOCKING, Boolean.TRUE);
        mc.getConfigurationContext().registerOperationContext(mc.getMessageID(), oc);
        AxisEngine.send(mc);
        if (internalCallback != null) {
            internalCallback.waitForCompletion(options.getTimeOutInMilliSeconds());

            // process the result of the invocation
            if (internalCallback.envelope == null) {
                if (internalCallback.error == null) {
                    log.error("Callback had neither error nor response");
                }
                if (options.isExceptionToBeThrownOnSOAPFault()) {
                    throw AxisFault.makeFault(internalCallback.error);
                }
            }
        }
    }

    /**
     * When synchronous send() gets back a response MessageContext, this is the workhorse
     * method which processes it.
     *
     * @param responseMessageContext the active response MessageContext
     * @throws AxisFault if something went wrong
     */
    protected void handleResponse(MessageContext responseMessageContext) throws AxisFault{
        // Options object reused above so soapAction needs to be removed so
        // that soapAction+wsa:Action on response don't conflict
        responseMessageContext.setSoapAction(null);

        if (responseMessageContext.getEnvelope() == null) {
            // If request is REST we assume the responseMessageContext is REST, so
            // set the variable
            /*
             * old code here was using the outbound message context to set the inbound SOAP namespace,
             * as such and passing it to TransportUtils.createSOAPMessage
             *
             * msgctx.getEnvelope().getNamespace().getNamespaceURI()
             *
             * However, the SOAP1.2 spec, appendix A indicates that if a SOAP1.2 message is sent to a SOAP1.1
             * endpoint, we will get a SOAP1.1 (fault) message response.  We need another way to set
             * the inbound SOAP version.  Best way to do this is to trust the content type and let
             * createSOAPMessage take care of figuring out what the SOAP namespace is.
             */
            SOAPEnvelope resenvelope = TransportUtils.createSOAPMessage(responseMessageContext);
            if (resenvelope != null) {
                responseMessageContext.setEnvelope(resenvelope);
            } else {
                throw new AxisFault(Messages
                        .getMessage("blockingInvocationExpectsResponse"));
            }
        }
        SOAPEnvelope resenvelope = responseMessageContext.getEnvelope();
        if (resenvelope != null) {
            AxisEngine.receive(responseMessageContext);
            if (responseMessageContext.getReplyTo() != null) {
                sc.setTargetEPR(responseMessageContext.getReplyTo());
            }

            // rampart handlers change the envelope and set the decrypted envelope
            // so need to check the new one else resenvelope.hasFault() become false.
            resenvelope = responseMessageContext.getEnvelope();
            if (resenvelope.hasFault()||responseMessageContext.isProcessingFault()) {
                if (options.isExceptionToBeThrownOnSOAPFault()) {
                    // does the SOAPFault has a detail element for Excpetion
                    throw Utils.getInboundFaultFromMessageContext(responseMessageContext);
                }
            }
        }
    }

    /**
     * Synchronously send the request and receive a response.  This relies on the transport
     * correctly connecting the response InputStream!
     *
     * @param msgContext the request MessageContext to send.
     * @return Returns MessageContext.
     * @throws AxisFault Sends the message using a two way transport and waits for a response
     */
    protected MessageContext send(MessageContext msgContext) throws AxisFault {

        // create the responseMessageContext

        MessageContext responseMessageContext =
                msgContext.getConfigurationContext().createMessageContext();

        responseMessageContext.setServerSide(false);
        responseMessageContext.setOperationContext(msgContext.getOperationContext());
        responseMessageContext.setOptions(new Options(options));
        responseMessageContext.setMessageID(msgContext.getMessageID());
        addMessageContext(responseMessageContext);
        responseMessageContext.setServiceContext(msgContext.getServiceContext());
        responseMessageContext.setAxisMessage(
                axisOp.getMessage(WSDLConstants.MESSAGE_LABEL_IN_VALUE));

        //sending the message
        AxisEngine.send(msgContext);

        responseMessageContext.setDoingREST(msgContext.isDoingREST());

        // Copy RESPONSE properties which the transport set onto the request message context when it processed
        // the incoming response recieved in reply to an outgoing request.
        responseMessageContext.setProperty(MessageContext.TRANSPORT_HEADERS, 
                                           msgContext.getProperty(MessageContext.TRANSPORT_HEADERS));
        responseMessageContext.setProperty(HTTPConstants.MC_HTTP_STATUS_CODE,
                                           msgContext.getProperty(HTTPConstants.MC_HTTP_STATUS_CODE));

        responseMessageContext.setProperty(MessageContext.TRANSPORT_IN, msgContext
                .getProperty(MessageContext.TRANSPORT_IN));
        responseMessageContext.setTransportIn(msgContext.getTransportIn());
        responseMessageContext.setTransportOut(msgContext.getTransportOut());
        handleResponse(responseMessageContext);
        return responseMessageContext;
    }

    /**
     * This class is the workhorse for a non-blocking invocation that uses a two
     * way transport.
     */
    private class NonBlockingInvocationWorker implements Runnable {
        private MessageContext msgctx;
        private AxisCallback axisCallback;

        public NonBlockingInvocationWorker(MessageContext msgctx ,
                                           AxisCallback axisCallback) {            
            this.msgctx = msgctx;
            this.axisCallback =axisCallback;
        }

        public void run() {
            try {
                // send the request and wait for response
                MessageContext response = send(msgctx);
                // call the callback
                if (response != null) {
                    SOAPEnvelope resenvelope = response.getEnvelope();
                    
                    if (resenvelope.hasFault()) {
                        SOAPBody body = resenvelope.getBody();
                        // If a fault was found, create an AxisFault with a MessageContext so that
                        // other programming models can deserialize the fault to an alternative form.
                        AxisFault fault = new AxisFault(body.getFault(), response);
                        if (axisCallback != null) {
                            if (options.isExceptionToBeThrownOnSOAPFault()) {
                                axisCallback.onError(fault);
                            } else {
                                axisCallback.onFault(response);
                            }
                        }

                    } else {
                        if (axisCallback != null) {
                            axisCallback.onMessage(response);
                        }

                    }
                }

            } catch (Exception e) {
                if (axisCallback != null) {
                    axisCallback.onError(e);
                }

            } finally {
                if (axisCallback != null) {
                    axisCallback.onComplete();
                }
            }
        }
    }

    /**
     * This class acts as a callback that allows users to wait on the result.
     */
    private class SyncCallBack implements AxisCallback {
        boolean complete;
        boolean receivedFault;

        public boolean waitForCompletion(long timeout) throws AxisFault {
            synchronized (this) {
                try {
                    if (complete) return !receivedFault;
                    wait(timeout);
                    if (!complete) {
                        // We timed out!
                        throw new AxisFault( Messages.getMessage("responseTimeOut"));
                    }
                } catch (InterruptedException e) {
                    // Something interrupted our wait!
                    error = e;
                }
            }

            if (error != null) throw AxisFault.makeFault(error);

            return !receivedFault;
        }

        /**
         * This is called when we receive a message.
         *
         * @param msgContext the (response) MessageContext
         */
        public void onMessage(MessageContext msgContext) {
            // Transport input stream gets closed after calling setComplete
            // method. Have to build the whole envelope including the
            // attachments at this stage. Data might get lost if the input
            // stream gets closed before building the whole envelope.

            // TODO: Shouldn't need to do this - need to hook up stream closure to Axiom completion
            this.envelope = msgContext.getEnvelope();
            this.envelope.buildWithAttachments();
        }

        /**
         * This gets called when a fault message is received.
         *
         * @param msgContext the MessageContext containing the fault.
         */
        public void onFault(MessageContext msgContext) {
           error = Utils.getInboundFaultFromMessageContext(msgContext);
        }

        /**
         * This is called at the end of the MEP no matter what happens, quite like a
         * finally block.
         */
        public synchronized void onComplete() {
            complete = true;
            notify();
        }

        private SOAPEnvelope envelope;

        private Exception error;

        public void onError(Exception e) {
            if (log.isDebugEnabled()) {
                log.debug("Entry: OutInAxisOperationClient$SyncCallBack::onError, " + e);
            }
            error = e;
            if (log.isDebugEnabled()) {
                log.debug("Exit: OutInAxisOperationClient$SyncCallBack::onError");
            }
        }
    }

}
