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

import org.eclipse.persistence.internal.core.helper.CoreClassConstants;
import org.eclipse.persistence.internal.core.queries.CoreContainerPolicy;
import org.eclipse.persistence.internal.core.sessions.CoreAbstractSession;
import org.eclipse.persistence.internal.oxm.mappings.BinaryDataCollectionMapping;
import org.eclipse.persistence.internal.oxm.mappings.ChoiceCollectionMapping;
import org.eclipse.persistence.internal.oxm.mappings.CollectionReferenceMapping;
import org.eclipse.persistence.internal.oxm.mappings.CompositeCollectionMapping;
import org.eclipse.persistence.internal.oxm.mappings.DirectCollectionMapping;
import org.eclipse.persistence.internal.oxm.mappings.Field;
import org.eclipse.persistence.internal.oxm.mappings.Mapping;
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.oxm.mappings.nullpolicy.AbstractNullPolicy;
import org.eclipse.persistence.oxm.mappings.nullpolicy.XMLNullRepresentationType;

public class XMLChoiceCollectionMappingMarshalNodeValue extends MappingNodeValue implements ContainerValue {
    private ChoiceCollectionMapping xmlChoiceCollectionMapping;
    private Map<Field, NodeValue> fieldToNodeValues;
    private Map<Class, List<FieldNodeValue>> classToNodeValues;
    private NodeValue choiceElementNodeValue;
    private Field xmlField;
    private boolean isMixedNodeValue;
    private boolean isAny;
    private NodeValue anyNodeValue;
    private int index = -1;

    /**
     * This class is needed to hold field and nodeValue relationship.
     * If we have choice with different fields with the same (java class) type (e.g. via XmlAdapter),
     * there is need to know to which field we are holding the nodeValue.
     *
     * It is used in getNodeValueForValue method. If we knew only class relationship to nodeValue,
     * there is no way how to say that this nodeValue is related to the first or second field (or any other field with given java class).
     */
    private static class FieldNodeValue {
        //author Martin Vojtek (martin.vojtek@oracle.com)
        //see AdapterWithElementsTestCases
        private final Field field;
        private final NodeValue nodeValue;
        public FieldNodeValue(Field field, NodeValue nodeValue) {
            super();
            this.field = field;
            this.nodeValue = nodeValue;
        }
        public Field getField() {
            return field;
        }
        public NodeValue getNodeValue() {
            return nodeValue;
        }

    }

    public XMLChoiceCollectionMappingMarshalNodeValue(ChoiceCollectionMapping mapping, Field xmlField) {
        this.xmlChoiceCollectionMapping = mapping;
        this.xmlField = xmlField;
        isAny = mapping.isAny();
        initializeNodeValue();
    }

    @Override
    public boolean isOwningNode(XPathFragment xPathFragment) {
        if(isMixedNodeValue) {
            if(xPathFragment.nameIsText()) {
                return true;
            } else {
                return false;
            }
        }
        return choiceElementNodeValue.isOwningNode(xPathFragment);
    }


    public void setFieldToNodeValues(Map<Field, NodeValue> fieldToNodeValues) {
        this.fieldToNodeValues = fieldToNodeValues;
        this.classToNodeValues = new HashMap<>();
        for(Field nextField:fieldToNodeValues.keySet()) {
            Class associatedClass = ((Map<Field, Class>)this.xmlChoiceCollectionMapping.getFieldToClassMappings()).get(nextField);

            if (classToNodeValues.containsKey(associatedClass)) {
                classToNodeValues.get(associatedClass).add(new FieldNodeValue(nextField, fieldToNodeValues.get(nextField)));
            } else {
                List<FieldNodeValue> newFieldToNodeValuesList = new ArrayList<>();
                newFieldToNodeValuesList.add(new FieldNodeValue(nextField, fieldToNodeValues.get(nextField)));
                this.classToNodeValues.put(associatedClass, newFieldToNodeValuesList);
            }


        }

        Collection classes = this.classToNodeValues.keySet();
        for(Class nextClass:((Map<Class, Mapping>)this.xmlChoiceCollectionMapping.getChoiceElementMappingsByClass()).keySet()) {
            //Create node values for any classes that aren't already processed
            if(!(classes.contains(nextClass))) {
        Field field = (Field) xmlChoiceCollectionMapping.getClassToFieldMappings().get(nextClass);
                NodeValue nodeValue = new XMLChoiceCollectionMappingUnmarshalNodeValue(xmlChoiceCollectionMapping, xmlField, (Mapping) xmlChoiceCollectionMapping.getChoiceElementMappingsByClass().get(nextClass));
                List<FieldNodeValue> newFieldToNodeValuesList = new ArrayList<>();
                newFieldToNodeValuesList.add(new FieldNodeValue(field, nodeValue));
                this.classToNodeValues.put(nextClass, newFieldToNodeValuesList);
                NodeValue nodeValueForField = fieldToNodeValues.get(field);
                nodeValue.setXPathNode(nodeValueForField.getXPathNode());
            }
        }
    }

