/*
 * 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;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import commonj.sdo.Property;
import commonj.sdo.Sequence;
import javax.xml.namespace.QName;
import org.eclipse.persistence.sdo.SDODataObject;
import org.eclipse.persistence.sdo.helper.ListWrapper;
import org.eclipse.persistence.sdo.helper.SDOTypeHelper;
import org.eclipse.persistence.core.mappings.CoreMapping;
import org.eclipse.persistence.exceptions.SDOException;
import org.eclipse.persistence.internal.oxm.XPathFragment;
import org.eclipse.persistence.oxm.NamespaceResolver;
import org.eclipse.persistence.oxm.XMLConstants;
import org.eclipse.persistence.oxm.XMLDescriptor;
import org.eclipse.persistence.oxm.XMLField;
import org.eclipse.persistence.oxm.XMLRoot;
import org.eclipse.persistence.oxm.mappings.XMLCollectionReferenceMapping;
import org.eclipse.persistence.oxm.mappings.XMLObjectReferenceMapping;
import org.eclipse.persistence.oxm.sequenced.Setting;
import org.eclipse.persistence.mappings.DatabaseMapping;

public class SDOSequence implements Sequence {
    private static final String TEXT_XPATH = "text()";
    private SDODataObject dataObject;
    private List<Setting> settings;
    private Map<Key, Setting> valuesToSettings;

    public SDOSequence(SDODataObject dataObject) {
        // catch a null dataObject early before we get NPE on any update
        // operations during add/remove
        if (null == dataObject) {
            throw SDOException.sequenceDataObjectInstanceFieldIsNull();
        }
        this.dataObject = dataObject;
        this.settings = new ArrayList<Setting>();
        this.valuesToSettings = new HashMap<Key, Setting>();
    }

    public SDODataObject getDataObject() {
        return dataObject;
    }

    public List<Setting> getSettings() {
        return settings;
    }

    protected Map<Key, Setting> getValuesToSettings() {
        return valuesToSettings;
    }

    @Override
    public void add(int index, int propertyIndex, Object value) {
        Property property = dataObject.getInstanceProperty(propertyIndex);
        add(index, property, value);
    }

    @Override
    public boolean add(int propertyIndex, Object value) {
        Property property = dataObject.getInstanceProperty(propertyIndex);
        return add(property, value);
    }

    @Override
    public void add(int index, Property property, Object value) {
        if (!isAllowedInSequence(property)) {
            return;
        }

        if (property != null && property.isOpenContent() && dataObject.getType().isOpen()) {
            dataObject.addOpenContentProperty(property);
        }
        // Update the data object
        if (property.isMany()) {
            ListWrapper listWrapper = (ListWrapper) dataObject.getList(property);
            if (value instanceof List) {
                // iterate list
                for (Iterator i = ((List) value).iterator(); i.hasNext();) {
                    // add a setting to the end of the sequence
                    Object aValue = i.next();
                    Setting setting = convertToSetting(property, aValue);
                    valuesToSettings.put(new Key(property, aValue), setting);
                    settings.add(index++, setting);
                    // no need to check updateContainment flag -
                    // ListWrapper.add() will not pass an entire List here
                    listWrapper.add(aValue, false);
                }
            } else {
                // set individual list item
                // add a setting to the end of the sequence
                Setting setting = convertToSetting(property, value);
                valuesToSettings.put(new Key(property, value), setting);
                settings.add(index, setting);
                int listIdx = getIndexInList(property, value);
                if (listIdx != -1) {
                    listWrapper.add(listIdx, value, false);
                } else {
                    listWrapper.add(value, false);
                }
            }
        } else {
            dataObject.setPropertyInternal((SDOProperty) property, value, false);
            // Update the settings
            Setting setting = convertToSetting(property, value);
            valuesToSettings.put(new Key(property, value), setting);
            settings.add(index, setting);
        }
    }

    private boolean isAllowedInSequence(Property property) {
        // Disallow the addition of a null Property
        if (null == property) {
            return false;
        }
        // Disallow the addition of a read only Property
        if (property.isReadOnly()) {
            return false;
        }
        // Disallow the addition of a Properties representing an XML attribute
        if (dataObject.getType().getHelperContext().getXSDHelper().isAttribute(property)) {
            throw SDOException.sequenceAttributePropertyNotSupported(property.getName());
        }
        // Disallow an open Property on a closed Type
        if (property.isOpenContent() && !dataObject.getType().isOpen()) {
            return false;
        }
        // Disallow the addition of an isMany==false Property that is already
        // set
        if (property.isMany()) {
            return true;
        }
        if (dataObject.isSet(property)) {
            throw SDOException.sequenceDuplicateSettingNotSupportedForComplexSingleObject(getIndexForProperty(property), property.getName());
        }
        return true;
    }

    @Override
    public void add(int index, String propertyName, Object value) {
        Property property = dataObject.getInstanceProperty(propertyName);
        if (property == null) {
            // Property with given name does not exist - create an open content
            // property
            property = dataObject.defineOpenContentProperty(propertyName, value);
            ((SDOProperty) property).setMany(true);
        }
        add(index, property, value);
    }

    @Override
    public void add(int index, String text) {
        addText(index, text);
    }

    @Override
    public boolean add(Property property, Object value) {
        if (addSettingWithoutModifyingDataObject(property, value)) {
            if (property != null && property.isOpenContent() && dataObject.getType().isOpen()) {
                dataObject.addOpenContentProperty(property);
            }
            if (value instanceof XMLRoot) {
                value = ((XMLRoot) value).getObject();
            }
            if (property.isMany()) {
                ListWrapper listWrapper = (ListWrapper) dataObject.getList(property);
                listWrapper.add(value, false);
            } else {
                dataObject.setPropertyInternal((SDOProperty) property, value, false);
            }
            return true;
        }
        return false;
    }

    @Override
    public boolean add(String propertyName, Object value) {
        Property property = dataObject.getInstanceProperty(propertyName);
        if (property == null) {
            // Property with given name does not exist - create an open content
            // property
            property = dataObject.defineOpenContentProperty(propertyName, value);
            ((SDOProperty) property).setMany(true);
        }
        return add(property, value);
    }

    @Override
    public void add(String text) {
        addText(text);
    }

    @Override
    public void addText(int index, String text) {
        // Trigger store of original sequence
        dataObject._setModified(true);
        Setting textSetting = new Setting(null, TEXT_XPATH);
        textSetting.setObject(dataObject);
        textSetting.setValue(text, false);
        settings.add(index, textSetting);
    }

    @Override
    public void addText(String text) {
        // Trigger store of original sequence
        dataObject._setModified(true);
        Setting textSetting = new Setting(null, TEXT_XPATH);
        textSetting.setObject(dataObject);
        textSetting.setValue(text, false);
        settings.add(textSetting);
    }

    @Override
    public SDOProperty getProperty(int index) {
        try {
            return getProperty(settings.get(index));
        } catch (IndexOutOfBoundsException iobex) {
            throw SDOException.invalidIndex(iobex, index);
        }
    }

    public SDOProperty getProperty(Setting setting) {
        CoreMapping mapping = setting.getMapping();
        if (null == mapping) {
            List<Setting> children = setting.getChildren();
            if (null != children && children.size() > 0) {
                return getProperty(children.get(0));
            }
        } else {
            SDOProperty property = null;
            if (null == setting.getName()) {
                Object value = setting.getValue();
                if (value instanceof SDODataObject) {
                    SDOProperty containmentProp = ((SDODataObject) value).getContainmentProperty();
                    if (containmentProp != null) {
                        property = dataObject.getInstanceProperty(containmentProp.getName());
                    }
                    if (property == null) {
                        XMLDescriptor desc = ((SDODataObject) value).getType().getXmlDescriptor();

                        String qualifiedName = desc.getDefaultRootElement();
                        int index = qualifiedName.indexOf(':');
                        String localName = null;
                        if (index > -1) {
                            localName = qualifiedName.substring(index + 1, qualifiedName.length());
                        } else {
                            localName = qualifiedName;
                        }
                        property = dataObject.getInstanceProperty(localName);
                    }
                } else {
                    XMLRoot xmlRoot = (XMLRoot) value;
                    if (null != xmlRoot) {
                        property = dataObject.getInstanceProperty(xmlRoot.getLocalName());
                    }
                }
            } else {
                property = dataObject.getInstanceProperty(mapping.getAttributeName());
            }
            return property;
        }
        return null;
    }

    @Override
    public Object getValue(int index) {
        try {
            return getValue(settings.get(index));
        } catch (IndexOutOfBoundsException iobex) {
            throw SDOException.invalidIndex(iobex, index);
        }
    }

    private Object getValue(Setting setting) {
        if (null != setting.getMapping() || (setting.getName() != null && setting.getName().equals(TEXT_XPATH))) {
            Object value = setting.getValue();
            if (value instanceof XMLRoot) {
                value = ((XMLRoot) value).getObject();
            }
            return value;
        }

        if (null == setting.getChildren() || setting.getChildren().size() == 0) {
            return null;
        }
        return getValue(setting.getChildren().get(0));
    }

    @Override
    public void move(int toIndex, int fromIndex) {
        if (toIndex == fromIndex) {
            return;
        }
        // verify indexes are in range
        int size = settings.size();
        if (fromIndex < 0 || fromIndex >= size) {
            throw SDOException.invalidIndex(null, fromIndex);
        }
        if (toIndex < 0 || toIndex >= size) {
            throw SDOException.invalidIndex(null, toIndex);
        }
        // trigger deep copy of sequence (if applicable)
        dataObject._setModified(true);

        Setting setting = settings.remove(fromIndex);
        settings.add(toIndex, setting);

        SDOProperty prop = getProperty(setting);
        if (prop != null && prop.isMany()) {
            ListWrapper lw = (ListWrapper) dataObject.getList(prop);
            Object value = getValue(setting);
            int currentIndexInLw = lw.indexOf(value);
            lw.remove(currentIndexInLw, false);
            int newIndexInLw = getIndexInList(prop, value);
            lw.add(newIndexInLw, value, false);
        }
    }

    @Override
    public void remove(int index) {
        Setting setting = settings.get(index);
        remove(setting);
        settings.remove(setting);
    }

    private void remove(Setting setting) {
        CoreMapping mapping = setting.getMapping();
        if (null != mapping) {
            Property property = null;
            if (null == setting.getName()) {
                XMLRoot xmlRoot = (XMLRoot) setting.getValue();
                if (null != xmlRoot) {
                    property = dataObject.getInstanceProperty(xmlRoot.getLocalName());
                    valuesToSettings.remove(new Key(property, setting.getValue()));
                }
            } else {
                property = dataObject.getInstanceProperty(mapping.getAttributeName());
                valuesToSettings.remove(new Key(property, setting.getValue()));
            }
            if (property.isMany()) {
                ListWrapper listWrapper = (ListWrapper) dataObject.getList(property);
                listWrapper.remove(setting.getValue(), false, false);
            } else {
                dataObject.unset(property, false, false);
            }
        } else if (setting.getName() != null && setting.getName().equals(TEXT_XPATH)) {
            // Handle "text()"
            dataObject._setModified(true);
        }
        List<Setting> children = setting.getChildren();
        if (null != children) {
            int childrenSize = children.size();
            for (int x = 0; x < childrenSize; x++) {
                remove(children.get(x));
            }
        }
    }

    /**
     * INTERNAL:
     *
     * @param setting
     */
    public void addValueToSettings(Setting setting) {
        valuesToSettings.put(new Key(getProperty(setting), getValue(setting)), setting);
    }

    /**
     * INTERNAL:
     *
     * @param setting
     */
    public void removeValueToSettings(Setting setting) {
        valuesToSettings.remove(new Key(getProperty(setting), getValue(setting)));
    }

    @Override
    public Object setValue(int index, Object value) {
        return setValue(settings.get(index), value);
    }

    private Object setValue(Setting setting, Object value) {
        if (null == setting.getMapping()) {
            if (setting.getName() != null && setting.getName().equals(TEXT_XPATH)) {
                dataObject._setModified(true);
                Object oldValue = setting.getValue();
                setting.setValue(value, false);
                return oldValue;
            }
            List<Setting> children = setting.getChildren();
            if (null != children && children.size() > 0) {
                return setValue(children.get(0), value);
            }
            return null;
        }

        SDOProperty property = getProperty(setting);
        Object oldValue = setting.getValue();

        if (property.isMany()) {
            ListWrapper listValue = (ListWrapper) dataObject.getList(property);
            int valueIndex = listValue.indexOf(oldValue);
            listValue.remove(oldValue, property.isContainment(), false);
            listValue.add(valueIndex, value, false);
            setting.setValue(value, false);
        } else {
            if (dataObject.isSet(property)) {
                updateSettingWithoutModifyingDataObject(property, dataObject.get(property), value);
                setting.setValue(value);
            } else {
                addSettingWithoutModifyingDataObject(property, value);
            }
            dataObject.setPropertyInternal(property, value, false);
        }
        return oldValue;
    }

    @Override
    public int size() {
        return settings.size();
    }

    private Setting convertToSetting(Property property, Object value) {
        SDOProperty sdoProperty = (SDOProperty) property;
        DatabaseMapping mapping = sdoProperty.getXmlMapping();
        Setting setting = new Setting();
        SDOType sdoType = dataObject.getType();
        XMLDescriptor xmlDescriptor = sdoType.getXmlDescriptor();
        if (null == mapping) {
            setting.setObject(dataObject);

            mapping = xmlDescriptor.getMappingForAttributeName("openContentProperties");
            setting.setMapping(mapping);
            XMLRoot xmlRoot = new XMLRoot();
            if (value instanceof XMLRoot) {
                xmlRoot.setLocalName(((XMLRoot) value).getLocalName());
                xmlRoot.setNamespaceURI(((XMLRoot) value).getNamespaceURI());
                xmlRoot.setObject(((XMLRoot) value).getObject());
            } else {
                xmlRoot.setLocalName(sdoProperty.getName());
                xmlRoot.setNamespaceURI(sdoProperty.getUri());
                xmlRoot.setObject(value);
                // do not set schema type for global properties
                SDOTypeHelper hlpr = (SDOTypeHelper) dataObject.getType().getHelperContext().getTypeHelper();
                if (hlpr.getOpenContentProperty(sdoProperty.getUri(), sdoProperty.getName()) == null) {
                    QName schemaTypeQName = hlpr.getXSDTypeFromSDOType(property.getType());
                    if (schemaTypeQName != null && schemaTypeQName != XMLConstants.STRING_QNAME) {
                        xmlRoot.setSchemaType(schemaTypeQName);
                    }
                }
            }
            setting.setValue(xmlRoot, false);
        } else {
            setting = convertToSetting(mapping, value);
        }
        return setting;
    }

    private Setting convertToSetting(DatabaseMapping mapping, Object value) {
        XMLDescriptor xmlDescriptor = (XMLDescriptor) mapping.getDescriptor();
        NamespaceResolver nsResolver = xmlDescriptor.getNamespaceResolver();
        Setting rootSetting = new Setting();
        XMLField xmlField = (XMLField) mapping.getField();
        if (xmlField == null) {
            if (mapping instanceof XMLObjectReferenceMapping) {
                xmlField = (XMLField) ((XMLObjectReferenceMapping) mapping).getFields().get(0);
            } else if (mapping instanceof XMLCollectionReferenceMapping) {
                xmlField = (XMLField) ((XMLCollectionReferenceMapping) mapping).getFields().get(0);
            }
        }
        Setting setting = rootSetting;
        if (xmlField != null) {
            XPathFragment xPathFragment = xmlField.getXPathFragment();
            rootSetting = convertToSetting(xPathFragment, nsResolver);
            setting = rootSetting;

            while (xPathFragment.getNextFragment() != null) {
                xPathFragment = xPathFragment.getNextFragment();
                Setting childSetting = convertToSetting(xPathFragment, nsResolver);
                setting.addChild(childSetting);
                setting = childSetting;
            }
        }
        setting.setObject(dataObject);
        setting.setMapping(mapping);
        setting.setValue(value, false);
        return rootSetting;
    }

    private Setting convertToSetting(XPathFragment xPathFragment, NamespaceResolver nsResolver) {
        Setting setting = new Setting();
        String name = xPathFragment.getLocalName();
        if (null == name) {
            name = xPathFragment.getShortName();
        }
        setting.setName(name);
        if (xPathFragment.hasNamespace()) {
            setting.setNamespaceURI(nsResolver.resolveNamespacePrefix(xPathFragment.getPrefix()));
        }
        return setting;
    }

    public SDOSequence copy() {
        SDOSequence copy = new SDOSequence(dataObject);
        for (int index = 0, size = settings.size(); index < size; index++) {
            Setting settingCopy = settings.get(index).copy();
            copy.getSettings().add(settingCopy);
            copy.getValuesToSettings().put(new Key(getProperty(settingCopy), getValue(settingCopy)), settingCopy);
        }
        return copy;
    }

    /**
     * INTERNAL: Add a setting to the list at the specified index. The owning
     * DataObject will not be made aware of this addition.
     *
     * @param index
     *            the index at which to add the new Setting in the Settings list
     * @param property
     * @param value
     * @return true if the a Setting was successfully added to the list,
     *         otherwise false
     */
    public boolean addSettingWithoutModifyingDataObject(int index, Property property, Object value) {
        Setting setting = convertToSetting(property, value);
        valuesToSettings.put(new Key(property, value), setting);
        if (index >= 0) {
            settings.add(index, setting);
        } else {
            settings.add(setting);
        }
        return true;
    }

    /**
     * INTERNAL:
     */
    public boolean addSettingWithoutModifyingDataObject(Property property, Object value) {
        return addSettingWithoutModifyingDataObject(property, value, true);
    }

    /**
     * INTERNAL:
     */
    public boolean addSettingWithoutModifyingDataObject(Property property, Object value, boolean checkAllowed) {
        if (checkAllowed && !isAllowedInSequence(property)) {
            return false;
        }
        Setting setting = convertToSetting(property, value);
        valuesToSettings.put(new Key(property, value), setting);
        settings.add(setting);
        return true;
    }

    /**
     * INTERNAL:
     */
    public void updateSettingWithoutModifyingDataObject(Property property, Object oldValue, Object newValue) {
        Key key = new Key(property, oldValue);
        Setting setting = valuesToSettings.get(key);
        valuesToSettings.remove(key);
        valuesToSettings.put(new Key(property, newValue), setting);
        // set the new value on the appropriate setting
        while (setting.getMapping() == null) {
            List<Setting> children = setting.getChildren();
            if (children != null && children.size() > 0) {
                setting = children.get(0);
            }
        }
        setting.setValue(newValue, false);
    }

    /**
     * INTERNAL:
     */
    public void removeSettingWithoutModifyingDataObject(Property property, Object value) {
        settings.remove(valuesToSettings.remove(new Key(property, value)));
    }

    /**
     * INTERNAL:
     */
    public void removeSettingWithoutModifyingDataObject(Property property) {
        List<Key> keys = new ArrayList<Key>(valuesToSettings.keySet());
        int size = valuesToSettings.keySet().size();
        for (int i = size - 1; i >= 0; i--) {
            Key nextKey = keys.get(i);
            if (nextKey.getProperty() == property) {
                settings.remove(valuesToSettings.remove(nextKey));
            }
        }
    }

    /**
     * INTERNAL: Convenience method that returns the index of the Setting
     * associated with a given property in the Settings list
     *
     * @param property
     * @return index of the Setting associated with a given property in the
     *         Settings list or -1 if not found
     */
    public int getIndexForProperty(Property property) {
        List<Key> keys = new ArrayList<Key>(valuesToSettings.keySet());
        for (int i = 0; i < keys.size(); i++) {
            Key nextKey = keys.get(i);
            if (nextKey.getProperty() == property) {
                return settings.indexOf(valuesToSettings.get(nextKey));
            }
        }
        return -1;
    }

    /**
     * INTERNAL: Convenience method that, given a many property and a value,
     * returns the associated Setting's index in the Settings list. For example,
     * if a sequence contains many properties "letters" and "numbers", such as
     * [A, 1, C, 2, B, D], and we are looking for the letter B, this method will
     * return 2. Although B is at index 4 of the Settings list, it is at index 2
     * of the list of "letters" - [A, C, B, D].
     *
     * @param property
     * @return index of the value's Setting in the list relative to a given
     *         property or -1 if not found.
     */
    private int getIndexInList(Property manyProp, Object value) {
        int returnIndex = -1;
        for (int i = 0; i < settings.size(); i++) {
            Setting nextSetting = settings.get(i);
            SDOProperty prop = getProperty(nextSetting);
            if (prop.equals(manyProp)) {
                returnIndex++;
                if (value.equals(getValue(nextSetting))) {
                    return returnIndex;
                }
            }
        }
        return returnIndex;
    }

    /**
     * INTERNAL: Get the root Setting for a given Setting.
     *
     * @param setting
     * @return the root Setting or this Setting if it is a root
     */
    public static Setting getRootSetting(Setting setting) {
        Setting rootSetting = setting;
        while (rootSetting.getParent() != null) {
            rootSetting = rootSetting.getParent();
        }
        return rootSetting;
    }

    /**
     * INTERNAL: Ensure that each Setting in the settings list is also present
     * in the valuesToSettings map
     */
    public void afterUnmarshal() {
        for (Iterator<Setting> setIt = getSettings().iterator(); setIt.hasNext();) {
            addValueToSettings(setIt.next());
        }
    }

    private static class Key {
        private Property property;
        private Object value;

        public Key(Property property, Object value) {
            this.property = property;
            this.value = value;
        }

        protected Property getProperty() {
            return this.property;
        }

        protected Object getValue() {
            return this.value;
        }

        @Override
        public boolean equals(Object object) {
            try {
                Key key = (Key) object;
                return property == key.getProperty() && value == key.getValue();
            } catch (ClassCastException e) {
                return false;
            }

        }

        @Override
        public int hashCode() {
            if (value == null) {
                return 0;
            }
            return value.hashCode();
        }
    }
}
