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

import java.lang.reflect.Modifier;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.xml.namespace.QName;

import org.eclipse.persistence.exceptions.DescriptorException;
import org.eclipse.persistence.exceptions.XMLMarshalException;
import org.eclipse.persistence.internal.core.helper.CoreField;
import org.eclipse.persistence.internal.core.sessions.CoreAbstractSession;
import org.eclipse.persistence.internal.oxm.mappings.Descriptor;
import org.eclipse.persistence.internal.oxm.mappings.Field;
import org.eclipse.persistence.internal.oxm.mappings.Mapping;
import org.eclipse.persistence.internal.oxm.mappings.UnmarshalKeepAsElementPolicy;
import org.eclipse.persistence.internal.oxm.mappings.XMLConverterMapping;
import org.eclipse.persistence.internal.oxm.record.MarshalRecord;
import org.eclipse.persistence.internal.oxm.record.UnmarshalRecord;
import org.eclipse.persistence.internal.oxm.record.XMLReader;
import org.eclipse.persistence.internal.oxm.record.XMLRecord;
import org.eclipse.persistence.internal.oxm.record.deferred.DescriptorNotFoundContentHandler;
import org.eclipse.persistence.core.queries.CoreAttributeGroup;
import org.eclipse.persistence.core.queries.CoreAttributeItem;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;

public abstract class XMLRelationshipMappingNodeValue extends MappingNodeValue {

    // Protected to public
    public void processChild(XPathFragment xPathFragment, UnmarshalRecord unmarshalRecord, Attributes atts, Descriptor xmlDescriptor, Mapping mapping) throws SAXException {
        if(xmlDescriptor == null){
            //Use the DescriptorNotFoundContentHandler to "look ahead" and determine if this is a simple or complex element
            //if it is complex the exception should be thrown
            DescriptorNotFoundContentHandler handler = new DescriptorNotFoundContentHandler(unmarshalRecord, mapping);
            String qnameString = xPathFragment.getLocalName();
            if(xPathFragment.getPrefix() != null) {
                qnameString = xPathFragment.getPrefix()  +Constants.COLON + qnameString;
            }
            handler.startElement(xPathFragment.getNamespaceURI(), xPathFragment.getLocalName(), qnameString, atts);
            XMLReader xmlReader = unmarshalRecord.getXMLReader();
            xmlReader.setContentHandler(handler);
            xmlReader.setLexicalHandler(handler);
            return;
        }

        if (xmlDescriptor.hasInheritance()) {
            unmarshalRecord.setAttributes(atts);
            CoreAbstractSession session = unmarshalRecord.getSession();
            Class classValue = ((ObjectBuilder)xmlDescriptor.getObjectBuilder()).classFromRow(unmarshalRecord, session);
            if (classValue == null) {
                // no xsi:type attribute - look for type indicator on the default root element
                XPathQName leafElementType = unmarshalRecord.getLeafElementType();

                // if we have a user-set type, try to get the class from the inheritance policy
                if (leafElementType != null) {
                    Object indicator = xmlDescriptor.getInheritancePolicy().getClassIndicatorMapping().get(leafElementType);
                    if(indicator != null) {
                        classValue = (Class)indicator;
                    }
                }
                // if xsi:type is overriden by JSON_TYPE_ATTRIBUTE_NAME unmarshall property
                if (classValue == null && unmarshalRecord.getUnmarshaller().isApplicationJSON() &&
                        unmarshalRecord.getUnmarshaller().getJsonTypeConfiguration().getJsonTypeAttributeName() != null && atts.getValue(unmarshalRecord.getUnmarshaller().getJsonTypeConfiguration().getJsonTypeAttributeName()) != null) {
                    QName qname = new QName(xmlDescriptor.getSchemaReference().getSchemaContextAsQName().getNamespaceURI(), atts.getValue(unmarshalRecord.getUnmarshaller().getJsonTypeConfiguration().getJsonTypeAttributeName()));
                    classValue = (Class)xmlDescriptor.getInheritancePolicy().getClassIndicatorMapping().get(qname);
                }
            }
            if (classValue != null) {
                xmlDescriptor = (Descriptor)session.getDescriptor(classValue);
            } else {
                // since there is no xsi:type attribute, use the reference descriptor set
                // on the mapping -  make sure it is non-abstract
                if (Modifier.isAbstract(xmlDescriptor.getJavaClass().getModifiers())) {
                    // need to throw an exception here
                    throw DescriptorException.missingClassIndicatorField(unmarshalRecord, (org.eclipse.persistence.oxm.XMLDescriptor)xmlDescriptor.getInheritancePolicy().getDescriptor());
                }
            }
        }
        ObjectBuilder targetObjectBuilder = (ObjectBuilder)xmlDescriptor.getObjectBuilder();

        CoreAttributeGroup group = unmarshalRecord.getUnmarshalAttributeGroup();
        CoreAttributeGroup nestedGroup = null;
        if(group == XMLRecord.DEFAULT_ATTRIBUTE_GROUP) {
            nestedGroup = group;
        }
        if(nestedGroup == null) {
            CoreAttributeItem item = group.getItem(getMapping().getAttributeName());
            nestedGroup = item.getGroup(xmlDescriptor.getJavaClass());
            if(nestedGroup == null) {
                if(item.getGroup() == null) {
                    nestedGroup = XMLRecord.DEFAULT_ATTRIBUTE_GROUP;
                } else {
                    nestedGroup = item.getGroup();
                }
            }
        }
        UnmarshalRecord childRecord = unmarshalRecord.getChildUnmarshalRecord(targetObjectBuilder);
        childRecord.setAttributes(atts);
        childRecord.startDocument();
        childRecord.initializeRecord(null);
        childRecord.setUnmarshalAttributeGroup(nestedGroup);
        childRecord.startElement(xPathFragment.getNamespaceURI(), xPathFragment.getLocalName(), xPathFragment.getShortName(), atts);

        XMLReader xmlReader = unmarshalRecord.getXMLReader();
        xmlReader.setContentHandler(childRecord);
        xmlReader.setLexicalHandler(childRecord);
    }

