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

import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMNamespace;
import org.apache.axiom.om.OMText;
import org.apache.axiom.om.impl.builder.StAXOMBuilder;
import org.apache.axiom.om.impl.llom.factory.OMXMLBuilderFactory;
import org.apache.axiom.om.util.Base64;
import org.apache.axiom.soap.SOAPEnvelope;
import org.apache.axiom.soap.SOAPFactory;
import org.apache.axis2.AxisFault;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.databinding.typemapping.SimpleTypeMapper;
import org.apache.axis2.databinding.utils.BeanUtil;
import org.apache.axis2.databinding.utils.reader.NullXMLStreamReader;
import org.apache.axis2.description.AxisMessage;
import org.apache.axis2.description.AxisService;
import org.apache.axis2.description.java2wsdl.TypeTable;
import org.apache.axis2.engine.ObjectSupplier;
import org.apache.axis2.util.StreamWrapper;

import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamReader;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Iterator;

public class RPCUtil {

    private static String RETURN_WRAPPER = "return";

    public static void processResponse(SOAPFactory fac, Object resObject,
                                       OMElement bodyContent,
                                       OMNamespace ns,
                                       SOAPEnvelope envelope,
                                       Method method,
                                       boolean qualified,
                                       TypeTable typeTable) {
        if (resObject != null) {
            //simple type
            if (resObject instanceof OMElement) {
                OMElement result = (OMElement) resObject;
                bodyContent = fac.createOMElement(
                        method.getName() + "Response", ns);
                OMElement resWrapper;
                if (qualified) {
                    resWrapper = fac.createOMElement(RETURN_WRAPPER, ns.getNamespaceURI(),
                            ns.getPrefix());
                } else {
                    resWrapper = fac.createOMElement(RETURN_WRAPPER, null);
                }
                resWrapper.addChild(result);
                bodyContent.addChild(resWrapper);
            } else if (SimpleTypeMapper.isSimpleType(resObject)) {
                bodyContent = fac.createOMElement(
                        method.getName() + "Response", ns);
                OMElement child;
                if (qualified) {
                    child = fac.createOMElement(RETURN_WRAPPER, ns);
                } else {
                    child = fac.createOMElement(RETURN_WRAPPER, null);
                }
                child.addChild(fac.createOMText(child, SimpleTypeMapper.getStringValue(resObject)));
                bodyContent.addChild(child);
            } else {
                bodyContent = fac.createOMElement(
                        method.getName() + "Response", ns);
                // Java Beans
                QName returnWrapper;
                if (qualified) {
                    returnWrapper = new QName(ns.getNamespaceURI(), RETURN_WRAPPER, ns.getPrefix());
                } else {
                    returnWrapper = new QName(RETURN_WRAPPER);
                }
                XMLStreamReader xr = BeanUtil.getPullParser(resObject,
                        returnWrapper, typeTable, qualified, false);
                StAXOMBuilder stAXOMBuilder =
                        OMXMLBuilderFactory.createStAXOMBuilder(
                                OMAbstractFactory.getOMFactory(), new StreamWrapper(xr));
                OMElement documentElement = stAXOMBuilder.getDocumentElement();
                if (documentElement != null) {
                    bodyContent.addChild(documentElement);
                }
            }
        }
        if (bodyContent != null) {
            envelope.getBody().addChild(bodyContent);
        }
    }