    private void initializeNodeValue() {
        Mapping xmlMapping = (Mapping) xmlChoiceCollectionMapping.getChoiceElementMappings().get(xmlField);
        if(xmlMapping instanceof BinaryDataCollectionMapping) {
            choiceElementNodeValue = new XMLBinaryDataCollectionMappingNodeValue((BinaryDataCollectionMapping)xmlMapping);
        } else if(xmlMapping instanceof DirectCollectionMapping) {
            choiceElementNodeValue = new XMLCompositeDirectCollectionMappingNodeValue((DirectCollectionMapping)xmlMapping);
        } else if(xmlMapping instanceof CompositeCollectionMapping) {
            choiceElementNodeValue = new XMLCompositeCollectionMappingNodeValue((CompositeCollectionMapping)xmlMapping);
        } else {
            CollectionReferenceMapping refMapping = ((CollectionReferenceMapping)xmlMapping);
            if(refMapping.usesSingleNode() || refMapping.getFields().size() == 1) {
                choiceElementNodeValue = new XMLCollectionReferenceMappingNodeValue(refMapping, xmlField);
            } else {
                choiceElementNodeValue = new XMLCollectionReferenceMappingMarshalNodeValue((CollectionReferenceMapping)xmlMapping);
            }
        }
        if(isAny){
            anyNodeValue = new XMLChoiceCollectionMappingUnmarshalNodeValue(xmlChoiceCollectionMapping, null, xmlChoiceCollectionMapping.getAnyMapping());
        }

    }

