/*
 * 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.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.eclipse.persistence.internal.core.helper.CoreField;
import org.eclipse.persistence.internal.core.sessions.CoreAbstractSession;
import org.eclipse.persistence.internal.oxm.mappings.BinaryDataMapping;
import org.eclipse.persistence.internal.oxm.mappings.ChoiceObjectMapping;
import org.eclipse.persistence.internal.oxm.mappings.CompositeObjectMapping;
import org.eclipse.persistence.internal.oxm.mappings.DirectMapping;
import org.eclipse.persistence.internal.oxm.mappings.Field;
import org.eclipse.persistence.internal.oxm.mappings.Mapping;
import org.eclipse.persistence.internal.oxm.mappings.ObjectReferenceMapping;
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.UnmarshalContext;
import org.eclipse.persistence.internal.oxm.record.UnmarshalRecord;

import org.xml.sax.Attributes;

/**
 * INTERNAL:
 * <p><b>Purpose</b>: This is how the XML Choice Collection Mapping is
 * handled when used with the TreeObjectBuilder.</p>
 * @author mmacivor
 */

public class XMLChoiceObjectMappingNodeValue extends MappingNodeValue {

    private NodeValue choiceElementNodeValue;
    private Map<Class<?>, NodeValue> choiceElementNodeValues;
    private ChoiceObjectMapping xmlChoiceMapping;
    //The first node value of the choice will be registered as a null capable value. If any
    //of the choice elements get hit, this needs to be removed as a null value.
    private XMLChoiceObjectMappingNodeValue nullCapableNodeValue;
    private Field xmlField;

    public XMLChoiceObjectMappingNodeValue(ChoiceObjectMapping mapping, Field xmlField) {
        this.xmlChoiceMapping = mapping;
        this.xmlField = xmlField;
        initializeNodeValue();
    }

    @Override
    public boolean isOwningNode(XPathFragment xPathFragment) {
        return choiceElementNodeValue.isOwningNode(xPathFragment);
    }

    public void initializeNodeValue() {
        Mapping xmlMapping = (Mapping) xmlChoiceMapping.getChoiceElementMappings().get(xmlField);
        choiceElementNodeValue = getNodeValueForMapping(xmlMapping);
        //check for mappings to other classes with the same field
        for(Entry<Class<?>, Mapping> entry: ((Map<Class<?>, Mapping>)xmlChoiceMapping.getChoiceElementMappingsByClass()).entrySet()) {
            Field field = (Field) xmlChoiceMapping.getClassToFieldMappings().get(entry.getKey());
            if(field != null && field.equals(this.xmlField)) {
                Mapping mappingForClass = entry.getValue();
                if(mappingForClass != xmlMapping) {
                    if(this.choiceElementNodeValues == null) {
                        choiceElementNodeValues = new HashMap<>();
                    }
                    choiceElementNodeValues.put(entry.getKey(), getNodeValueForMapping(mappingForClass));
                }
            }
        }
    }

    private NodeValue getNodeValueForMapping(Mapping xmlMapping) {
        if(xmlMapping instanceof BinaryDataMapping){
            return new XMLBinaryDataMappingNodeValue((BinaryDataMapping)xmlMapping);
        } else if(xmlMapping instanceof DirectMapping) {
            return new XMLDirectMappingNodeValue((DirectMapping)xmlMapping);
        } else if(xmlMapping instanceof ObjectReferenceMapping) {
            return new XMLObjectReferenceMappingNodeValue((ObjectReferenceMapping)xmlMapping, xmlField);
        } else {
            return new XMLCompositeObjectMappingNodeValue((CompositeObjectMapping)xmlMapping);
        }
    }
    public void setNullCapableNodeValue(XMLChoiceObjectMappingNodeValue nodeValue) {
        this.nullCapableNodeValue = nodeValue;
    }

    @Override
    public boolean marshal(XPathFragment xPathFragment, MarshalRecord marshalRecord, Object object, CoreAbstractSession session, NamespaceResolver namespaceResolver) {
        return this.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(xmlChoiceMapping.isReadOnly()) {
            return false;
        }
        Object value = xmlChoiceMapping.getFieldValue(object, session, marshalRecord);
        return this.marshalSingleValue(xPathFragment, marshalRecord, object, value, session, namespaceResolver, marshalContext);
    }