    public static void processObjectAsDocLitBare(SOAPFactory fac,
                                                 Object resObject,
                                                 OMElement bodyContent,
                                                 OMNamespace ns,
                                                 SOAPEnvelope envelope,
                                                 boolean qualified,
                                                 TypeTable typeTable,
                                                 String partName) {
        if (resObject instanceof OMElement) {
            OMElement result = (OMElement) resObject;
            bodyContent = fac.createOMElement(
                    partName, ns);
            bodyContent.addChild(result);
        } else if (SimpleTypeMapper.isSimpleType(resObject)) {
            bodyContent = fac.createOMElement(
                    partName, ns);
            bodyContent.addChild(fac.createOMText(bodyContent,
                    SimpleTypeMapper.getStringValue(resObject)));
        } else {
            QName returnWrapper = new QName(ns.getNamespaceURI(), partName, ns.getPrefix());
            XMLStreamReader xr = BeanUtil.getPullParser(resObject,
                    returnWrapper, typeTable, qualified, true);
            StAXOMBuilder stAXOMBuilder =
                    OMXMLBuilderFactory.createStAXOMBuilder(
                            OMAbstractFactory.getOMFactory(), new StreamWrapper(xr));
            OMElement documentElement = stAXOMBuilder.getDocumentElement();
            if (documentElement != null) {
                envelope.getBody().addChild(documentElement);
            }
        }
        if (bodyContent != null) {
            envelope.getBody().addChild(bodyContent);
        }
    }


    public static Object[] processRequest(OMElement methodElement,
                                          Method method, ObjectSupplier objectSupplier)
            throws AxisFault {
        Class[] parameters = method.getParameterTypes();
        return BeanUtil.deserialize(methodElement, parameters, objectSupplier);
    }

    public static Object invokeServiceClass(AxisMessage inAxisMessage,
                                            Method method,
                                            Object implClass,
                                            String messageNameSpace,
                                            OMElement methodElement,
                                            MessageContext inMessage) throws AxisFault,
            IllegalAccessException, InvocationTargetException {
        if (inAxisMessage.getElementQName() == null) {
            // method accept empty SOAPbody
            return method.invoke(implClass, new Object[0]);
        } else {
            QName elementQName = inAxisMessage.getElementQName();
            messageNameSpace = elementQName.getNamespaceURI();
            OMNamespace namespace = methodElement.getNamespace();
            if (messageNameSpace != null) {
                if (namespace == null) {
                    throw new AxisFault("namespace mismatch require " +
                            messageNameSpace +
                            " found none");
                }
                if (!messageNameSpace.equals(namespace.getNamespaceURI())) {
                    throw new AxisFault("namespace mismatch require " +
                            messageNameSpace +
                            " found " + methodElement.getNamespace().getNamespaceURI());
                }
            } else if (namespace != null) {
                throw new AxisFault(
                        "namespace mismatch. Axis Oepration expects non-namespace " +
                                "qualified element. But received a namespace qualified element");
            }
            Object[] objectArray;
            if (inAxisMessage.isWrapped()) {
                objectArray = RPCUtil.processRequest(methodElement,
                        method, inMessage.getAxisService().getObjectSupplier());
            } else {
                objectArray = RPCUtil.processRequest((OMElement) methodElement.getParent(),
                        method, inMessage.getAxisService().getObjectSupplier());
            }
            return method.invoke(implClass, objectArray);

        }
    }

    public static OMElement getResponseElement(QName resname,
                                               Object[] objs,
                                               boolean qualified,
                                               TypeTable typeTable) {
        if (qualified) {
            return BeanUtil.getOMElement(resname, objs,
                    new QName(resname.getNamespaceURI(),
                            RETURN_WRAPPER,
                            resname.getPrefix()),
                    qualified,
                    typeTable);
        } else {
            return BeanUtil.getOMElement(resname, objs,
                    new QName(RETURN_WRAPPER), qualified,
                    typeTable);
        }
    }