    @Override
    public boolean marshal(XPathFragment xPathFragment, MarshalRecord marshalRecord, Object object, CoreAbstractSession session, NamespaceResolver namespaceResolver) {
        if(xmlChoiceCollectionMapping.isReadOnly()) {
            return false;
        }

        Object value = xmlChoiceCollectionMapping.getAttributeValueFromObject(object);
        if(value == null) {
            AbstractNullPolicy wrapperNP = xmlChoiceCollectionMapping.getWrapperNullPolicy();
            if (wrapperNP != null && wrapperNP.getMarshalNullRepresentation() == XMLNullRepresentationType.XSI_NIL) {
                marshalRecord.nilSimple(namespaceResolver);
                return true;
            } else {
                return false;
            }
        }
        CoreContainerPolicy cp = getContainerPolicy();
        Object iterator = cp.iteratorFor(value);
        if (null != iterator && cp.hasNext(iterator)) {
            if(xPathFragment != null) {
                XPathFragment groupingFragment = marshalRecord.openStartGroupingElements(namespaceResolver);
                marshalRecord.closeStartGroupingElements(groupingFragment);
            }
        } else {
            return marshalRecord.emptyCollection(xPathFragment, namespaceResolver, xmlChoiceCollectionMapping.getWrapperNullPolicy() != null);
        }

        if(marshalRecord.getMarshaller().isApplicationJSON()){
            List<NodeValue> nodeValues = new ArrayList();
            List<List> values = new ArrayList<>();

            NodeValue mixedNodeValue = null;
            List mixedValues = null;

            //sort the elements. Results will be a list of nodevalues and a corresponding list of
            //collections associated with those nodevalues
            while(cp.hasNext(iterator)) {
                Object nextValue = xmlChoiceCollectionMapping.convertObjectValueToDataValue(cp.next(iterator, session), session, marshalRecord.getMarshaller());
                NodeValue nodeValue = getNodeValueForValue(nextValue);

                if(nodeValue != null){
                    if(nodeValue == this){
                        mixedNodeValue = this;
                        if(mixedValues == null){
                            mixedValues = new ArrayList();
                        }
                        mixedValues.add(nextValue);
                    }else{
                        int index = nodeValues.indexOf(nodeValue);
                        if(index > -1){
                            values.get(index).add(nextValue);
                        }else{
                            nodeValues.add(nodeValue);
                            List valuesList = new ArrayList();
                            valuesList.add(nextValue);
                            values.add(valuesList);
                        }
                    }
                }
            }
            //always write out mixed values last so we can determine if the textWrapper key needs to be written.
            if(mixedNodeValue != null){
                nodeValues.add(mixedNodeValue);
                values.add(mixedValues);
            }

            for(int i =0;i < nodeValues.size(); i++){
                NodeValue associatedNodeValue = nodeValues.get(i);
                List listValue = values.get(i);

                XPathFragment frag = null;
                if(associatedNodeValue == this){
                    frag = marshalRecord.getTextWrapperFragment();
                }else{
                   frag = associatedNodeValue.getXPathNode().getXPathFragment();
                   if(frag != null){
                       frag = getOwningFragment(associatedNodeValue, frag);
                       associatedNodeValue = ((XMLChoiceCollectionMappingUnmarshalNodeValue)associatedNodeValue).getChoiceElementMarshalNodeValue();
                   }
                }
                if(frag != null || associatedNodeValue.isAnyMappingNodeValue()){
                    int valueSize = listValue.size();
                    if(valueSize > 1 || !marshalRecord.getMarshaller().isReduceAnyArrays()) {
                        marshalRecord.startCollection();
                    }

                    for(int j=0;j<valueSize; j++){
                        marshalSingleValueWithNodeValue(frag, marshalRecord, object, listValue.get(j), session, namespaceResolver, ObjectMarshalContext.getInstance(), associatedNodeValue);
                    }
                    if(valueSize > 1 || !marshalRecord.getMarshaller().isReduceAnyArrays()) {
                        marshalRecord.endCollection();
                    }
                }
            }
        }
        else{
            while(cp.hasNext(iterator)) {
                Object nextValue = cp.next(iterator, session);
                marshalSingleValue(xPathFragment, marshalRecord, object, nextValue, session, namespaceResolver, ObjectMarshalContext.getInstance());
            }
        }
        return true;
    }

    @Override
    public boolean marshalSingleValue(XPathFragment xPathFragment, MarshalRecord marshalRecord, Object object, Object value, CoreAbstractSession session, NamespaceResolver namespaceResolver, MarshalContext marshalContext) {
        value = xmlChoiceCollectionMapping.convertObjectValueToDataValue(value, session, marshalRecord.getMarshaller());
        if(value !=null && value.getClass() == CoreClassConstants.STRING && this.xmlChoiceCollectionMapping.isMixedContent()) {
            marshalMixedContent(marshalRecord, (String)value);
            return true;
        }
        NodeValue associatedNodeValue = getNodeValueForValue(value);
        if(associatedNodeValue != null) {
            if(associatedNodeValue.isAnyMappingNodeValue()){
                //NodeValue unwrappedNodeValue = ((XMLChoiceCollectionMappingUnmarshalNodeValue)associatedNodeValue).getChoiceElementMarshalNodeValue();
                return marshalSingleValueWithNodeValue(null, marshalRecord, object, value, session, namespaceResolver, marshalContext, associatedNodeValue);
            }
            else{
            //Find the correct fragment
            XPathFragment frag = associatedNodeValue.getXPathNode().getXPathFragment();
            if(frag != null){
                frag = getOwningFragment(associatedNodeValue, frag);
                NodeValue unwrappedNodeValue = ((XMLChoiceCollectionMappingUnmarshalNodeValue)associatedNodeValue).getChoiceElementMarshalNodeValue();
                return marshalSingleValueWithNodeValue(frag, marshalRecord, object, value, session, namespaceResolver, marshalContext, unwrappedNodeValue);
            }
            }
        }
        return true;
    }

