/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Oracle - initial API and implementation from Oracle TopLink

package org.eclipse.persistence.internal.dbws;

// Javase imports
import static javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI;
import static javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI;
import static jakarta.xml.soap.SOAPConstants.SOAP_1_2_PROTOCOL;
import static jakarta.xml.soap.SOAPConstants.URI_NS_SOAP_1_1_ENVELOPE;
import static jakarta.xml.soap.SOAPConstants.URI_NS_SOAP_1_2_ENVELOPE;
import static org.eclipse.persistence.internal.oxm.Constants.BASE_64_BINARY;
import static org.eclipse.persistence.internal.oxm.Constants.SCHEMA_INSTANCE_PREFIX;
import static org.eclipse.persistence.internal.oxm.Constants.SCHEMA_PREFIX;
import static org.eclipse.persistence.internal.xr.Util.SERVICE_NAMESPACE_PREFIX;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import jakarta.activation.DataHandler;
import javax.xml.namespace.QName;
import jakarta.xml.soap.AttachmentPart;
import jakarta.xml.soap.MessageFactory;
import jakarta.xml.soap.SOAPBody;
import jakarta.xml.soap.SOAPException;
import jakarta.xml.soap.SOAPMessage;

import org.eclipse.persistence.internal.oxm.schema.model.ComplexType;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.internal.sessions.DatabaseSessionImpl;
import org.eclipse.persistence.internal.xr.Attachment;
import org.eclipse.persistence.internal.xr.Operation;
import org.eclipse.persistence.internal.xr.QueryOperation;
import org.eclipse.persistence.oxm.NamespaceResolver;
import org.eclipse.persistence.oxm.XMLDescriptor;
import org.eclipse.persistence.oxm.XMLField;
import org.eclipse.persistence.oxm.XMLMarshaller;
import org.eclipse.persistence.oxm.mappings.XMLAnyObjectMapping;
import org.eclipse.persistence.oxm.mappings.XMLBinaryDataMapping;
import org.eclipse.persistence.oxm.mappings.XMLCompositeCollectionMapping;
import org.eclipse.persistence.oxm.mappings.XMLCompositeObjectMapping;
import org.eclipse.persistence.oxm.mappings.XMLDirectMapping;

public class SOAPResponseWriter {

    protected DBWSAdapter dbwsAdapter;
    protected Map<String, XMLDescriptor> resultDescriptors = new HashMap<String, XMLDescriptor>();
    public static final QName RECEIVER_QNAME = new QName(URI_NS_SOAP_1_2_ENVELOPE, "Receiver");
    public static final QName SERVER_QNAME = new QName(URI_NS_SOAP_1_1_ENVELOPE, "Server");

    public SOAPResponseWriter(DBWSAdapter dbwsAdapter) {
        this.dbwsAdapter = dbwsAdapter;
    }

    @SuppressWarnings("unchecked")
    public void initialize() {
        SOAPResponseClassLoader loader =
            new SOAPResponseClassLoader(Thread.currentThread().getContextClassLoader());
        NamespaceResolver nr = new NamespaceResolver();
        nr.put(SERVICE_NAMESPACE_PREFIX, dbwsAdapter.getExtendedSchema().getTargetNamespace());
        for (Operation op : dbwsAdapter.getOperationsList()) {
            String className = op.getName() + "_Response";
            Class<?> opClass = loader.buildClass(className);
            XMLDescriptor descriptor = new XMLDescriptor();
            descriptor.setDefaultRootElement(SERVICE_NAMESPACE_PREFIX + ":" + op.getName() + "Response");
            descriptor.setNamespaceResolver(nr);
            descriptor.setJavaClass(opClass);
            if (op instanceof QueryOperation) {
                QueryOperation queryOperation = (QueryOperation)op;
                if (queryOperation.isSimpleXMLFormat()) {
                    XMLAnyObjectMapping mapping = new XMLAnyObjectMapping();
                    mapping.setUseXMLRoot(true);
                    mapping.setAttributeName("result");
                    mapping.setXPath(SERVICE_NAMESPACE_PREFIX + ":" + "result");
                    descriptor.addMapping(mapping);
                    mapping.initialize((AbstractSession)dbwsAdapter.getOXSession());
                }
                else if (queryOperation.isAttachment()) {
                    Attachment attachment = queryOperation.getResult().getAttachment();
                    XMLBinaryDataMapping mapping = new XMLBinaryDataMapping();
                    mapping.setAttributeName("result");
                    mapping.setXPath(SERVICE_NAMESPACE_PREFIX + ":" + "result");
                    mapping.setSwaRef(true);
                    mapping.setShouldInlineBinaryData(false);
                    mapping.setMimeType(attachment.getMimeType());
                    descriptor.addMapping(mapping);
                }
                else {
                    QName type = queryOperation.getResult().getType();
                    String localElement = type.getLocalPart();
                    // look for top-level complex types
                    Set<Map.Entry<String, ComplexType>> entrySet =
                        dbwsAdapter.getSchema().getTopLevelComplexTypes().entrySet();
                    for (Map.Entry<String, ComplexType> me : entrySet) {
                        if (me.getValue().getName().equals(type.getLocalPart())) {
                            localElement = me.getKey();
                            break;
                        }
                    }
                    XMLDescriptor typeDescriptor =
                        dbwsAdapter.getDescriptorsByQName().get(type);
                    if (typeDescriptor != null) {
                        if (queryOperation.isCollection()) {
                            XMLCompositeCollectionMapping mapping =
                                new XMLCompositeCollectionMapping();
                            mapping.setAttributeName("result");
                            mapping.setReferenceClass(typeDescriptor.getJavaClass());
                            mapping.useCollectionClass(ArrayList.class);
                            mapping.setXPath(SERVICE_NAMESPACE_PREFIX + ":" + "result/" + localElement);
                            descriptor.getNamespaceResolver().setDefaultNamespaceURI(
                                typeDescriptor.getNamespaceResolver().getDefaultNamespaceURI());
                            descriptor.addMapping(mapping);
                            mapping.initialize((AbstractSession)dbwsAdapter.getOXSession());
                        }
                        else {
                            XMLCompositeObjectMapping mapping = new XMLCompositeObjectMapping();
                            mapping.setAttributeName("result");
                            mapping.setReferenceClass(typeDescriptor.getJavaClass());
                            mapping.setXPath(SERVICE_NAMESPACE_PREFIX + ":" + "result/" + localElement);
                            descriptor.getNamespaceResolver().setDefaultNamespaceURI(
                                typeDescriptor.getNamespaceResolver().getDefaultNamespaceURI());
                            descriptor.addMapping(mapping);
                            mapping.initialize((AbstractSession)dbwsAdapter.getOXSession());
                        }
                    }
                    else {
                        if (type.equals(new QName(W3C_XML_SCHEMA_NS_URI, "any"))) {
                            XMLAnyObjectMapping mapping = new XMLAnyObjectMapping();
                            mapping.setAttributeName("result");
                            mapping.setXPath(SERVICE_NAMESPACE_PREFIX + ":" + "result");
                            descriptor.addMapping(mapping);
                        }
                        else if (type.equals(new QName(W3C_XML_SCHEMA_NS_URI, BASE_64_BINARY))) {
                            XMLBinaryDataMapping mapping = new XMLBinaryDataMapping();
                            mapping.setAttributeName("result");
                            mapping.setXPath(SERVICE_NAMESPACE_PREFIX + ":" + "result");
                            mapping.setShouldInlineBinaryData(true);
                            ((XMLField)mapping.getField()).setSchemaType(type);
                            descriptor.addMapping(mapping);
                        }
                        else {
                            XMLDirectMapping mapping = new XMLDirectMapping();
                            mapping.setAttributeName("result");
                            mapping.setXPath(SERVICE_NAMESPACE_PREFIX + ":" + "result/text()");
                            descriptor.addMapping(mapping);
                        }
                    }
                }
            }
            dbwsAdapter.getOXSession().getProject().addDescriptor(descriptor);
            ((DatabaseSessionImpl)dbwsAdapter.getOXSession())
                .initializeDescriptorIfSessionAlive(descriptor);
            dbwsAdapter.getXMLContext().storeXMLDescriptorByQName(descriptor);
            resultDescriptors.put(op.getName(), descriptor);
        }
    }

