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

import javax.xml.namespace.QName;

import org.eclipse.persistence.internal.core.queries.CoreContainerPolicy;
import org.eclipse.persistence.internal.core.queries.CoreMappedKeyMapContainerPolicy;
import org.eclipse.persistence.internal.core.sessions.CoreAbstractSession;
import org.eclipse.persistence.internal.oxm.mappings.AnyAttributeMapping;
import org.eclipse.persistence.internal.oxm.record.MarshalContext;
import org.eclipse.persistence.internal.oxm.record.MarshalRecord;
import org.eclipse.persistence.internal.oxm.record.UnmarshalRecord;

/**
 * INTERNAL:
 * <p><b>Purpose</b>: This is how the XML Any Attribute Mapping is handled when
 * used with the TreeObjectBuilder.</p>
 */

public class XMLAnyAttributeMappingNodeValue extends MappingNodeValue implements ContainerValue {
    private AnyAttributeMapping xmlAnyAttributeMapping;
    private int index = -1;

    public XMLAnyAttributeMappingNodeValue(AnyAttributeMapping xmlAnyAttributeMapping) {
        super();
        this.xmlAnyAttributeMapping = xmlAnyAttributeMapping;
    }

    @Override
    public boolean isOwningNode(XPathFragment xPathFragment) {
        return xPathFragment == null;
    }

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

    @Override
    public boolean marshal(XPathFragment xPathFragment, MarshalRecord marshalRecord, Object object, CoreAbstractSession session, NamespaceResolver namespaceResolver) {
        if (xmlAnyAttributeMapping.isReadOnly()) {
            return false;
        }
        Object collection = xmlAnyAttributeMapping.getAttributeValueFromObject(object);
        if (collection == null) {
            return false;
        }
        CoreContainerPolicy cp = getContainerPolicy();
        Object iter = cp.iteratorFor(collection);
        if (!cp.hasNext(iter)) {
            return false;
        }
        XPathFragment groupingElements = marshalRecord.openStartGroupingElements(namespaceResolver);
        List extraNamespaces = new ArrayList();
        NamespaceResolver nr = marshalRecord.getNamespaceResolver();
        while (cp.hasNext(iter)) {
            Map.Entry entry = (Map.Entry)cp.nextEntry(iter, session);
            Object key = entry.getKey();
            if (key instanceof QName) {
                QName name = (QName) key;
                String value = entry.getValue().toString();

                String qualifiedName = name.getLocalPart();
                if (nr != null) {
                    String prefix = nr.resolveNamespaceURI(name.getNamespaceURI());
                    if ((prefix != null) && prefix.length() > 0) {
                        qualifiedName = prefix + Constants.COLON+ qualifiedName;
                    } else if (name.getNamespaceURI() != null && name.getNamespaceURI().length() > 0) {
                        String generatedPrefix = nr.generatePrefix();
                        if(marshalRecord.hasCustomNamespaceMapper()) {
                            String customPrefix = marshalRecord.getMarshaller().getNamespacePrefixMapper().getPreferredPrefix(name.getNamespaceURI(), generatedPrefix, true);
                            if(customPrefix != null && customPrefix.length() > 0) {
                                generatedPrefix = customPrefix;
                            }
                        }
                        qualifiedName = generatedPrefix + Constants.COLON + qualifiedName;
                        nr.put(generatedPrefix, name.getNamespaceURI());
                        extraNamespaces.add(generatedPrefix);
                        marshalRecord.namespaceDeclaration(generatedPrefix, name.getNamespaceURI());

                    }
                }
                if(javax.xml.XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(name.getNamespaceURI())){
                    marshalRecord.namespaceDeclaration(name.getLocalPart(), name.getNamespaceURI());
                }else{
                    marshalRecord.attribute(name.getNamespaceURI(), name.getLocalPart(), qualifiedName, value);
                }
            }
        }

        for (int i = 0; i < extraNamespaces.size(); i++) {
            marshalRecord.getNamespaceResolver().removeNamespace((String) extraNamespaces.get(i));
        }
        marshalRecord.closeStartGroupingElements(groupingElements);
        return true;
    }

    @Override
    public void attribute(UnmarshalRecord unmarshalRecord, String namespaceURI, String localName, String value) {
        boolean includeAttribute = true;
        if(!xmlAnyAttributeMapping.isNamespaceDeclarationIncluded() && javax.xml.XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(namespaceURI)){
            includeAttribute = false;
        }else if(!xmlAnyAttributeMapping.isSchemaInstanceIncluded() && javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI.equals(namespaceURI)){
            includeAttribute = false;
        }

        if(includeAttribute){
            CoreContainerPolicy cp = xmlAnyAttributeMapping.getContainerPolicy();
            Object containerInstance = unmarshalRecord.getContainerInstance(this);
            QName key = new QName(namespaceURI, localName);
            cp.addInto(key, value, containerInstance, unmarshalRecord.getSession());
        }
    }

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

    @Override
    public void setContainerInstance(Object object, Object container) {
        xmlAnyAttributeMapping.setAttributeValueInObject(object, container);
    }

    @Override
    public CoreMappedKeyMapContainerPolicy getContainerPolicy() {
        return (CoreMappedKeyMapContainerPolicy) xmlAnyAttributeMapping.getContainerPolicy();
    }

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

    @Override
    public boolean marshalSingleValue(XPathFragment xPathFragment, MarshalRecord marshalRecord, Object object, Object value, CoreAbstractSession session, NamespaceResolver namespaceResolver, MarshalContext marshalContext) {
        return true;
    }

    @Override
    public AnyAttributeMapping getMapping() {
        return xmlAnyAttributeMapping;
    }

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

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

}
