/*
 * 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<Class> 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);
        }
    }

}
