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

import commonj.sdo.DataObject;
import commonj.sdo.Property;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * <p><b>Purpose</b>:Default implementation of the ValueStore interface.
 * <p><b>Responsibilities</b>:<ul>
 * <li> Provide get/set/isset/unset access to the values of a DataObject
 * <li> Store the values of the declared and open content propeties in memory
 * </ul>
 */
public class DefaultValueStore implements ValueStore {
    private Map openContentValues;//open content values keyed on real prop name
    private Object[] typePropertyValues;
    /** Visibility reduced from [public] in 2.1.0. May 15 2007 */
    private boolean[] typePropertiesIsSetStatus;
    private DataObject dataObject;

    public DefaultValueStore() {
    }

    @Override
    public Object getDeclaredProperty(int propertyIndex) {
        if (typePropertyValues != null) {
            return typePropertyValues[propertyIndex];
        }
        return null;
    }

    @Override
    public Object getOpenContentProperty(Property property) {
        return getOpenContentValues().get(property);
    }

    @Override
    public void setDeclaredProperty(int propertyIndex, Object value) {
        getTypePropertyValues()[propertyIndex] = value;
        getTypePropertiesIsSetStatus()[propertyIndex] = true;
    }

    @Override
    public void setOpenContentProperty(Property property, Object value) {
        getOpenContentValues().put(property, value);
    }

    @Override
    public boolean isSetDeclaredProperty(int propertyIndex) {
        boolean[] typePropertiesIsSetStatus = getTypePropertiesIsSetStatus();
        if(propertyIndex >= typePropertiesIsSetStatus.length) {
            // New properties have been added to the type since the DataObject
            // was created so return false to indicate that the new property has
            // not been set.
            return false;
        }
        return typePropertiesIsSetStatus[propertyIndex];
    }

    @Override
    public boolean isSetOpenContentProperty(Property property) {
        return getOpenContentValues().containsKey(property);
    }

    @Override
    public void unsetDeclaredProperty(int propertyIndex) {
        Property prop = ((SDODataObject)dataObject).getInstanceProperty(propertyIndex);
        if (!prop.isMany()) {
            getTypePropertyValues()[propertyIndex] = null;
        }
        getTypePropertiesIsSetStatus()[propertyIndex] = false;
    }

    @Override
    public void unsetOpenContentProperty(Property property) {
        getOpenContentValues().remove(property);
    }

    /**
      * Perform any post-instantiation integrity operations that could not be done during
      * ValueStore creation.<br>
      * Since the dataObject reference passed in may be bidirectional or self-referencing
      * - we cannot set this variable until the dataObject itself is finished instantiation
      * - hence the 2-step initialization.
      *
      * @param aDataObject
      */
    @Override
    public void initialize(DataObject aDataObject) {
        dataObject = aDataObject;
        setTypePropertiesIsSetStatus(new boolean[aDataObject.getType().getProperties().size()]);
        setTypePropertyValues(new Object[aDataObject.getType().getProperties().size()]);
    }

    /**
     * Set the values for declared properties
     * @param typePropertyValuesArray
     */
    public void setTypePropertyValues(Object[] typePropertyValuesArray) {
        typePropertyValues = typePropertyValuesArray;
    }

    /**
     * INTERNAL:
     * @param typePropertiesIsSetStatusArray  boolean[] of isSet values for declared properties
     */
    public void setTypePropertiesIsSetStatus(boolean[] typePropertiesIsSetStatusArray) {
        typePropertiesIsSetStatus = typePropertiesIsSetStatusArray;
    }

    /**
     * INTERNAL:
     * @return Object[] of the values of declared properties
     */
    public Object[] getTypePropertyValues() {
        return typePropertyValues;
    }

    /**
     * INTERNAL:
     * @return boolean[] of isSet values for declared properties
     */
    public boolean[] getTypePropertiesIsSetStatus() {
        return typePropertiesIsSetStatus;
    }

    /**
     * INTERNAL:
     * @param openContentValues
     */
    public void setOpenContentValues(Map openContentValues) {
        this.openContentValues = openContentValues;
    }

    /**
     * INTERNAL:
     * @return Non-null Map of values for open content properties
     */
    public Map getOpenContentValues() {
        if (openContentValues == null) {
            openContentValues = new HashMap();
        }
        return openContentValues;
    }

    //  Do not implement this function unless the valueStore handles its own object wrapping
    @Override
    public void setManyProperty(Property property, Object value) {
    }