    public static void processResonseAsDocLitBare(Object resObject,
                                                  AxisService service,
                                                  SOAPEnvelope envelope,
                                                  SOAPFactory fac,
                                                  OMNamespace ns,
                                                  OMElement bodyContent,
                                                  MessageContext outMessage
    ) throws Exception {
        QName elementQName = outMessage.getAxisMessage().getElementQName();
        String partName = outMessage.getAxisMessage().getPartName();
        if (resObject == null) {
            processNullReturns(service, envelope, partName);
        } else {
            if (resObject instanceof Object[]) {
                QName resName = new QName(elementQName.getNamespaceURI(),
                        partName,
                        elementQName.getPrefix());
                OMElement bodyChild = RPCUtil.getResponseElement(resName,
                        (Object[]) resObject,
                        service.isElementFormDefault(),
                        service.getTypeTable());
                envelope.getBody().addChild(bodyChild);
            } else {
                if (resObject.getClass().isArray()) {
                    int length = Array.getLength(resObject);
                    Object objArray[];
                    if (resObject instanceof byte[]) {
                        objArray = new Object[1];
                        objArray[0] = Base64.encode((byte[]) resObject);
                    } else {
                        objArray = new Object[length];
                        for (int i = 0; i < length; i++) {
                            objArray[i] = Array.get(resObject, i);
                        }
                    }

                    QName resName = new QName(elementQName.getNamespaceURI(),
                            partName,
                            elementQName.getPrefix());
                    OMElement bodyChild = RPCUtil.getResponseElement(resName,
                            objArray,
                            service.isElementFormDefault(),
                            service.getTypeTable());
                    envelope.getBody().addChild(bodyChild);
                } else {
                    if (SimpleTypeMapper.isCollection(resObject.getClass())) {
                        Collection collection = (Collection) resObject;
                        int size = collection.size();
                        Object values[] = new Object[size];
                        int count = 0;
                        for (Iterator iterator = collection.iterator(); iterator.hasNext();) {
                            values[count] = iterator.next();
                            count++;

                        }
                        QName resName = new QName(elementQName.getNamespaceURI(),
                                partName,
                                elementQName.getPrefix());
                        OMElement bodyChild = RPCUtil.getResponseElement(resName,
                                values,
                                service.isElementFormDefault(),
                                service.getTypeTable());
                        envelope.getBody().addChild(bodyChild);
                    } else if (SimpleTypeMapper.isDataHandler(resObject.getClass())) {
                        OMElement resElemt;
                        if (service.isElementFormDefault()) {
                            resElemt = fac.createOMElement(partName, ns);
                        } else {
                            resElemt = fac.createOMElement(partName, null);
                        }
                        OMText text = fac.createOMText(resObject, true);
                        resElemt.addChild(text);
                        envelope.getBody().addChild(resElemt);
                    } else {
                        if (service.isElementFormDefault()) {
                            RPCUtil.processObjectAsDocLitBare(fac,
                                    resObject,
                                    bodyContent,
                                    ns,
                                    envelope,
                                    service.isElementFormDefault(),
                                    service.getTypeTable(),
                                    partName);
                        } else {
                            RPCUtil.processObjectAsDocLitBare(fac,
                                    resObject,
                                    bodyContent,
                                    ns,
                                    envelope,
                                    service.isElementFormDefault(),
                                    null,
                                    partName);
                        }
                    }
                }
            }
        }
        outMessage.setEnvelope(envelope);
    }

    /**
     * This method is use to to crete the reposne when , the return value is null
     *
     * @param service  Current AxisService
     * @param envelope response enevelop
     */
    private static void processNullReturns(AxisService service,
                                           SOAPEnvelope envelope, String partName) {
        QName resName;
        if (service.isElementFormDefault()) {
            resName = new QName(service.getSchemaTargetNamespace(),
                    partName,
                    service.getSchemaTargetNamespacePrefix());
        } else {
            resName = new QName(partName);
        }
        XMLStreamReader xr = new NullXMLStreamReader(resName);
        StreamWrapper parser = new StreamWrapper(xr);
        StAXOMBuilder stAXOMBuilder =
                OMXMLBuilderFactory.createStAXOMBuilder(
                        OMAbstractFactory.getSOAP11Factory(), parser);
        envelope.getBody().addChild(stAXOMBuilder.getDocumentElement());
    }