    protected Descriptor findReferenceDescriptor(XPathFragment xPathFragment, UnmarshalRecord unmarshalRecord, Attributes atts, Mapping mapping, UnmarshalKeepAsElementPolicy policy) {
        Descriptor returnDescriptor = null;
        //try xsi:type
        if(atts != null){
            Context xmlContext = unmarshalRecord.getUnmarshaller().getContext();
            String schemaType = null;
            if(unmarshalRecord.isNamespaceAware()){
                schemaType = atts.getValue(javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, Constants.SCHEMA_TYPE_ATTRIBUTE);
            }else{
                schemaType = atts.getValue(Constants.EMPTY_STRING, Constants.SCHEMA_TYPE_ATTRIBUTE);
            }


            if(schemaType != null){
                schemaType = schemaType.trim();
                if(schemaType.length() > 0) {
                    XPathFragment frag = new XPathFragment(schemaType, unmarshalRecord.getNamespaceSeparator(), unmarshalRecord.isNamespaceAware());

                    QName qname = null;
                    if (frag.hasNamespace()) {
                        String prefix = frag.getPrefix();
                        String url = unmarshalRecord.resolveNamespacePrefix(prefix);
                        frag.setNamespaceURI(url);

                        qname = new QName(url, frag.getLocalName());
                        unmarshalRecord.setTypeQName(qname);
                    } else {
                        String url = unmarshalRecord.resolveNamespacePrefix(Constants.EMPTY_STRING);
                        if(null != url) {
                            frag.setNamespaceURI(url);

                            qname = new QName(url, frag.getLocalName());
                            unmarshalRecord.setTypeQName(qname);
                        }
                        if(!unmarshalRecord.isNamespaceAware() || !unmarshalRecord.getUnmarshaller().getJsonTypeConfiguration().useXsdTypesWithPrefix()){
                            qname = new QName(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI ,frag.getLocalName());
                            unmarshalRecord.setTypeQName(qname);
                        }
                    }
                    returnDescriptor = xmlContext.getDescriptorByGlobalType(frag);
                    if(returnDescriptor == null){
                        if(policy == null || (!policy.isKeepUnknownAsElement() && !policy.isKeepAllAsElement())){
                            Class<Object> theClass = unmarshalRecord.getConversionManager().javaType(qname);
                            if(theClass == null){
                                throw XMLMarshalException.unknownXsiTypeValue(schemaType, mapping);
                            }
                        }
                    }
               }
            }
        }
        return returnDescriptor;
    }

    protected void addTypeAttribute(Descriptor descriptor, MarshalRecord marshalRecord, String schemaContext) {
        String typeValue = schemaContext.substring(1);

        String xsiPrefix = null;
        if (descriptor.getNamespaceResolver() != null) {
            xsiPrefix = descriptor.getNamespaceResolver().resolveNamespaceURI(javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI);
        } else {
            xsiPrefix = Constants.SCHEMA_INSTANCE_PREFIX;
            marshalRecord.namespaceDeclaration(xsiPrefix,  javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI);

        }
        if (xsiPrefix == null) {
            xsiPrefix = descriptor.getNamespaceResolver().generatePrefix(Constants.SCHEMA_INSTANCE_PREFIX);
            marshalRecord.namespaceDeclaration(xsiPrefix,  javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI);
        }
        marshalRecord.attribute(javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, Constants.SCHEMA_TYPE_ATTRIBUTE, xsiPrefix + Constants.COLON + Constants.SCHEMA_TYPE_ATTRIBUTE, typeValue);
    }

