/*
 * 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.sdo.helper;

import commonj.sdo.DataObject;
import commonj.sdo.Property;
import commonj.sdo.Sequence;
import commonj.sdo.helper.HelperContext;
import commonj.sdo.helper.TypeHelper;

import java.util.ArrayList;
import java.util.List;
import org.eclipse.persistence.sdo.SDOChangeSummary;
import org.eclipse.persistence.sdo.SDOConstants;
import org.eclipse.persistence.sdo.SDODataObject;
import org.eclipse.persistence.sdo.SDOProperty;
import org.eclipse.persistence.sdo.SDOSequence;
import org.eclipse.persistence.exceptions.SDOException;
import org.eclipse.persistence.internal.oxm.XMLConversionManager;
import org.eclipse.persistence.oxm.XMLRoot;
import org.eclipse.persistence.oxm.XMLUnmarshaller;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

/**
 * <p><b>Purpose</b>: Implementation of XMLUnmarshalListener used when unmarshalling XML to XMLDocuments
 * <p><b>Responsibilities</b>:<ul>
 * <li> When creating a DataObject we need to call setType and setHelperContext with the appropriate values
 * <li> When we are finished Unmarshalling the root object we need to set up the ChangeSummary objects.
 * ChangeSummaries have xpaths to other parts of the documents so the rest of the objects need to be built before we process the ChangeSummaries
 * </ul>
 */
public class SDOUnmarshalListener extends SDOCSUnmarshalListener {
    private List<SDOChangeSummary> changeSummaries;

    public SDOUnmarshalListener(HelperContext aContext) {
        super(aContext);
    }

    @Override
    public void beforeUnmarshal(Object target, Object parent) {
        //Setting the helperContext and type on the DataObject or ChangeSummary
        super.beforeUnmarshal(target, parent);
    }