    /**
      * Get a shallow copy of the original ValueStore.
      * Changes made to the copy must not impact the original ValueStore
      * @return ValueStore
      */
    @Override
    public ValueStore copy() {

        /**
         * Implementer: SDODataObject.resetChanges()
         */
        DefaultValueStore anOriginalValueStore = new DefaultValueStore();
        anOriginalValueStore.dataObject = dataObject;

        boolean[] currentIsSet = getTypePropertiesIsSetStatus();
        boolean[] isSetCopy = new boolean[currentIsSet.length];
        System.arraycopy(currentIsSet, 0, isSetCopy, 0, currentIsSet.length);

        Object[] currentValues = getTypePropertyValues();
        Object[] valueCopy = new Object[currentValues.length];
        System.arraycopy(currentValues, 0, valueCopy, 0, currentValues.length);
        // shallow copy isSet boolean
        anOriginalValueStore.setTypePropertiesIsSetStatus(isSetCopy);
        // shallow copy the object values
        anOriginalValueStore.setTypePropertyValues(valueCopy);

        HashMap clonedMap = new HashMap();

        /**
         * Note: if the oc Map is null we will return an empty map
         * this empty Map will be set on the copy but the original will still actually have a null Map
         * this is ok because any get on the original will create a new Map and we will
         * not have object equality between copy and original oc maps
         * Just be aware that the two openContentValues will not pass value equility unless
         * the public get function is used
         */
        clonedMap.putAll(getOpenContentValues());
        // shallow copy oc values
        anOriginalValueStore.setOpenContentValues(clonedMap);

        return anOriginalValueStore;
    }

    /**
     *  Indicates if a given ValueStore is equal to this.  The following
     *  attributes are tested for equality:
     *      - data object
     *      - type property values
     *      - open content property values
     *      - property isSet values
     */
    @Override
    public boolean equals(Object obj) {
        DefaultValueStore dvs;
        try {
            dvs = (DefaultValueStore) obj;
        } catch (ClassCastException cce) {
            return false;
        }
        // Compare data object
        if (dvs.dataObject != this.dataObject) {
            return false;
        }
        // Compare declared properties and isSet status
        // All lists must be the same length
        if (dvs.getTypePropertyValues().length != this.getTypePropertyValues().length ||
                dvs.getTypePropertiesIsSetStatus().length != this.getTypePropertiesIsSetStatus().length) {
            return false;
        }
        for (int i=0; i<dvs.getTypePropertyValues().length; i++) {
            // isSet values must be equal
            if (dvs.isSetDeclaredProperty(i) != this.isSetDeclaredProperty(i)) {
                return false;
            }
            Object dvsPropVal  = dvs.getDeclaredProperty(i);
            Object thisPropVal = this.getDeclaredProperty(i);
            // Both values need to be null or non-null
            if (dvsPropVal == null) {
                if (thisPropVal != null) {
                    return false;
                }
                // Here both are null so no need to check anything
            } else {
                if (!(dvsPropVal.equals(thisPropVal))) {
                    return false;
                }
            }
        }
        // Compare open content properties
        if (dvs.getOpenContentValues().size() != this.getOpenContentValues().size()) {
            return false;
        }
        Iterator<Property> keyIt = dvs.getOpenContentValues().keySet().iterator();
        while (keyIt.hasNext()) {
            Property key = keyIt.next();
            Object dvsOCVal  = dvs.getOpenContentProperty(key);
            Object thisOCVal = this.getOpenContentProperty(key);
            // Both values need to be null or non-null
            if (dvsOCVal == null) {
                if (thisOCVal != null) {
                    return false;
                }
                // Here both are null so no need to check anything
            } else {
                if (!(dvsOCVal.equals(thisOCVal))) {
                    return false;
                }
            }
        }
        return true;
    }

    @Override
    public int hashCode() {
        Object[] typePropertyValues = getTypePropertyValues();
        boolean[] typePropertiesIsSetStatus = getTypePropertiesIsSetStatus();
        int result = dataObject != null ? dataObject.hashCode() : 0;
        result = 31 * result + (typePropertyValues != null ? Arrays.hashCode(typePropertyValues) : 0);
        result = 31 * result + (typePropertiesIsSetStatus != null ? Arrays.hashCode(typePropertiesIsSetStatus) : 0);
        result = 31 * result + getOpenContentValues().hashCode();
        return result;
    }
}
