/*
 * Copyright (c) 2012, 2020 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:
//     Blaise Doughan - 2.5 - initial implementation
package org.eclipse.persistence.internal.oxm.record;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.xml.namespace.QName;

import org.eclipse.persistence.core.descriptors.CoreInheritancePolicy;
import org.eclipse.persistence.internal.core.helper.CoreField;
import org.eclipse.persistence.internal.core.sessions.CoreAbstractRecord;
import org.eclipse.persistence.internal.core.sessions.CoreAbstractSession;
import org.eclipse.persistence.internal.oxm.Constants;
import org.eclipse.persistence.internal.oxm.ConversionManager;
import org.eclipse.persistence.internal.oxm.Marshaller;
import org.eclipse.persistence.internal.oxm.Namespace;
import org.eclipse.persistence.internal.oxm.NamespaceResolver;
import org.eclipse.persistence.internal.oxm.ObjectBuilder;
import org.eclipse.persistence.internal.oxm.Root;
import org.eclipse.persistence.internal.oxm.XPathQName;
import org.eclipse.persistence.internal.oxm.mappings.Descriptor;
import org.eclipse.persistence.internal.oxm.mappings.Field;
import org.eclipse.persistence.oxm.XMLConstants;
import org.eclipse.persistence.oxm.XMLField;
import org.eclipse.persistence.oxm.schema.XMLSchemaReference;
import org.w3c.dom.Node;

public class AbstractMarshalRecordImpl<
    ABSTRACT_SESSION extends CoreAbstractSession,
    FIELD extends CoreField,
    MARSHALLER extends Marshaller,
    NAMESPACE_RESOLVER extends NamespaceResolver> extends CoreAbstractRecord implements AbstractMarshalRecord<ABSTRACT_SESSION, FIELD, MARSHALLER, NAMESPACE_RESOLVER> {

    private ConversionManager conversionManager;
    protected boolean equalNamespaceResolvers;
    protected boolean hasCustomNamespaceMapper;
    private boolean isXOPPackage;
    private XPathQName leafElementType;
    protected MARSHALLER marshaller;
    protected boolean namespaceAware = true;
    protected NAMESPACE_RESOLVER namespaceResolver;
    private Object owningObject;
    private AbstractMarshalRecord<ABSTRACT_SESSION, FIELD, MARSHALLER, NAMESPACE_RESOLVER> realRecord;
    protected ABSTRACT_SESSION session;

    public AbstractMarshalRecordImpl(AbstractMarshalRecord realRecord) {
        this.realRecord = realRecord;
    }

    @Override
    public List addExtraNamespacesToNamespaceResolver(Descriptor descriptor,
            CoreAbstractSession session, boolean allowOverride,
            boolean ignoreEqualResolvers) {
        if (equalNamespaceResolvers && !ignoreEqualResolvers) {
            return null;
        }

        org.eclipse.persistence.internal.oxm.NamespaceResolver descriptorNamespaceResolver = descriptor.getNamespaceResolver();
        if(null == descriptorNamespaceResolver || !descriptorNamespaceResolver.hasPrefixesToNamespaces()) {
            return null;
        }
        Map<String, String> prefixesToNamespaces = descriptorNamespaceResolver.getPrefixesToNamespaces();
        if(prefixesToNamespaces.size() == 0) {
            return null;
        }
        List returnList = new ArrayList(prefixesToNamespaces.size());
        org.eclipse.persistence.internal.oxm.NamespaceResolver marshalRecordNamespaceResolver = namespaceResolver;
        for(Entry<String, String> entry: prefixesToNamespaces.entrySet()) {

            //if isn't already on a parentadd namespace to this element
            String prefix = marshalRecordNamespaceResolver.resolveNamespaceURI(entry.getValue());

            if (prefix == null || prefix.length() == 0) {
                //if there is no prefix already declared for this uri in the nr add this one
                //unless that prefix is already bound to another namespace uri
                prefix = entry.getKey();
                if(hasCustomNamespaceMapper) {
                    String newPrefix = getMarshaller().getNamespacePrefixMapper().getPreferredPrefix(entry.getValue(), prefix, true);
                    if(newPrefix != null && !(newPrefix.length() == 0)) {
                        prefix = newPrefix;
                    }
                }
                String uri = marshalRecordNamespaceResolver.resolveNamespacePrefix(prefix);
                if(hasCustomNamespaceMapper || allowOverride || uri == null || uri.length() == 0) {
                    //if this uri is unknown, the cutom mapper will return the preferred prefix for this uri
                    marshalRecordNamespaceResolver.put(entry.getKey(), entry.getValue());
                    returnList.add(new Namespace(prefix, entry.getValue()));
                }
            } else if(allowOverride) {
                //if overrides are allowed, add the prefix if the URI is different
                if (!prefix.equals(entry.getKey()) && !hasCustomNamespaceMapper) {
                    //if prefix exists for uri but is different then add this
                    //unless using a custom namespace prefix mapper. Then prefix is expected to be different
                    marshalRecordNamespaceResolver.put(entry.getKey(), entry.getValue());
                    returnList.add(new Namespace(entry.getKey(), entry.getValue()));
                }
            }
        }
        return returnList;
    }

    @Override
    public boolean addXsiTypeAndClassIndicatorIfRequired(Descriptor descriptor, Descriptor referenceDescriptor, Field xmlField, boolean isRootElement) {
        ObjectBuilder objectBuilder = (ObjectBuilder) descriptor.getObjectBuilder();
        boolean xsiTypeIndicatorField = objectBuilder.isXsiTypeIndicatorField();

        if(objectBuilder.addClassIndicatorFieldToRow(this)) {
            return true;
        }



        QName leafType = null;
        if (xmlField != null) {
            leafType = xmlField.getLeafElementType();

            XMLSchemaReference xmlRef = descriptor.getSchemaReference();
            if (xmlRef != null) {
                if (leafType == null) {
                    if (xmlRef.getType() == XMLSchemaReference.ELEMENT) {
                        return false;
                    }
                    if (referenceDescriptor == null) {
                        writeXsiTypeAttribute(descriptor, xmlRef, isRootElement);
                        return true;
                    }
                } else if (((xmlRef.getType() == XMLSchemaReference.COMPLEX_TYPE) || (xmlRef.getType() == XMLSchemaReference.SIMPLE_TYPE)) && xmlRef.getSchemaContext() != null && xmlRef.isGlobalDefinition()) {
                    QName ctxQName = xmlRef.getSchemaContextAsQName(descriptor.getNamespaceResolver());
                    if (!ctxQName.equals(leafType)) {
                        writeXsiTypeAttribute(descriptor, xmlRef, isRootElement);
                        return true;
                    }
                }
            }
        }

        if (referenceDescriptor != null && referenceDescriptor == descriptor) {
            return false;
        }
        if (descriptor.hasInheritance() && !descriptor.getInheritancePolicy().isRootParentDescriptor()) {
            CoreInheritancePolicy inheritancePolicy = descriptor.getInheritancePolicy();
            Field indicatorField = (Field) inheritancePolicy.getClassIndicatorField();
            if (indicatorField != null && xsiTypeIndicatorField) {
                Object classIndicatorValueObject = inheritancePolicy.getClassIndicatorMapping().get(descriptor.getJavaClass());
                String classIndicatorUri = null;
                String classIndicatorLocal= null;
                String classIndicatorPrefix= null;
                if (classIndicatorValueObject instanceof QName) {
                    QName classIndicatorQName = (QName) classIndicatorValueObject;
                    classIndicatorUri = classIndicatorQName.getNamespaceURI();
                    classIndicatorLocal = classIndicatorQName.getLocalPart();
                    classIndicatorPrefix = classIndicatorQName.getPrefix();
                } else {
                    String classIndicatorValue = (String) inheritancePolicy.getClassIndicatorMapping().get(descriptor.getJavaClass());
                    int nsindex = classIndicatorValue.indexOf(Constants.COLON);
                    String prefix = null;
                    if (nsindex != -1) {
                        classIndicatorLocal = classIndicatorValue.substring(nsindex + 1);
                        prefix = classIndicatorValue.substring(0, nsindex);
                    } else {
                        classIndicatorLocal = classIndicatorValue;
                    }
                    classIndicatorUri = descriptor.getNonNullNamespaceResolver().resolveNamespacePrefix(prefix);
                }
                if(leafType == null
                        || isRootElement && marshaller.isApplicationJSON() && !marshaller.isIncludeRoot()
                        || !(leafType.getLocalPart().equals(classIndicatorLocal))
                        || (classIndicatorUri == null && (leafType.getNamespaceURI() != null && leafType.getNamespaceURI().length() >0))
                        || (classIndicatorUri != null && !classIndicatorUri.equals(leafType.getNamespaceURI()))
                       ){
                    if (inheritancePolicy.hasClassExtractor()) {
                        objectBuilder.addClassIndicatorFieldToRow(this);
                    } else {
                        writeXsiTypeAttribute(descriptor, classIndicatorUri, classIndicatorLocal,classIndicatorPrefix, isRootElement);
                    }
                    return true;
                }
                return false;
            }

        }
        return false;
    }

    /**
     * INTERNAL
     * @since EclipseLink 2.5.0
     */
   @Override
