/*
 * Copyright (c) 1998, 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:
//     Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.internal.oxm;

import java.util.ArrayList;

import javax.xml.namespace.QName;

import org.eclipse.persistence.core.sessions.CoreSession;
import org.eclipse.persistence.internal.core.sessions.CoreAbstractSession;
import org.eclipse.persistence.internal.oxm.mappings.DirectMapping;
import org.eclipse.persistence.internal.oxm.mappings.Field;
import org.eclipse.persistence.internal.oxm.record.MarshalContext;
import org.eclipse.persistence.internal.oxm.record.MarshalRecord;
import org.eclipse.persistence.internal.oxm.record.ObjectMarshalContext;
import org.eclipse.persistence.internal.oxm.record.UnmarshalRecord;

/**
 * INTERNAL:
 * <p><b>Purpose</b>: This is how the XML Direct Mapping is handled when used
 * with the TreeObjectBuilder.</p>
 */
public class XMLDirectMappingNodeValue extends MappingNodeValue implements NullCapableValue {
    private DirectMapping xmlDirectMapping;

    public XMLDirectMappingNodeValue(DirectMapping xmlDirectMapping) {
        this.xmlDirectMapping = xmlDirectMapping;
    }

    @Override
    public void setXPathNode(XPathNode xPathNode) {
        super.setXPathNode(xPathNode);
        xmlDirectMapping.getNullPolicy().xPathNode(xPathNode, this);
        if(((Field) xmlDirectMapping.getField()).isTypedTextField()) {
            XPathFragment typeAttributeXPathFragment = new XPathFragment();
            typeAttributeXPathFragment.setAttribute(true);
            typeAttributeXPathFragment.setLocalName(Constants.SCHEMA_TYPE_ATTRIBUTE);
            typeAttributeXPathFragment.setNamespaceURI(javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI);
            xPathNode.getParent().addChild(typeAttributeXPathFragment, new TypeNodeValue(), null);
        }
    }

    @Override
    public boolean isOwningNode(XPathFragment xPathFragment) {
        return xPathFragment.hasAttribute || xPathFragment.nameIsText;
    }

    @Override
    public boolean marshal(XPathFragment xPathFragment, MarshalRecord marshalRecord, Object object, CoreAbstractSession session, NamespaceResolver namespaceResolver) {
        return marshal(xPathFragment, marshalRecord, object, session, namespaceResolver, ObjectMarshalContext.getInstance());
    }

    @Override
    public boolean marshal(XPathFragment xPathFragment, MarshalRecord marshalRecord, Object object, CoreAbstractSession session, NamespaceResolver namespaceResolver, MarshalContext marshalContext) {
        if (xmlDirectMapping.isReadOnly()) {
            return false;
        }
        Object objectValue = marshalContext.getAttributeValue(object, xmlDirectMapping);
        return this.marshalSingleValue(xPathFragment, marshalRecord, object, objectValue, session, namespaceResolver, marshalContext);
    }

    @Override
    public boolean marshalSingleValue(XPathFragment xPathFragment, MarshalRecord marshalRecord, Object object, Object objectValue, CoreAbstractSession session, NamespaceResolver namespaceResolver, MarshalContext marshalContext) {
        Object fieldValue = xmlDirectMapping.getFieldValue(objectValue, session, marshalRecord);

        // Check for a null value
        if (null == fieldValue) {
            // Perform marshal operations based on the null policy
            return xmlDirectMapping.getNullPolicy().directMarshal(xPathFragment, marshalRecord, object, session, namespaceResolver);
        } else {
            QName schemaType = ((Field) xmlDirectMapping.getField()).getSchemaTypeForValue(fieldValue, session);
            XPathFragment groupingFragment = null;
            boolean isQName = false;
            if(Constants.QNAME_QNAME.equals(schemaType)) {
                //if marshalling a QName, handle grouping elements here in case namespace adjustments need
                //to happen
                groupingFragment = openGroupingElementsForQName((QName)fieldValue, marshalRecord);
                isQName = true;
            }
            if(groupingFragment == null) {
                groupingFragment = marshalRecord.openStartGroupingElements(namespaceResolver);
            }
            if (xPathFragment.hasAttribute) {
                marshalRecord.attribute(xPathFragment, namespaceResolver, fieldValue, schemaType);
                marshalRecord.closeStartGroupingElements(groupingFragment);
            } else {
                if(((Field) xmlDirectMapping.getField()).getXPathFragment().nameIsText ){
                    XPathNode parentNode = xPathNode.getParent();
                    if(parentNode.getAttributeChildren() != null){
                        marshalRecord.forceValueWrapper();
                    }
                }
                Field xmlField = (Field) xmlDirectMapping.getField();
                if (xmlField.isTypedTextField()) {
                    updateNamespaces(schemaType, marshalRecord, xmlField);
                }
                marshalRecord.closeStartGroupingElements(groupingFragment);
                marshalRecord.characters(schemaType, fieldValue, null, xmlDirectMapping.isCDATA());
            }
            if(isQName) {
                //check to see if the last grouping fragment was swapped
                XPathFragment fragment = getLastGroupingFragment();
                if(fragment != groupingFragment) {
                    marshalRecord.endElement(groupingFragment, namespaceResolver);
                    return false;
                }
            }
            return true;
        }
    }