    public static void processResponseAsDocLitWrapped(Object resObject,
                                                      AxisService service,
                                                      Method method,
                                                      SOAPEnvelope envelope,
                                                      SOAPFactory fac,
                                                      OMNamespace ns,
                                                      OMElement bodyContent,
                                                      MessageContext outMessage
    ) throws Exception {
        QName elementQName = outMessage.getAxisMessage().getElementQName();
        if (resObject == null) {
            QName resName;
            if (service.isElementFormDefault()) {
                resName = new QName(service.getSchemaTargetNamespace(),
                        RETURN_WRAPPER,
                        service.getSchemaTargetNamespacePrefix());
            } else {
                resName = new QName(RETURN_WRAPPER);
            }
            XMLStreamReader xr = new NullXMLStreamReader(resName);
            StreamWrapper parser = new StreamWrapper(xr);
            StAXOMBuilder stAXOMBuilder =
                    OMXMLBuilderFactory.createStAXOMBuilder(
                            OMAbstractFactory.getSOAP11Factory(), parser);
            ns = fac.createOMNamespace(service.getSchemaTargetNamespace(),
                    service.getSchemaTargetNamespacePrefix());
            OMElement bodyChild = fac.createOMElement(method.getName() + "Response", ns);
            bodyChild.addChild(stAXOMBuilder.getDocumentElement());
            envelope.getBody().addChild(bodyChild);
        } else {
            if (resObject instanceof Object[]) {

                QName resName = new QName(elementQName.getNamespaceURI(),
                        method.getName() + "Response",
                        elementQName.getPrefix());
                OMElement bodyChild = RPCUtil.getResponseElement(resName,
                        (Object[]) resObject,
                        service.isElementFormDefault(),
                        service.getTypeTable());
                envelope.getBody().addChild(bodyChild);
            } else {
                if (resObject.getClass().isArray()) {
                    int length = Array.getLength(resObject);
                    Object objArray[];
                    if (resObject instanceof byte[]) {
                        objArray = new Object[1];
                        objArray[0] = Base64.encode((byte[]) resObject);
                    } else {
                        objArray = new Object[length];
                        for (int i = 0; i < length; i++) {
                            objArray[i] = Array.get(resObject, i);
                        }
                    }

                    QName resName = new QName(elementQName.getNamespaceURI(),
                            method.getName() + "Response",
                            elementQName.getPrefix());
                    OMElement bodyChild = RPCUtil.getResponseElement(resName,
                            objArray,
                            service.isElementFormDefault(),
                            service.getTypeTable());
                    envelope.getBody().addChild(bodyChild);
                } else {
                    if (SimpleTypeMapper.isCollection(resObject.getClass())) {
                        Collection collection = (Collection) resObject;
                        int size = collection.size();
                        Object values[] = new Object[size];
                        int count = 0;
                        for (Iterator iterator = collection.iterator(); iterator.hasNext();) {
                            values[count] = iterator.next();
                            count++;

                        }
                        QName resName = new QName(elementQName.getNamespaceURI(),
                                method.getName() + "Response",
                                elementQName.getPrefix());
                        OMElement bodyChild = RPCUtil.getResponseElement(resName,
                                values,
                                service.isElementFormDefault(),
                                service.getTypeTable());
                        envelope.getBody().addChild(bodyChild);
                    } else if (SimpleTypeMapper.isDataHandler(resObject.getClass())) {
                        OMElement resElemt = fac.createOMElement(method.getName() + "Response", ns);
                        OMText text = fac.createOMText(resObject, true);
                        OMElement returnElement;
                        if (service.isElementFormDefault()) {
                            returnElement = fac.createOMElement(RETURN_WRAPPER, ns);
                        } else {
                            returnElement = fac.createOMElement(RETURN_WRAPPER, null);
                        }
                        returnElement.addChild(text);
                        resElemt.addChild(returnElement);
                        envelope.getBody().addChild(resElemt);
                    } else {
                        if (service.isElementFormDefault()) {
                            RPCUtil.processResponse(fac, resObject, bodyContent, ns,
                                    envelope, method,
                                    service.isElementFormDefault(),
                                    service.getTypeTable());
                        } else {
                            RPCUtil.processResponse(fac, resObject, bodyContent, ns,
                                    envelope, method,
                                    service.isElementFormDefault(),
                                    null);
                        }
                    }
                }
            }
        }
        outMessage.setEnvelope(envelope);
    }
}