    private boolean marshalSingleValueWithNodeValue(XPathFragment xPathFragment, MarshalRecord marshalRecord, Object object, Object value, CoreAbstractSession session, NamespaceResolver namespaceResolver, MarshalContext marshalContext, NodeValue unwrappedNodeValue) {

        if(unwrappedNodeValue != null){
            unwrappedNodeValue.marshalSingleValue(xPathFragment, marshalRecord, object, value, session, namespaceResolver, marshalContext);
        }
        return true;
    }

    private NodeValue getNodeValueForValue(Object value){
        if(value == null){
            Iterator<NodeValue> nodeValues= fieldToNodeValues.values().iterator();
            while(nodeValues.hasNext()) {

                XMLChoiceCollectionMappingUnmarshalNodeValue unmarshalNodeValue = (XMLChoiceCollectionMappingUnmarshalNodeValue)nodeValues.next();
                NodeValue nextNodeValue = unmarshalNodeValue.getChoiceElementMarshalNodeValue();

                if(nextNodeValue instanceof MappingNodeValue){
                    Mapping nextMapping = ((MappingNodeValue)nextNodeValue).getMapping();
                    if(nextMapping.isAbstractCompositeCollectionMapping()){
                        if(((CompositeCollectionMapping)nextMapping).getNullPolicy().isNullRepresentedByXsiNil()){
                            return unmarshalNodeValue;
                        }
                    }else if(nextMapping.isAbstractCompositeDirectCollectionMapping()){
                        if(((DirectCollectionMapping)nextMapping).getNullPolicy().isNullRepresentedByXsiNil()){
                            return unmarshalNodeValue;
                        }
                    }else if(nextMapping instanceof BinaryDataCollectionMapping){
                        if(((BinaryDataCollectionMapping)nextMapping).getNullPolicy().isNullRepresentedByXsiNil()){
                            return unmarshalNodeValue;
                        }
                    }
                }

            }
            return null;
        }

        Field associatedField = null;
        NodeValue nodeValue = null;
        if(value instanceof Root) {
            Root rootValue = (Root)value;
            String localName = rootValue.getLocalName();
            String namespaceUri = rootValue.getNamespaceURI();
            Object fieldValue = rootValue.getObject();
            associatedField = getFieldForName(localName, namespaceUri);
            if(associatedField == null) {
                if(xmlChoiceCollectionMapping.isAny()) {
                    return this.anyNodeValue;
                }
                Class theClass = fieldValue.getClass();
                while(associatedField == null) {
                    associatedField = (Field) xmlChoiceCollectionMapping.getClassToFieldMappings().get(theClass);
                    if(theClass.getSuperclass() != null) {
                        theClass = theClass.getSuperclass();
                    } else {
                        break;
                    }
                }
            }
            if(associatedField != null) {
                nodeValue = this.fieldToNodeValues.get(associatedField);
            }
        } else {
            Class theClass = value.getClass();
            while(associatedField == null) {
                associatedField = (Field) xmlChoiceCollectionMapping.getClassToFieldMappings().get(theClass);
                List<FieldNodeValue> fieldNodes = classToNodeValues.get(theClass);

                nodeValue = null;
                if (null != fieldNodes) {

                    //match also field
                    if (null != associatedField && fieldNodes.size() > 1) {
                        for (FieldNodeValue fieldNode : fieldNodes) {
                            if (fieldNode.getField().equals(associatedField)) {
                                nodeValue = fieldNode.getNodeValue();
                            }
                        }
                    }

                    if (null == nodeValue && fieldNodes.size() > 0) {
                        nodeValue = fieldNodes.get(0).getNodeValue();
                    }
                }

                if(theClass.getSuperclass() != null) {
                    theClass = theClass.getSuperclass();
                } else {
                    break;
                }
            }
        }
        if(associatedField == null) {
            //check the field associations
            List<Field> sourceFields = null;
            Class theClass = value.getClass();
            while(theClass != null) {
                sourceFields = (List<Field>) xmlChoiceCollectionMapping.getClassToSourceFieldsMappings().get(theClass);
                if(sourceFields != null) {
                    break;
                }
                theClass = theClass.getSuperclass();
            }
            if(sourceFields != null) {
                associatedField = sourceFields.get(0);
                nodeValue = fieldToNodeValues.get(associatedField);
            }
        }
        if(nodeValue != null){
            return nodeValue;
        }
        if(associatedField != null) {
            return fieldToNodeValues.get(associatedField);
        }
        if (xmlChoiceCollectionMapping.isMixedContent() && value instanceof String){
            //use this as a placeholder for the nodevalue for mixedcontent
            return this;
        }
        if (xmlChoiceCollectionMapping.isAny()){
            return anyNodeValue;
        }
        return null;
    }