    public SOAPMessage generateResponse(Operation op, boolean useSOAP12, Exception e) throws SOAPException {
        MessageFactory messageFactory = null;
        if (useSOAP12) {
            messageFactory = MessageFactory.newInstance(SOAP_1_2_PROTOCOL);
        } else {
            messageFactory = MessageFactory.newInstance();
        }
        SOAPMessage message = messageFactory.createMessage();
        message.getSOAPPart().getEnvelope().addNamespaceDeclaration(SCHEMA_PREFIX, W3C_XML_SCHEMA_NS_URI);
        message.getSOAPPart().getEnvelope().addNamespaceDeclaration(SCHEMA_INSTANCE_PREFIX, W3C_XML_SCHEMA_INSTANCE_NS_URI);
        SOAPBody body = message.getSOAPPart().getEnvelope().getBody();
        QName faultCodeQName = null;
        if (useSOAP12) {
            faultCodeQName = RECEIVER_QNAME;
        } else {
            faultCodeQName = SERVER_QNAME;
        }
        body.addFault(faultCodeQName, op.getName() + " failed: " + e);
        return message;
    }

    public SOAPMessage generateResponse(Operation op, boolean useSOAP12, Object result) throws SOAPException {
        MessageFactory messageFactory = null;
        if (useSOAP12) {
            messageFactory = MessageFactory.newInstance(SOAP_1_2_PROTOCOL);
        }
        else {
            messageFactory = MessageFactory.newInstance();
        }
        SOAPMessage message = messageFactory.createMessage();
        message.getSOAPPart().getEnvelope().addNamespaceDeclaration(SCHEMA_PREFIX, W3C_XML_SCHEMA_NS_URI);
        message.getSOAPPart().getEnvelope().addNamespaceDeclaration(SCHEMA_INSTANCE_PREFIX, W3C_XML_SCHEMA_INSTANCE_NS_URI);
        SOAPBody body = message.getSOAPPart().getEnvelope().getBody();

        XMLDescriptor descriptor = resultDescriptors.get(op.getName());
        SOAPResponse response = null;
        try {
            response = (SOAPResponse) descriptor.getJavaClass().getConstructor().newInstance();
        } catch (ReflectiveOperationException ie) {
            throw new SOAPException(ie);
        }
        response.setResult(result);

        SOAPAttachmentHandler attachmentHandler = new SOAPAttachmentHandler();
        XMLMarshaller marshaller = dbwsAdapter.getXMLContext().createMarshaller();
        marshaller.setAttachmentMarshaller(attachmentHandler);
        marshaller.marshal(response, body);

        if (attachmentHandler.hasAttachments()) {
            // add attachments to message
            for (String id : attachmentHandler.getAttachments().keySet()) {
                DataHandler attachment = attachmentHandler.getAttachments().get(id);
                AttachmentPart part = message.createAttachmentPart(attachment);
                part.setContentType(attachment.getContentType());
                String contentId = "<" + id.substring(4) + ">";
                part.setContentId(contentId);
                part.setMimeHeader("Content-Transfer-Encoding", "binary");
                message.addAttachmentPart(part);
            }
        }
        message.saveChanges();

        return message;
    }
}