public boolean addXsiTypeAndClassIndicatorIfRequired(Descriptor descriptor, Descriptor referenceDescriptor, Field xmlField,
           Object originalObject, Object obj, boolean wasXMLRoot, boolean isRootElement) {
        if (wasXMLRoot) {
            XMLSchemaReference xmlRef = descriptor.getSchemaReference();

            if (descriptor != null) {
                Root xr = (Root) originalObject;

                if (xmlRef == null) {
                    return false;
                }

        if (xr.getDeclaredType() != null && xr.getDeclaredType() == xr.getObject().getClass()) {
                    return false;
                }

                String xmlRootLocalName = xr.getLocalName();
                String xmlRootUri = xr.getNamespaceURI();

                XPathQName qName = new XPathQName(xmlRootUri, xmlRootLocalName, namespaceAware);
                Descriptor xdesc = marshaller.getContext().getDescriptor(qName);
                if (xdesc != null) {
                    boolean writeTypeAttribute = xdesc.getJavaClass() != descriptor.getJavaClass();
                    if (writeTypeAttribute) {
                        writeXsiTypeAttribute(descriptor, xmlRef, isRootElement);
                        return true;
                    }
                    return false;

                }

                boolean writeTypeAttribute = true;
                int tableSize = descriptor.getTableNames().size();
                for (int i = 0; i < tableSize; i++) {
                    if (!writeTypeAttribute) {
                        return false;
                    }
                    String defaultRootQualifiedName = (String) descriptor.getTableNames().get(i);
                    if (defaultRootQualifiedName != null) {
                        String defaultRootLocalName = null;
                        String defaultRootUri = null;
                        int colonIndex = defaultRootQualifiedName.indexOf(Constants.COLON);
                        if (colonIndex > 0) {
                            String defaultRootPrefix = defaultRootQualifiedName.substring(0, colonIndex);
                            defaultRootLocalName = defaultRootQualifiedName.substring(colonIndex + 1);
                            if (descriptor.getNamespaceResolver() != null) {
                                defaultRootUri = descriptor.getNamespaceResolver().resolveNamespacePrefix(defaultRootPrefix);
                            }
                        } else {
                            defaultRootLocalName = defaultRootQualifiedName;
                        }

                        if (xmlRootLocalName != null) {
                            if ((((defaultRootLocalName == null) && (xmlRootLocalName == null)) || (defaultRootLocalName.equals(xmlRootLocalName)))
                                && (((defaultRootUri == null) && (xmlRootUri == null)) || ((xmlRootUri != null) && (defaultRootUri != null) && (defaultRootUri.equals(xmlRootUri))))) {
                                // if both local name and uris are equal then don't need to write type attribute
                                return false;
                            }
                        }
                    } else {
                        // no default rootElement was set
                        // if xmlRootName = null then writeTypeAttribute = false
                        if (xmlRootLocalName == null) {
                            return false;
                        }
                    }
                }
                if (writeTypeAttribute && xmlRef != null) {
                    writeXsiTypeAttribute(descriptor, xmlRef, isRootElement);
                    return true;
                }
            }
            return false;
        } else {
            return addXsiTypeAndClassIndicatorIfRequired(descriptor, referenceDescriptor, xmlField, isRootElement);
        }
    }

    @Override
    public void attribute(String namespaceURI, String localName,
            String qualifiedName, String value) {
        if(null != realRecord) {
            realRecord.attribute(namespaceURI, localName, qualifiedName, value);
        }
    }

    @Override
    public void attributeWithoutQName(String namespaceURI, String localName,
            String prefix, String value) {
        String qualifiedName = localName;
        if(prefix != null && prefix.length() >0){
            qualifiedName = prefix + getNamespaceSeparator() + qualifiedName;
        }
        attribute(namespaceURI, localName, qualifiedName, value);
    }

    /**
     * @since EclipseLink 2.6.0
     */
    @Override
    public ConversionManager getConversionManager() {
        if(null == conversionManager) {
            conversionManager = (ConversionManager) session.getDatasourcePlatform().getConversionManager();
        }
        return conversionManager;
    }

    @Override
    public Node getDOM() {
        // TODO Auto-generated method stub
        throw new UnsupportedOperationException();
    }

    @Override
    public XPathQName getLeafElementType() {
        return leafElementType;
    }

    @Override
    public MARSHALLER getMarshaller() {
        return marshaller;
    }

    @Override
    public NAMESPACE_RESOLVER getNamespaceResolver() {
        return namespaceResolver;
    }

    @Override
    public char getNamespaceSeparator() {
        return Constants.COLON;
    }

    @Override
    public Object getOwningObject() {
        return owningObject;
    }

    @Override
    public ABSTRACT_SESSION getSession() {
        return session;
    }

    @Override
    public boolean hasCustomNamespaceMapper() {
        return hasCustomNamespaceMapper;
    }

    @Override
    public boolean hasEqualNamespaceResolvers() {
        return equalNamespaceResolvers;
    }

    /**
     * Determine if namespaces will be considered during marshal/unmarshal operations.
     */
    @Override
    public boolean isNamespaceAware() {
        return namespaceAware;
    }

    @Override
    public boolean isXOPPackage() {
        return isXOPPackage;
    }

    @Override
    public void namespaceDeclaration(String prefix, String typeUri) {
        if(realRecord != null) {
            realRecord.namespaceDeclaration(prefix, typeUri);
            return;
        }
        throw new UnsupportedOperationException();
    }

    @Override
    public Object put(FIELD field, Object object) {
        if(null != realRecord) {
            return realRecord.put(field, object);
        }
        throw new UnsupportedOperationException();
    }

    @Override
    public void removeExtraNamespacesFromNamespaceResolver(List<Namespace> extraNamespaces, CoreAbstractSession session) {
        if (extraNamespaces == null){
          return;
        }

         for (int i = 0; i < extraNamespaces.size(); i++) {
             Namespace nextExtraNamespace = extraNamespaces.get(i);
             String uri = namespaceResolver.resolveNamespacePrefix(nextExtraNamespace.getPrefix());
             if ((uri != null) && uri.equals(nextExtraNamespace.getNamespaceURI())) {
                namespaceResolver.removeNamespace(nextExtraNamespace.getPrefix());
             }
         }
     }

    @Override
    public String resolveNamespacePrefix(String prefix) {
        return null;
    }

    @Override
    public void setCustomNamespaceMapper(boolean customNamespaceMapper) {
        this.hasCustomNamespaceMapper = customNamespaceMapper;
    }

    @Override
    public void setEqualNamespaceResolvers(boolean equalNRs) {
        this.equalNamespaceResolvers = equalNRs;
    }

    @Override
    public void setLeafElementType(QName type) {
        if(type != null){
            setLeafElementType(new XPathQName(type, isNamespaceAware()));
        }
    }

    @Override
    public void setLeafElementType(XPathQName type) {
        leafElementType = type;
    }

    @Override
    public void setMarshaller(MARSHALLER marshaller) {
        this.marshaller = marshaller;
        if(marshaller != null){
            if(marshaller.getNamespacePrefixMapper() != null){
                namespaceAware = true;
            }else{
                namespaceAware = marshaller.isApplicationXML();
            }
        }
    }

    @Override
    public void setNamespaceResolver(NAMESPACE_RESOLVER namespaceResolver) {
        this.namespaceResolver = namespaceResolver;
    }

    @Override
    public void setOwningObject(Object owningObject) {
        this.owningObject = owningObject;
    }

    @Override
    public void setSession(ABSTRACT_SESSION session) {
        this.session = session;
    }

    @Override
    public void setXOPPackage(boolean isXOPPackage) {
        this.isXOPPackage = isXOPPackage;
    }

    @Override
    public void writeXsiTypeAttribute(Descriptor descriptor, String typeUri,
            String typeLocal, String typePrefix, boolean addToNamespaceResolver) {
        if (typeLocal == null){
            return;
        }
        String typeValue = typeLocal;
        if(isNamespaceAware() && typeUri != null && !typeUri.equals(Constants.EMPTY_STRING) && !typeUri.equals(namespaceResolver.getDefaultNamespaceURI())){
            String prefix = namespaceResolver.resolveNamespaceURI(typeUri);
            if(prefix != null && !prefix.equals(Constants.EMPTY_STRING)){
                typeValue = prefix + getNamespaceSeparator() + typeValue;
            } else if (typeUri.equals(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI)) {
                prefix = namespaceResolver.generatePrefix(Constants.SCHEMA_PREFIX);
                typeValue = prefix + getNamespaceSeparator() + typeValue;
                namespaceDeclaration(prefix, typeUri);

            } else if (typePrefix != null && !typePrefix.equals(Constants.EMPTY_STRING)){
                String existingUri = namespaceResolver.resolveNamespacePrefix(typePrefix);
                if(existingUri != null){
                    prefix = namespaceResolver.generatePrefix();
                }else{
                    prefix = typePrefix;
                }
                typeValue = prefix + getNamespaceSeparator() + typeValue;
                namespaceDeclaration(prefix, typeUri);
            }else{
                prefix = namespaceResolver.generatePrefix();
                typeValue = prefix + getNamespaceSeparator() + typeValue;
                namespaceDeclaration(prefix, typeUri);

            }
        }

        String xsiPrefix = null;
        if(isNamespaceAware()){
            xsiPrefix = namespaceResolver.resolveNamespaceURI(javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI);
            if (xsiPrefix == null) {
                xsiPrefix = namespaceResolver.generatePrefix(Constants.SCHEMA_INSTANCE_PREFIX);
                namespaceDeclaration(xsiPrefix, javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI);
                if(addToNamespaceResolver){
                    namespaceResolver.put(xsiPrefix, javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI);
                }
            }
        }
        if (marshaller.isApplicationJSON() && descriptor != null && descriptor.getInheritancePolicyOrNull() != null &&
                descriptor.getInheritancePolicyOrNull().getClassIndicatorFieldName() != null) {
            //true - override default type attribute name by JSON_TYPE_ATTRIBUTE_NAME marshaller property
            if(XMLConstants.DEFAULT_XML_TYPE_ATTRIBUTE == descriptor.getInheritancePolicyOrNull().getClassIndicatorField() &&
                    marshaller.getJsonTypeConfiguration().getJsonTypeAttributeName() != null) {
                attributeWithoutQName(javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, marshaller.getJsonTypeConfiguration().getJsonTypeAttributeName(), xsiPrefix, typeValue);
            } else {
                attributeWithoutQName(javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI,
                        ((XMLField) (descriptor.getInheritancePolicyOrNull().getClassIndicatorField())).getXPathFragment().getLocalName(), xsiPrefix, typeValue);
            }
        } else {
            attributeWithoutQName(javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, Constants.SCHEMA_TYPE_ATTRIBUTE, xsiPrefix, typeValue);
        }
    }

    @Override
    public void writeXsiTypeAttribute(Descriptor xmlDescriptor, XMLSchemaReference xmlRef, boolean addToNamespaceResolver) {
        QName contextAsQName = xmlRef.getSchemaContextAsQName();

        if(contextAsQName == null){
            contextAsQName = xmlRef.getSchemaContextAsQName(namespaceResolver);
        }
        if (contextAsQName != null) {
            writeXsiTypeAttribute(xmlDescriptor, contextAsQName.getNamespaceURI(), contextAsQName.getLocalPart(), null, addToNamespaceResolver);
        }
    }

}