    @Override
    public boolean marshalSingleValue(XPathFragment xPathFragment, MarshalRecord marshalRecord, Object object, Object value, CoreAbstractSession session, NamespaceResolver namespaceResolver, MarshalContext marshalContext) {
        Class<?> valueClass = null;
        if (value instanceof Root) {
            Root root = (Root)value;
            for(CoreField next: (List<CoreField>) this.xmlChoiceMapping.getFields()) {
                XPathFragment fragment = ((Field)next).getXPathFragment();
                while(fragment != null && !fragment.nameIsText) {
                    if(fragment.getNextFragment() == null || fragment.getHasText()) {
                        if(fragment.getLocalName().equals(root.getLocalName())) {
                            String fragUri = fragment.getNamespaceURI();
                            String namespaceUri = root.getNamespaceURI();
                            if((namespaceUri == null && fragUri == null) || (namespaceUri != null && fragUri != null && namespaceUri.equals(fragUri))) {
                                if(next == this.xmlField) {
                                    return this.choiceElementNodeValue.marshalSingleValue(xPathFragment, marshalRecord, object, value, session, namespaceResolver, marshalContext);
                                } else {
                                    //If this root is associated with another field, then return and let that NodeValue handle it
                                    return false;
                                }
                            }
                        }
                    }
                    fragment = fragment.getNextFragment();
                }
            }
            valueClass = root.getObject().getClass();
        }
        if (value != null) {
            if(valueClass == null) {
                valueClass = value.getClass();
            }
            Field fieldForClass = null;
            Class<?> theClass = valueClass;
            while(theClass != null) {
                fieldForClass = (Field) xmlChoiceMapping.getClassToFieldMappings().get(valueClass);
                if(fieldForClass != null) {
                    break;
                }
                theClass = theClass.getSuperclass();
            }
            if (fieldForClass != null && fieldForClass.equals(this.xmlField)) {
                if(this.choiceElementNodeValues != null) {
                    NodeValue nodeValue = this.choiceElementNodeValues.get(theClass);
                    if(nodeValue != null) {
                        return nodeValue.marshalSingleValue(xPathFragment, marshalRecord, object, value, session, namespaceResolver, marshalContext);
                    }
                }
                return this.choiceElementNodeValue.marshalSingleValue(xPathFragment, marshalRecord, object, value, session, namespaceResolver, marshalContext);
            }
            List<Field> sourceFields = null;
            theClass = valueClass;
            while(theClass != null) {
                sourceFields = (List<Field>) xmlChoiceMapping.getClassToSourceFieldsMappings().get(theClass);
                if(sourceFields != null) {
                    break;
                }
                theClass = theClass.getSuperclass();
            }
            if (sourceFields != null && sourceFields.contains(this.xmlField)) {
                return this.choiceElementNodeValue.marshalSingleValue(xPathFragment, marshalRecord, object, value, session, namespaceResolver, marshalContext);
            }
        }
        return false;
    }

    @Override
    public void endElement(XPathFragment xPathFragment, UnmarshalRecord unmarshalRecord) {
        if(null != xmlChoiceMapping.getConverter()) {
            UnmarshalContext unmarshalContext = unmarshalRecord.getUnmarshalContext();
            unmarshalRecord.setUnmarshalContext(new ChoiceUnmarshalContext(unmarshalContext, xmlChoiceMapping));
            this.choiceElementNodeValue.endElement(xPathFragment, unmarshalRecord);
            unmarshalRecord.setUnmarshalContext(unmarshalContext);
        } else {
            this.choiceElementNodeValue.endElement(xPathFragment, unmarshalRecord);
        }
    }

    @Override
    public boolean startElement(XPathFragment xPathFragment, UnmarshalRecord unmarshalRecord, Attributes atts) {
        return this.choiceElementNodeValue.startElement(xPathFragment, unmarshalRecord, atts);
    }

    @Override
    public void setXPathNode(XPathNode xPathNode) {
        super.setXPathNode(xPathNode);
        this.choiceElementNodeValue.setXPathNode(xPathNode);
        if(this.choiceElementNodeValues != null) {
            for(NodeValue next:choiceElementNodeValues.values()) {
                next.setXPathNode(xPathNode);
            }
        }
    }

    /**
     * The underlying choice element node value will handle attributes.
     *
     */
    @Override
    public void attribute(UnmarshalRecord unmarshalRecord, String URI, String localName, String value) {
        this.choiceElementNodeValue.attribute(unmarshalRecord, URI, localName, value);
    }

    @Override
    public Mapping getMapping() {
        return this.xmlChoiceMapping;
    }

    @Override
    public boolean isWhitespaceAware() {
        return choiceElementNodeValue.isWhitespaceAware();
    }
}