    /**
     * @param target assumed to be non-null
     * @param parent may be null, indicating target is root object
     */
    @Override
    public void afterUnmarshal(Object target, Object parent) {
        SDODataObject targetDataObject;
        // assume target is DataObject or ChangeSummary
        try {
            targetDataObject = (SDODataObject)target;
        } catch (ClassCastException ccex) {
            // each time we hit a ChangeSummary store it to process later and set its root
            // object - this is because we can't fully process the cs's because they have
            // references that can't be resolved until the full tree is built
            SDOChangeSummary sdoChangeSummary = (SDOChangeSummary) target;
            sdoChangeSummary.setRootDataObject((DataObject)parent);
            getChangeSummaries().add(sdoChangeSummary);
            return;
        }

        // if getType is sequenced, then update values to settings map
        if (targetDataObject.getType().isSequenced()) {
            targetDataObject.getSequence().afterUnmarshal();
        }

        // if parent is null we are back to the root object
        // the last object that will hit the afterUnmarshal method
        if (parent == null && null != changeSummaries) {
            XMLUnmarshaller unmarshaller = null;
            for (int i = 0, changeSummariesSize=changeSummaries.size(); i < changeSummariesSize; i++) {
                SDOChangeSummary nextCS = changeSummaries.get(i);
                // Set logging to true until finished building modified list.
                boolean loggingValue = nextCS.isLoggingMapping();
                nextCS.setLogging(true);

                // CREATES
                // For each xpath in the create attribute convert it to an sdo path and execute it against the root
                // dataobject to get the dataobject being pointed to and set that dataobject to be created
                List xpaths = nextCS.getCreatedXPaths();
                for (int j = 0, xpathsSize = xpaths.size(); j < xpathsSize; j++) {
                    String nextXPath = (String)xpaths.get(j);
                    String sdoPath = convertXPathToSDOPath(nextXPath);
                    SDODataObject nextCreatedDO = targetDataObject.getDataObject(sdoPath);

                    if(nextCreatedDO == null) {
                        int nextSlash = sdoPath.indexOf('/');
                        if(nextSlash != -1) {
                            sdoPath = sdoPath.substring(nextSlash + 1);
                        } else {
                            sdoPath = "/";
                        }
                        nextCreatedDO = targetDataObject.getDataObject(sdoPath);
                    }

                    if (nextCreatedDO != null) {
                        nextCreatedDO._setCreated(true);
                        nextCS.getOldContainers().remove(nextCreatedDO);
                    } else {
                        throw SDOException.errorProcessingXPath(nextXPath);
                    }
                }
                //clear the createxpaths list that was read in from XML
                nextCS.setCreatedXPaths(null);

                //MODIFIED
                List modifiedDoms = nextCS.getModifiedDoms();
                for (int j = 0, modifiedDomsSize=modifiedDoms.size(); j < modifiedDomsSize; j++) {
                    Element nextNode = (Element)modifiedDoms.get(j);
                    String refValue = nextNode.getAttributeNS(SDOConstants.SDO_URL, SDOConstants.CHANGESUMMARY_REF);
                    if ((refValue == null) || (refValue.length() == 0)) {
                        throw SDOException.missingRefAttribute();
                    }
                    //nextModifiedDO is the real modified current data object
                    String sdoPath = convertXPathToSDOPath(refValue);
                    SDODataObject nextModifiedDO = targetDataObject.getDataObject(sdoPath);
                    //if it failed, try peeling off the first fragment (may be the root
                    if(nextModifiedDO == null) {
                        int nextSlash = sdoPath.indexOf('/');
                        if(nextSlash != -1) {
                            sdoPath = sdoPath.substring(nextSlash + 1);
                        } else {
                            sdoPath = "/";
                        }
                        nextModifiedDO = targetDataObject.getDataObject(sdoPath);
                    }
                    String unsetValue = nextNode.getAttributeNS(SDOConstants.SDO_URL, SDOConstants.CHANGESUMMARY_UNSET);
                    List unsetValueList = new ArrayList();
                    if ((unsetValue != null) && (unsetValue.length() > 0)) {
                        XMLConversionManager xmlConversionManager = ((SDOXMLHelper) aHelperContext.getXMLHelper()).getXmlConversionManager();
                        unsetValueList = xmlConversionManager.convertObject(unsetValue, List.class);
                    }
                    if (nextModifiedDO != null) {
                        nextModifiedDO._setModified(true);
                        SDOCSUnmarshalListener listener = new SDOCSUnmarshalListener(nextModifiedDO.getType().getHelperContext(), true);
                        if(null == unmarshaller) {
                            unmarshaller = ((SDOXMLHelper)aHelperContext.getXMLHelper()).getXmlContext().createUnmarshaller();
                        }
                        unmarshaller.setUnmarshalListener(listener);
                        unmarshaller.getProperties().put("sdoHelperContext", aHelperContext);
                        unmarshaller.setUnmappedContentHandlerClass(SDOUnmappedContentHandler.class);
                        Object unmarshalledNode = unmarshaller.unmarshal(nextNode, nextModifiedDO.getType().getXmlDescriptor().getJavaClass());
                        //unmarshalledDO is the modified dataobject from the changesummary xml
                        SDODataObject unmarshalledDO = null;
                        // Assumption: unmarshalledNode should always be either an instance of XMLRoot or DataObject
                        if (unmarshalledNode instanceof XMLRoot) {
                            unmarshalledDO = (SDODataObject)((XMLRoot)unmarshalledNode).getObject();
                        } else if (unmarshalledNode instanceof DataObject) {
                            unmarshalledDO = (SDODataObject)unmarshalledNode;
                        }
                        List modifiedProps = new ArrayList();
                        Node n = nextNode.getFirstChild();
                        TypeHelper typeHelper = aHelperContext.getTypeHelper();
                        while(n != null) {
                            if (n.getNodeType() == Node.ELEMENT_NODE) {
                                String propName = n.getLocalName();
                                Property nextProp = unmarshalledDO.getInstanceProperty(propName);
                                if (nextProp == null) {
                                    nextProp = typeHelper.getOpenContentProperty(n.getNamespaceURI(), propName);
                                }
                                if (!modifiedProps.contains(nextProp)) {
                                    modifiedProps.add(nextProp);
                                }
                            }
                            n = n.getNextSibling();
                        }
                        //instead of iterating over all props can we just check elements in cs and get appropriate properties from DO
                        for (int k = 0, modifiedPropsSize = modifiedProps.size(); k < modifiedPropsSize; k++) {
                            SDOProperty nextProp = (SDOProperty)modifiedProps.get(k);
                            if (!nextProp.getType().isDataType()) {
                                if (nextProp.isMany()) {
                                    //original value is the list from the changesummary xml
                                    List originalValue = unmarshalledDO.getList(nextProp);
                                    List newList = new ArrayList();
                                    List toDelete = new ArrayList();
                                    List indexsToDelete = new ArrayList();
                                    for (int l = 0, originalValueSize = originalValue.size(); l < originalValueSize; l++) {
                                        SDODataObject nextInList = (SDODataObject)originalValue.get(l);
                                        String sdoRef = nextInList._getSdoRef();
                                        if (sdoRef != null) {
                                            //if sdoRef is not null then object is modified
                                            String sdoRefPath = convertXPathToSDOPath(sdoRef);
                                            int nextSlash = sdoRefPath.indexOf('/');
                                            if(nextSlash != -1) {
                                                sdoRefPath = sdoRefPath.substring(nextSlash + 1);
                                            } else {
                                                sdoRefPath = "/";
                                            }
                                            newList.add(targetDataObject.getDataObject(sdoRefPath));
                                        } else {
                                            //if sdo ref is null there is a deleted object
                                            toDelete.add(nextInList);
                                            indexsToDelete.add(l);
                                            newList.add(nextInList);
                                        }
                                    }
                                    //lw is the list from the real current data object
                                    ListWrapper lw = ((ListWrapper)nextModifiedDO.getList(nextProp));
                                    int indexsToDeleteSize = indexsToDelete.size();
                                    if (indexsToDeleteSize > 0) {
                                        //after this loop, lw will have the entire list when logging was turned on
                                        nextCS.pauseLogging();
                                        for (int m = 0; m < indexsToDeleteSize; m++) {
                                            int toDeleteIndex = (Integer) indexsToDelete.get(m);
                                            SDODataObject nextToDelete = (SDODataObject)toDelete.get(m);
                                            lw.add(toDeleteIndex, nextToDelete);
                                        }
                                        nextCS.setPropertyInternal(nextModifiedDO, nextProp, lw);
                                        SDOSequence nextSeq = ((SDOSequence)nextCS.getOriginalSequences().get(nextModifiedDO));
                                        nextCS.resumeLogging();
                                        nextModifiedDO._setModified(true);
                                        for (int m = indexsToDeleteSize - 1; m >= 0; m--) {
                                            int toDeleteIndex = (Integer) indexsToDelete.get(m);
                                            SDODataObject nextToDelete = (SDODataObject)toDelete.get(m);
                                            if(nextSeq != null){
                                               nextSeq.addSettingWithoutModifyingDataObject(-1, nextProp, nextToDelete);
                                            }
                                            nextToDelete.resetChanges();

                                            lw.remove(toDeleteIndex);
                                        }
                                    }
                                    nextCS.getOriginalElements().put(lw, newList);
                                } else {
                                    SDODataObject value = unmarshalledDO.getDataObject(nextProp);
                                    if (value != null) {
                                        String sdoRef = value._getSdoRef();
                                        if (sdoRef != null) {
                                            //modified
                                            nextModifiedDO._setModified(true);
                                        } else {
                                            //deleted
                                            value._setChangeSummary(nextCS);
                                            nextModifiedDO._setModified(true);
                                            nextCS.pauseLogging();
                                            boolean wasSet = nextModifiedDO.isSet(nextProp);

                                            Object existingValue = nextModifiedDO.get(nextProp);
                                            // grab index of nextProp's Setting for use during setting below
                                            Sequence nextModifiedDOSequence = nextModifiedDO.getSequence();
                                            int settingIdx = -1;
                                            if (nextModifiedDOSequence != null) {
                                                settingIdx = ((SDOSequence)nextModifiedDOSequence).getIndexForProperty(nextProp);
                                            }
                                            value._setContainmentPropertyName(null);
                                            value._setContainer(null);
                                            nextModifiedDO.set(nextProp, value);
                                            nextCS.setPropertyInternal(nextModifiedDO, nextProp, value);
                                            SDOSequence nextSeq = ((SDOSequence)nextCS.getOriginalSequences().get(nextModifiedDO));
                                            if(nextSeq != null){
                                              nextSeq.addSettingWithoutModifyingDataObject(-1, nextProp, value);
                                            }

                                            nextCS.resumeLogging();
                                            nextModifiedDO._setModified(true);

                                            value.resetChanges();
                                            value.delete();
                                            if (wasSet) {
                                                // need to add at the right pos in the list, not at the end
                                                nextModifiedDO.set(nextProp, existingValue, false);
                                                if (settingIdx != -1) {
                                                    nextModifiedDO.getSequence().addSettingWithoutModifyingDataObject(settingIdx, nextProp, existingValue);
                                                }
                                            } else {
                                                nextModifiedDO.unset(nextProp);
                                            }
                                        }
                                    } else {
                                        nextModifiedDO._setModified(true);
                                        nextCS.setPropertyInternal(nextModifiedDO, nextProp, null);
                                    }
                                }
                            } else {
                                nextModifiedDO._setModified(true);
                                Object value = unmarshalledDO.get(nextProp);
                                //lw is the list from the real current data object

                                if(nextProp.isMany()){

                                  Property theProp = nextModifiedDO.getInstanceProperty(nextProp.getName());
                                  if(theProp == null){
                                    Property newProp = nextModifiedDO.defineOpenContentProperty(nextProp.getName(), new ArrayList(), nextProp.getType());
                                    nextModifiedDO.set(newProp, new ArrayList());
                                    theProp = newProp;
                                  }
                                  List lw = nextModifiedDO.getList(theProp.getName());
                                  nextCS.setPropertyInternal(nextModifiedDO, theProp, lw);
                                  nextCS.getOriginalElements().put(lw, ((ListWrapper)value).getCurrentElements());
                                }else{
                                  nextCS.setPropertyInternal(nextModifiedDO, nextProp, value);
                                }
                            }
                        }

                        for (int k = 0, unsetValueListSize = unsetValueList.size(); k < unsetValueListSize; k++) {
                            SDOProperty nextProp = unmarshalledDO.getInstanceProperty((String)unsetValueList.get(k));
                            if (nextProp != null) {
                                Object oldValue = null;
                                if (nextProp.getType().isDataType() || nextProp.isMany()) {
                                    //to get default
                                    oldValue = unmarshalledDO.get(nextProp);
                                }
                                nextModifiedDO._setModified(true);
                                nextCS.setPropertyInternal(nextModifiedDO, nextProp, oldValue);
                                nextCS.unsetPropertyInternal(nextModifiedDO, nextProp);
                            } else {
                                nextProp = nextModifiedDO.getInstanceProperty((String)unsetValueList.get(k));
                                nextModifiedDO._setModified(true);
                                nextCS.setPropertyInternal(nextModifiedDO, nextProp, null);
                                nextCS.unsetPropertyInternal(nextModifiedDO, nextProp);
                            }
                        }
                    } else {
                        throw SDOException.errorProcessingXPath(refValue);
                    }
                }

                //clear modified doms list
                nextCS.setModifiedDoms(null);

                //clear deleted xpaths list
                nextCS.setDeletedXPaths(null);

                List created = nextCS.getCreated();
                for(int j=0, createdSize = created.size(); j<createdSize; j++) {
                    SDODataObject next = (SDODataObject)created.get(j);
                    Property containmentProperty = next.getContainmentProperty();
                    if(containmentProperty != null && containmentProperty.isMany()) {
                        SDODataObject container = next.getContainer();
                        ListWrapper list = (ListWrapper)container.get(containmentProperty);
                        if(!(nextCS.getOriginalElements().containsKey(list))) {
                            //if there was an object created as part of a list, and that list is not
                            //already in the original elements map. Add an empty list to the map.
                            nextCS.getOriginalElements().put(list, new ArrayList());
                        }
                    }
                }

                nextCS.setLogging(loggingValue);
            }
            // reset changeSummary list - we are done with it
            changeSummaries = null;
        }
    }

    private List<SDOChangeSummary> getChangeSummaries() {
        if(null == changeSummaries) {
            changeSummaries = new ArrayList<SDOChangeSummary>();
        }
        return changeSummaries;
    }

    private String convertXPathToSDOPath(String xpath) {
        if ((xpath == null) || (xpath.length() < SDOConstants.SDO_CHANGESUMMARY_REF_PATH_PREFIX_LENGTH) ||//
                !xpath.startsWith(SDOConstants.SDO_CHANGESUMMARY_REF_PATH_PREFIX)) {
            throw SDOException.errorProcessingXPath(xpath);
        }
        if (xpath.equals("#/")) {
            return "/";
        } else if (xpath.startsWith("#/")) {
            return xpath.substring(2, xpath.length());
        } else {
            // remove the sdo ref prefix only "#", leave the root path identifier "/"
            return xpath.substring(1, xpath.length());
        }
    }

}