    private XPathFragment getLastGroupingFragment() {
        XPathFragment fragment = ((Field)this.getMapping().getField()).getXPathFragment();
        if(fragment.hasAttribute || fragment.nameIsText) {
            return null;
        }
        while(fragment.getNextFragment() != null) {
            if(fragment.getNextFragment().nameIsText || fragment.getNextFragment().hasAttribute) {
                return fragment;
            }
            fragment = fragment.getNextFragment();
        }
        return fragment;
    }
    private XPathFragment openGroupingElementsForQName(QName fieldValue, MarshalRecord marshalRecord) {
        XPathFragment xPathFragment = null;
        ArrayList<XPathNode> groupingElements = marshalRecord.getGroupingElements();
        NamespaceResolver namespaceResolver = marshalRecord.getNamespaceResolver();
        if((fieldValue.getNamespaceURI() == null || fieldValue.getNamespaceURI().equals(Constants.EMPTY_STRING)) && marshalRecord.getNamespaceResolver().getDefaultNamespaceURI() != null) {
            //In this case, the last grouping element may need to have a new prefix generated.
            for (int x = 0, groupingElementsSize = groupingElements.size(); x < groupingElementsSize; x++) {
                XPathNode xPathNode = groupingElements.get(x);
                xPathFragment = xPathNode.getXPathFragment();
                if(x == (groupingElements.size() - 1) && namespaceResolver.getDefaultNamespaceURI().equals(xPathFragment.getNamespaceURI()) && xPathFragment.getPrefix() == null) {
                    String prefix = namespaceResolver.generatePrefix();
                    String xPath = prefix +  Constants.COLON + xPathFragment.getShortName();
                    XPathFragment newFragment = new XPathFragment(xPath);
                    newFragment.setNamespaceURI(namespaceResolver.getDefaultNamespaceURI());
                    marshalRecord.openStartElement(newFragment, namespaceResolver);
                    marshalRecord.namespaceDeclaration(prefix,  namespaceResolver.getDefaultNamespaceURI());
                    marshalRecord.predicateAttribute(xPathFragment, namespaceResolver);
                    xPathFragment = newFragment;
                } else {
                    marshalRecord.openStartElement(xPathFragment, namespaceResolver);
                    marshalRecord.predicateAttribute(xPathFragment, namespaceResolver);
                    marshalRecord.closeStartElement();
                }
            }
            marshalRecord.setGroupingElement(null);

        }
        return xPathFragment;


    }

    @Override
    public void attribute(UnmarshalRecord unmarshalRecord, String namespaceURI, String localName, String value) {
        unmarshalRecord.removeNullCapableValue(this);
        Field xmlField = (Field) xmlDirectMapping.getField();
        CoreAbstractSession session = unmarshalRecord.getSession();
        Object realValue = unmarshalRecord.getXMLReader().convertValueBasedOnSchemaType(xmlField, value, (ConversionManager) session.getDatasourcePlatform().getConversionManager(), unmarshalRecord);

        // Perform operations on the object based on the null policy
        Object convertedValue = xmlDirectMapping.getAttributeValue(realValue, session, unmarshalRecord);
        xmlDirectMapping.setAttributeValueInObject(unmarshalRecord.getCurrentObject(), convertedValue);
    }

    @Override
    public void endElement(XPathFragment xPathFragment, UnmarshalRecord unmarshalRecord) {
        if(unmarshalRecord.isNil() && xmlDirectMapping.getNullPolicy().isNullRepresentedByXsiNil()){
            Object convertedValue = xmlDirectMapping.getAttributeValue(org.eclipse.persistence.oxm.record.XMLRecord.NIL, unmarshalRecord.getSession(), unmarshalRecord);
            unmarshalRecord.setAttributeValue(convertedValue, xmlDirectMapping);
            unmarshalRecord.resetStringBuffer();
            return;
        }

        unmarshalRecord.removeNullCapableValue(this);
        Field xmlField = (Field) xmlDirectMapping.getField();
        if (!xmlField.getLastXPathFragment().nameIsText) {
            return;
        }
        Object value;
        CharSequence unmarshalRecordCharacters = unmarshalRecord.getCharacters();
        if (unmarshalRecordCharacters.length() == 0) {
            value = xmlDirectMapping.getNullValue();
        } else {
            value = unmarshalRecordCharacters.toString();
        }
        unmarshalRecord.resetStringBuffer();
        CoreAbstractSession session = unmarshalRecord.getSession();
        ConversionManager conversionManager = (ConversionManager) session.getDatasourcePlatform().getConversionManager();
        QName typeQName = unmarshalRecord.getTypeQName();
        if (typeQName != null) {
            Class typeClass = xmlField.getJavaClass(typeQName, conversionManager);
            value = conversionManager.convertObject(value, typeClass, typeQName);
        } else {
            value = unmarshalRecord.getXMLReader().convertValueBasedOnSchemaType(xmlField, value, conversionManager, unmarshalRecord);
        }

        Object convertedValue = xmlDirectMapping.getAttributeValue(value, session, unmarshalRecord);
        unmarshalRecord.setAttributeValue(convertedValue, xmlDirectMapping);
    }

    @Override
    public void setNullValue(Object object, CoreSession session) {
        Object value = xmlDirectMapping.getObjectValue(null, session);
        xmlDirectMapping.setAttributeValueInObject(object, value);
    }

    @Override
    public boolean isNullCapableValue() {
        if(xmlDirectMapping.getAttributeAccessor().isInstanceVariableAttributeAccessor() && !xmlDirectMapping.hasConverter() && xmlDirectMapping.getNullValue() == null) {
             return false;
        }
        return xmlDirectMapping.getNullPolicy().getIsSetPerformedForAbsentNode();
    }

    @Override
    public DirectMapping getMapping() {
        return xmlDirectMapping;
    }

    @Override
    public boolean isWhitespaceAware() {
        return !xmlDirectMapping.getNullPolicy().isNullRepresentedByEmptyNode();
    }

}
