/**
 * 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.cxf.binding.corba;

import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.xml.namespace.QName;

import org.apache.cxf.binding.corba.types.CorbaHandlerUtils;
import org.apache.cxf.binding.corba.types.CorbaObjectHandler;
import org.apache.cxf.binding.corba.utils.ContextUtils;
import org.apache.cxf.binding.corba.utils.CorbaAnyHelper;
import org.apache.cxf.binding.corba.utils.CorbaBindingHelper;
import org.apache.cxf.binding.corba.utils.CorbaUtils;
import org.apache.cxf.binding.corba.utils.OrbConfig;
import org.apache.cxf.binding.corba.wsdl.AddressType;
import org.apache.cxf.binding.corba.wsdl.CorbaConstants;
import org.apache.cxf.binding.corba.wsdl.OperationType;
import org.apache.cxf.binding.corba.wsdl.RaisesType;
import org.apache.cxf.common.logging.LogUtils;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.io.CachedOutputStream;
import org.apache.cxf.message.Exchange;
import org.apache.cxf.message.Message;
import org.apache.cxf.message.MessageImpl;
import org.apache.cxf.service.model.BindingOperationInfo;
import org.apache.cxf.service.model.EndpointInfo;
import org.apache.cxf.service.model.ServiceInfo;
import org.apache.cxf.transport.Conduit;
import org.apache.cxf.transport.MessageObserver;
import org.apache.cxf.ws.addressing.AttributedURIType;
import org.apache.cxf.ws.addressing.EndpointReferenceType;
import org.omg.CORBA.Any;
import org.omg.CORBA.Context;
import org.omg.CORBA.ContextList;
import org.omg.CORBA.ExceptionList;
import org.omg.CORBA.NVList;
import org.omg.CORBA.NamedValue;
import org.omg.CORBA.ORB;
import org.omg.CORBA.Request;
import org.omg.CORBA.SystemException;
import org.omg.CORBA.TypeCode;
import org.omg.CORBA.UnknownUserException;

public class CorbaConduit implements Conduit {
    private static final Logger LOG = LogUtils.getL7dLogger(CorbaConduit.class);


    private EndpointInfo endpointInfo;
    private EndpointReferenceType target;
    private MessageObserver incomingObserver;
    private ORB orb;
    private OrbConfig orbConfig;
    private CorbaTypeMap typeMap;

    public CorbaConduit(EndpointInfo ei, EndpointReferenceType ref, OrbConfig config) {
        endpointInfo = ei;
        target = getTargetReference(ref);
        orbConfig = config;
        typeMap = TypeMapCache.get(ei.getService());
    }

    public OrbConfig getOrbConfig() {
        return orbConfig;
    }
    
    public synchronized void prepareOrb() {
        if (orb == null) {
            orb = CorbaBindingHelper.getDefaultORB(orbConfig);
        }
    }
    public void prepare(Message message) throws IOException {    
        try {
            prepareOrb();
            
            String address = null;
            if (target != null) {
                address = target.getAddress().getValue();
            }
            if (address == null) {
                AddressType ad = endpointInfo.getExtensor(AddressType.class);
                if (ad != null) {
                    address = ad.getLocation();
                }
            }
            String ref = (String)message.get(Message.ENDPOINT_ADDRESS);
            if (ref != null) {
                // A non-null endpoint address from the message means that we want to invoke on a particular
                // object reference specified by the endpoint reference type.  If the reference is null, then
                // we want to invoke on the default location as specified in the WSDL.
                address = ref;
            }
            if (address == null) {
                LOG.log(Level.SEVERE, "Unable to locate a valid CORBA address");
                throw new CorbaBindingException("Unable to locate a valid CORBA address");
            }
            org.omg.CORBA.Object targetObject;
            targetObject = CorbaUtils.importObjectReference(orb, address);
            message.put(CorbaConstants.ORB, orb);
            message.put(CorbaConstants.CORBA_ENDPOINT_OBJECT, targetObject);
            message.setContent(OutputStream.class,
                               new CorbaOutputStream(message));
            
            if (message instanceof CorbaMessage) {
                ((CorbaMessage)message).setCorbaTypeMap(typeMap);
            }
           
        } catch (java.lang.Exception ex) {
            LOG.log(Level.SEVERE, "Could not resolve target object");
            throw new CorbaBindingException(ex);
        }
    }

    public void close(Message message) throws IOException {
        if (message.get(CorbaConstants.CORBA_ENDPOINT_OBJECT) != null) {
            BindingOperationInfo boi = message.getExchange().getBindingOperationInfo();
            OperationType opType = boi.getExtensor(OperationType.class);
            try {
                if (message instanceof CorbaMessage) {
                    buildRequest((CorbaMessage)message, opType);            
                }
                message.getContent(OutputStream.class).close();
            } catch (Exception ex) {
                LOG.log(Level.SEVERE, "Could not build the corba request");
                throw new CorbaBindingException(ex);
            }
        }
    }

    public EndpointReferenceType getTarget() {
        return target;
    }

    public void close() {
        
    }

    public void setMessageObserver(MessageObserver observer) {
        incomingObserver = observer;
    }

    public final EndpointReferenceType getTargetReference(EndpointReferenceType t) {
        EndpointReferenceType ref = null;
        if (null == t) {
            ref = new EndpointReferenceType();
            AttributedURIType address = new AttributedURIType();
            address.setValue(getAddress());
            ref.setAddress(address);
        } else {
            ref = t;
        }
        return ref;
    }

    public final String getAddress() {
        return endpointInfo.getAddress();
    }
        
    public void buildRequest(CorbaMessage message, OperationType opType) throws Exception {        
        ServiceInfo service = message.getExchange().getEndpoint().getEndpointInfo().getService();
        NVList nvlist = getArguments(message);
        NamedValue ret = getReturn(message);
        Map<TypeCode, RaisesType> exceptions = getOperationExceptions(opType, typeMap);
        ExceptionList exList = getExceptionList(exceptions, message, opType);
        Request request = getRequest(message, opType.getName(), nvlist, ret, exList);
        if (request == null) {
            throw new CorbaBindingException("Couldn't build the corba request");
        }
        Exception ex = null;
        try {
            request.invoke();
            ex = request.env().exception();
        } catch (SystemException sysex) {
            ex = sysex;
        }
        if (ex != null) {
            if (ex instanceof SystemException) {
                message.setContent(Exception.class, new Fault(ex));
                message.setSystemException((SystemException) ex);
                return;
            }
            if (ex instanceof UnknownUserException) {
                UnknownUserException userEx = (UnknownUserException) ex;
                Any except = userEx.except;
                RaisesType raises = exceptions.get(except.type());
                if (raises == null) {
                    throw new CorbaBindingException("Couldn't find the exception type code to unmarshall");
                }
                QName elName = new QName("", raises.getException().getLocalPart());
                CorbaObjectHandler handler =
                    CorbaHandlerUtils.initializeObjectHandler(orb,
                                                              elName,
                                                              raises.getException(),
                                                              typeMap,
                                                              service);
                
                CorbaStreamable exStreamable = message.createStreamableObject(handler, elName);
                exStreamable._read(except.create_input_stream());
                message.setStreamableException(exStreamable);
                message.setContent(Exception.class, new Fault(userEx));
            } else {
                message.setContent(Exception.class, new Fault(ex));
            }
        }
    }
       
    public NVList getArguments(CorbaMessage message) {
        if (orb == null) {
            prepareOrb();
        }
        // Build the list of DII arguments, returns, and exceptions
        NVList list = null;
        if (message.getStreamableArguments() != null) {
            CorbaStreamable[] arguments = message.getStreamableArguments();
            list = orb.create_list(arguments.length);

            for (CorbaStreamable argument : arguments) {
                Any value = CorbaAnyHelper.createAny(orb);
                argument.getObject().setIntoAny(value, argument, true);
                list.add_value(argument.getName(), value, argument.getMode());
            }
        } else {
            list = orb.create_list(0);
        }

        return list;        
    }
    
    public NamedValue getReturn(CorbaMessage message) {
        if (orb == null) {
            prepareOrb();
        }
        CorbaStreamable retVal = message.getStreamableReturn();
        NamedValue ret = null;
        if (retVal != null) {
            Any returnAny = CorbaAnyHelper.createAny(orb);
            retVal.getObject().setIntoAny(returnAny, retVal, false);
            ret = orb.create_named_value(retVal.getName(), returnAny, org.omg.CORBA.ARG_OUT.value);
        } else {
            // TODO: REVISIT: for some reason,some ORBs do not like to
            // have a null NamedValue return value. Create this 'empty' 
            // one if a void return type is used.
            ret = orb.create_named_value("return", orb.create_any(), org.omg.CORBA.ARG_OUT.value);
        }
        return ret;        
    }
    
    public ExceptionList getExceptionList(Map<TypeCode, RaisesType> exceptions,
                                             CorbaMessage message, 
                                             OperationType opType) {
        if (orb == null) {
            prepareOrb();
        }

        // Get the typecodes for the exceptions this operation can throw.
        // These are defined in the operation definition from WSDL.
        ExceptionList exList = orb.create_exception_list();

               
        if (exceptions != null) {
            Object[] tcs = null;
            tcs = exceptions.keySet().toArray();
        
            for (int i = 0; i < exceptions.size(); ++i) {
                exList.add((TypeCode)tcs[i]);
            }
        }
        return exList;
    }
            
    public Request getRequest(CorbaMessage message,
                                 String opName,
                                 org.omg.CORBA.NVList nvlist, 
                                 org.omg.CORBA.NamedValue ret, 
                                 org.omg.CORBA.ExceptionList exList) 
        throws Exception {
        Request request = null;
        if (orb == null) {
            prepareOrb();
        }
        ContextList ctxList = orb.create_context_list();
        Context ctx = null;
        try {
            ctx = orb.get_default_context();            
        } catch (Exception ex) {
            //ignore?
        }

        org.omg.CORBA.Object targetObj =
            (org.omg.CORBA.Object)message.get(CorbaConstants.CORBA_ENDPOINT_OBJECT);
        if (targetObj != null) {
            request = targetObj._create_request(ctx, opName, nvlist, ret, exList, ctxList);
        }
        return request;
    }
        
    public Map<TypeCode, RaisesType> getOperationExceptions(
                                         OperationType operation, 
                                         CorbaTypeMap map) {
        if (orb == null) {
            prepareOrb();
        }
        Map<TypeCode, RaisesType> exceptions = new HashMap<TypeCode, RaisesType>();
        List<RaisesType> exList = operation.getRaises(); 
        if (exList != null) {
            for (int i = 0; i < exList.size(); ++i) {
                RaisesType ex = exList.get(i);
                TypeCode tc = CorbaUtils.getTypeCode(orb, ex.getException(), map);
                exceptions.put(tc, ex);
            }
        }

        return exceptions;
    }
    
    private class CorbaOutputStream extends CachedOutputStream {
       
        private Message message;
        private boolean isOneWay;

        CorbaOutputStream(Message m) {
            message = m;        
        }

        /**
         * Perform any actions required on stream flush (freeze headers, reset
         * output stream ... etc.)
         */
        public void doFlush() throws IOException {
            // do nothing here
        }

        /**
         * Perform any actions required on stream closure (handle response etc.)
         */
        public void doClose() throws IOException {            
            if (ContextUtils.isRequestor(message) && ContextUtils.isOutbound(message)) {
                try {
                    isOneWay = message.getExchange().isOneWay();
                    
                    if (!isOneWay) {                
                        handleResponse();
                    }
                } catch (Exception ex) {
                    LOG.log(Level.WARNING, "Connection failed with Exception : ", ex);
                    throw new IOException(ex.toString());
                }            
            }
        }

        public void onWrite() throws IOException {

        }

        public void handleResponse() throws IOException {
            LOG.log(Level.FINE, "incoming observer is " + incomingObserver);
            Exchange exchange = message.getExchange();
            CorbaMessage corbaMsg = (CorbaMessage) message;
            MessageImpl inMessage = new MessageImpl();
            CorbaDestination destination = new CorbaDestination(endpointInfo, orbConfig, typeMap);
            inMessage.setDestination(destination);
            exchange.put(ORB.class, orb);
            inMessage.setExchange(exchange);
            CorbaMessage inCorbaMsg = new CorbaMessage(inMessage);       
            inCorbaMsg.setCorbaTypeMap(typeMap);
            if (corbaMsg.getStreamableException() != null) {
                exchange.setInFaultMessage(corbaMsg);
                inCorbaMsg.setStreamableException(corbaMsg.getStreamableException());
            } else if (corbaMsg.getSystemException() != null) {
                exchange.setInFaultMessage(corbaMsg);
                inCorbaMsg.setSystemException(corbaMsg.getSystemException());
            }
            LOG.log(Level.FINE, "incoming observer is " + incomingObserver);
            incomingObserver.onMessage(inCorbaMsg);
            message.setContent(Exception.class, inCorbaMsg.getContent(Exception.class));
        }

    }

    public MessageObserver getMessageObserver() {
        return this.incomingObserver;
    }
}