    private XPathFragment getOwningFragment(NodeValue nodeValue, XPathFragment frag){
        while(frag != null) {
               if(nodeValue.isOwningNode(frag)) {
                   return frag;
               }
               frag = frag.getNextFragment();
           }
        return null;
    }

    private void marshalMixedContent(MarshalRecord record, String value) {
        record.characters(value);
    }

    private Field getFieldForName(String localName, String namespaceUri) {
        Iterator<Field> fields = fieldToNodeValues.keySet().iterator();
        while(fields.hasNext()) {
            Field nextField = fields.next();
            if(nextField != null){
            XPathFragment fragment = nextField.getXPathFragment();
            while(fragment != null && (!fragment.nameIsText())) {
                if(fragment.getNextFragment() == null || fragment.getHasText()) {
                    if(fragment.getLocalName().equals(localName)) {
                        String fragUri = fragment.getNamespaceURI();
                        if((namespaceUri == null && fragUri == null) || (namespaceUri != null && fragUri != null && namespaceUri.equals(fragUri))) {
                            return nextField;
                        }
                    }
                }
                fragment = fragment.getNextFragment();
            }
            }
        }
        return null;
    }

    public Collection<NodeValue> getAllNodeValues() {
        return this.fieldToNodeValues.values();
    }

    @Override
    public boolean isMarshalNodeValue() {
        return true;
    }

    @Override
    public boolean isUnmarshalNodeValue() {
        return false;
    }

    @Override
    public boolean isWrapperAllowedAsCollectionName() {
        return false;
    }

    @Override
    public Object getContainerInstance() {
        return getContainerPolicy().containerInstance();
    }

    @Override
    public void setContainerInstance(Object object, Object containerInstance) {
        xmlChoiceCollectionMapping.setAttributeValueInObject(object, containerInstance);
    }

    @Override
    public CoreContainerPolicy getContainerPolicy() {
        return xmlChoiceCollectionMapping.getContainerPolicy();
    }

    @Override
    public boolean isContainerValue() {
        return true;
    }

    @Override
    public ChoiceCollectionMapping getMapping() {
        return xmlChoiceCollectionMapping;
    }

    @Override
    public boolean getReuseContainer() {
        return getMapping().getReuseContainer();
    }

    /**
     * INTERNAL:
     * Indicates that this is the choice mapping node value that represents the mixed content.
     */
    public void setIsMixedNodeValue(boolean b) {
        this.isMixedNodeValue = b;
    }

    /**
     * INTERNAL:
     * Return true if this is the node value representing mixed content.
     */
    @Override
    public boolean isMixedContentNodeValue() {
        return this.isMixedNodeValue;
    }

    /**
     *  INTERNAL:
     *  Used to track the index of the corresponding containerInstance in the containerInstances Object[] on UnmarshalRecord
     */
    @Override
    public void setIndex(int index){
        this.index = index;
    }

    /**
     * INTERNAL:
     * Set to track the index of the corresponding containerInstance in the containerInstances Object[] on UnmarshalRecord
     * Set during TreeObjectBuilder initialization
     */
    @Override
    public int getIndex(){
        return index;
    }

    /**
     * INTERNAL
     * Return true if an empty container should be set on the object if there
     * is no presence of the collection in the XML document.
     * @since EclipseLink 2.3.3
     */
    @Override
    public boolean isDefaultEmptyContainer() {
        return getMapping().isDefaultEmptyContainer();
    }

    @Override
    public void setXPathNode(XPathNode xPathNode) {
        super.setXPathNode(xPathNode);
        if(this.anyNodeValue != null) {
            this.anyNodeValue.setXPathNode(xPathNode);
        }
    }

}