    protected void writeExtraNamespaces(List extraNamespaces, XMLRecord xmlRecord, CoreAbstractSession session) {
        if (extraNamespaces == null) {
            return;
        }
        for (int i = 0, extraNamespacesSize=extraNamespaces.size(); i < extraNamespacesSize; i++) {
            Namespace next = (Namespace)extraNamespaces.get(i);
            String prefix = next.getPrefix();
            if(((MarshalRecord)xmlRecord).hasCustomNamespaceMapper()) {
                prefix = ((MarshalRecord)xmlRecord).getNamespaceResolver().resolveNamespaceURI(next.getNamespaceURI());
            }
           ((MarshalRecord)xmlRecord).namespaceDeclaration(prefix, next.getNamespaceURI());
        }

    }

    protected void setupHandlerForKeepAsElementPolicy(UnmarshalRecord unmarshalRecord, XPathFragment xPathFragment, Attributes atts) {
        SAXFragmentBuilder builder = unmarshalRecord.getFragmentBuilder();
        builder.setOwningRecord(unmarshalRecord);
        builder.setMixedContent(xPathNode.getUnmarshalNodeValue().isMixedContentNodeValue());
        try {
            String namespaceURI = Constants.EMPTY_STRING;
            if (xPathFragment.getNamespaceURI() != null) {
                namespaceURI = xPathFragment.getNamespaceURI();
            }
            String qName = xPathFragment.getLocalName();
            if (xPathFragment.getPrefix() != null) {
                qName = xPathFragment.getPrefix() + unmarshalRecord.getNamespaceSeparator() + qName;
            }

            if(!(unmarshalRecord.getPrefixesForFragment().isEmpty())) {
                for(Entry<String, String> next:((Map<String, String>) unmarshalRecord.getPrefixesForFragment()).entrySet()) {
                    builder.startPrefixMapping(next.getKey(), next.getValue());
                }
            }
            builder.startElement(namespaceURI, xPathFragment.getLocalName(), qName, atts);
            XMLReader xmlReader = unmarshalRecord.getXMLReader();
            xmlReader.setContentHandler(builder);
            xmlReader.setLexicalHandler(null);
        } catch (SAXException ex) {
        }
    }

    protected void setOrAddAttributeValueForKeepAsElement(SAXFragmentBuilder builder, Mapping mapping, XMLConverterMapping converter, UnmarshalRecord unmarshalRecord, boolean isCollection, Object collection) {
        Object node = builder.getNodes().remove(builder.getNodes().size() -1);
        if (converter != null) {
            node = converter.convertDataValueToObjectValue(node, unmarshalRecord.getSession(), unmarshalRecord.getUnmarshaller());
        }

        if (isCollection) {
            if(collection != null){
                unmarshalRecord.addAttributeValue((ContainerValue) this, node, collection);
            }else{
                unmarshalRecord.addAttributeValue((ContainerValue) this, node);
            }
        } else {
            unmarshalRecord.setAttributeValue(node, mapping);
        }
    }

    protected void endElementProcessText(UnmarshalRecord unmarshalRecord, XMLConverterMapping converter, XPathFragment xPathFragment, Object collection) {
        Object value = unmarshalRecord.getCharacters().toString();

        unmarshalRecord.resetStringBuffer();
        if(!unmarshalRecord.isNil()) {
            QName qname = unmarshalRecord.getTypeQName();
            if (qname == null) {
                if(Constants.EMPTY_STRING.equals(value)) {
                    value = null;
                }
            } else {
                ConversionManager conversionManager = unmarshalRecord.getConversionManager();
                if(qname.equals(Constants.QNAME_QNAME)) {
                    value = conversionManager.buildQNameFromString((String)value, unmarshalRecord);
                } else {
                    Class theClass = getClassForQName(qname, conversionManager);
                    if (theClass != null) {
                        value = conversionManager.convertObject(value, theClass, qname);
                    }
                }
            }
            value = converter.convertDataValueToObjectValue(value, unmarshalRecord.getSession(), unmarshalRecord.getUnmarshaller());
            setOrAddAttributeValue(unmarshalRecord, value, xPathFragment, collection);
        }
    }

    protected Class getClassForQName(QName qname, ConversionManager conversionManager){
        CoreField field = getMapping().getField();
        if(field != null){
            return ((Field)field).getJavaClass(qname, conversionManager);
        }
        return conversionManager.javaType(qname);
    }


    protected abstract void setOrAddAttributeValue(UnmarshalRecord unmarshalRecord, Object value, XPathFragment xPathFragment, Object collection);
}
