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

import java.util.*;

import org.eclipse.persistence.internal.queries.ContainerPolicy;

/**
 * <p>
 * <b>Purpose</b>: This class holds the record of the changes made to a collection attribute of
 * an object.
 * <p>
 * <b>Description</b>: Collections must be compared to each other and added and removed objects must
 * be recorded separately.
 */
public class DirectCollectionChangeRecord extends DeferrableChangeRecord implements org.eclipse.persistence.sessions.changesets.DirectCollectionChangeRecord {
    protected HashMap addObjectMap;
    protected HashMap removeObjectMap;
    /**
     * Contains the number of objects that must be inserted to once the value is removed
     * in the database as a delete where value = "value" will remove all instances
     * of that value in the database not just one.
     */
    protected HashMap commitAddMap;

    /**
     * Used only in case listOrderField != null in the mapping.
     * Maps each object which has been added or removed or which order in the list has changed
     * to an array of two (non-intersecting) sets of indexes - old and new.
     */
    protected Map changedIndexes;
    protected int oldSize;
    protected int newSize;

    protected boolean isFirstToAddAlreadyInCollection;
    protected boolean isFirstToRemoveAlreadyOutCollection;

    protected boolean isFirstToAdd = true;
    protected boolean isFirstToRemove = true;

    /**
     * Indicates whether IndirectList's order has been repaired.
     */
    protected boolean orderHasBeenRepaired;

    /**
     * This default constructor.
     */
    public DirectCollectionChangeRecord() {
        super();
    }

    /**
     * This constructor returns a changeRecord representing the DirectCollection mapping.
     */
    public DirectCollectionChangeRecord(ObjectChangeSet owner) {
        this.owner = owner;
    }

    /**
     * This method takes a map of primitive objects and adds them to the add list.
     * The map stores the number of times the object is in the list.
     */
    public void addAdditionChange(HashMap additions, HashMap databaseCount) {
        Iterator enumtr = additions.keySet().iterator();
        while (enumtr.hasNext()) {
            Object object = enumtr.next();
            if (databaseCount.containsKey(object)){
                getCommitAddMap().put(object, databaseCount.get(object));
            }
            addAdditionChange(object, (Integer)additions.get(object));
        }
    }

    /**
     * This method takes a single addition value and records it.
     */
    public void addAdditionChange(Object key, Integer count){
        if (getRemoveObjectMap().containsKey(key)) {
            int removeValue = ((Integer)getRemoveObjectMap().get(key)).intValue();
            int addition = count.intValue();
            int result = removeValue - addition;
            if (result > 0 ) { // more removes still
                getRemoveObjectMap().put(key, Integer.valueOf(result));
            } else if (result < 0) { // more adds now
                getRemoveObjectMap().remove(key);
                getAddObjectMap().put(key, Integer.valueOf(Math.abs(result)));
            } else { // equal
                getRemoveObjectMap().remove(key);
            }
        } else {
            if (this.getAddObjectMap().containsKey(key)) {
                int addValue = ((Integer)this.getAddObjectMap().get(key)).intValue();
                addValue += count.intValue();
                this.getAddObjectMap().put(key, Integer.valueOf(addValue));
            } else {
                this.getAddObjectMap().put(key, count);
            }
        }
        if(this.isFirstToAdd) {
            this.isFirstToAdd = false;
            if(this.isFirstToAddAlreadyInCollection) {
                return;
            }
        }
        // this is an attribute change track add keep count
        int addValue = count.intValue();
        int commitValue = 0;
        if (getCommitAddMap().containsKey(key)) {
            commitValue = ((Integer)getCommitAddMap().get(key)).intValue();
        }
        getCommitAddMap().put(key, Integer.valueOf(addValue + commitValue));
    }

    /**
     * This method takes a hashtable of primitive objects and adds them to the remove list.
     * Each reference in the hashtable lists the number of this object that needs to be removed from the
     * collection.
     */
    public void addRemoveChange(HashMap additions, HashMap databaseCount) {
        Iterator enumtr = additions.keySet().iterator();
        while (enumtr.hasNext()) {
            Object object = enumtr.next();
            if (databaseCount.containsKey(object)){
                getCommitAddMap().put(object, databaseCount.get(object));
            }
            addRemoveChange(object, (Integer)additions.get(object));
        }
    }

    /**
     * This method takes a single remove change and integrates it with this changeset.
     */
    public void addRemoveChange(Object key, Integer count){
        if (getAddObjectMap().containsKey(key)) {
            int removeValue = ((Integer)getAddObjectMap().get(key)).intValue();
            int addition = count.intValue();
            int result = removeValue - addition;
            if (result > 0 ) { // more removes still
                getAddObjectMap().put(key, Integer.valueOf(result));
            } else if (result < 0) { // more adds now
                getAddObjectMap().remove(key);
                getRemoveObjectMap().put(key, Integer.valueOf(Math.abs(result)));
            } else { // equal
                getAddObjectMap().remove(key);
            }
        } else {
            if (this.getRemoveObjectMap().containsKey(key)){
                int addValue = ((Integer)this.getRemoveObjectMap().get(key)).intValue();
                addValue += count.intValue();
                this.getRemoveObjectMap().put(key, Integer.valueOf(addValue));
            } else {
                this.getRemoveObjectMap().put(key, count);
            }
        }
        if(this.isFirstToRemove) {
            this.isFirstToRemove = false;
            if(this.isFirstToRemoveAlreadyOutCollection) {
                return;
            }
        }
        int removeValue = count.intValue();
        int commitValue = 0;
        if (getCommitAddMap().containsKey(key)){
            commitValue = ((Integer)getCommitAddMap().get(key)).intValue();
        }
        getCommitAddMap().put(key, Integer.valueOf(commitValue - removeValue));
    }

    /**
     * This method takes a hashtable of primitives and adds them to the commit list.
     * This count value provided is the number of instances that will need to be
     * inserted into the database once a remove has occurred.  This is only set
     * once for each object type.
     */
    public void setCommitAddition(Hashtable additions){
        Enumeration enumtr = additions.keys();
        while (enumtr.hasMoreElements()) {
            Object object = enumtr.nextElement();
            getCommitAddMap().put(object, additions.get(object));
        }
    }

    /**
     * This method will iterate over the collection and store the database counts for
     * the objects within the collection, this is used for minimal updates.
     */
    public void storeDatabaseCounts(Object collection, ContainerPolicy containerPolicy, AbstractSession session){
        Object iterator = containerPolicy.iteratorFor(collection);
        while (containerPolicy.hasNext(iterator)) {
            Object object = containerPolicy.next(iterator, session);
            incrementDatabaseCount(object);
        }
    }

    /**
     * Increment the count for object
     */
    public void incrementDatabaseCount(Object object){
        if (getCommitAddMap().containsKey(object)) {
            int count = ((Integer)getCommitAddMap().get(object)).intValue();
            getCommitAddMap().put(object, Integer.valueOf(++count));
        } else {
            getCommitAddMap().put(object, Integer.valueOf(1));
        }
    }

    /**
     * Decrement the count for object
     */
    public void decrementDatabaseCount(Object object){
        if (getCommitAddMap().containsKey(object)) {
            int count = ((Integer)getCommitAddMap().get(object)).intValue();
            if(count > 1) {
                getCommitAddMap().put(object, Integer.valueOf(--count));
            } else {
                getCommitAddMap().remove(object);
            }
        }
    }

    /**
     * ADVANCED:
     * This method returns the list of added objects.
     */
    @Override
    public Vector getAddObjectList(){
        Vector vector = new Vector();
        for (Iterator iterator = getAddObjectMap().keySet().iterator(); iterator.hasNext();){
            Object object = iterator.next();
            int count = ((Integer)getAddObjectMap().get(object)).intValue();
            while (count > 0){
                vector.add(object);
                --count;
            }
        }
        return vector;
    }

    /**
     * This method returns the collection of objects that were added to the collection.
     */
    public HashMap getAddObjectMap() {
        if (this.addObjectMap == null) {
            this.addObjectMap = new HashMap(1);
        }
        return addObjectMap;
    }

    /**
     * This method returns the collection of objects that were added to the collection.
     */
    public HashMap getCommitAddMap() {
        if (this.commitAddMap == null) {
            this.commitAddMap = new HashMap(1);
        }
        return commitAddMap;
    }

    /**
     * ADVANCED:
     * This method returns the list of removed objects.
     */
    @Override
    public Vector getRemoveObjectList(){
        Vector vector = new Vector();
        for (Iterator iterator = getRemoveObjectMap().keySet().iterator(); iterator.hasNext();){
            Object object = iterator.next();
            int count = ((Integer)getRemoveObjectMap().get(object)).intValue();
            while (count > 0){
                vector.add(object);
                --count;
            }
        }
        return vector;
    }

    /**
     * This method returns the collection of objects that were removed from the collection.
     */
    public HashMap getRemoveObjectMap() {
        if (this.removeObjectMap == null) {
            removeObjectMap = new HashMap(1);
        }
        return removeObjectMap;
    }

    /**
     * Returns true if the change set has changes.
     */
    public boolean hasChanges() {
        return (!((this.addObjectMap == null || this.addObjectMap.isEmpty())
            && (this.removeObjectMap == null || this.removeObjectMap.isEmpty())
            && (this.changedIndexes == null || this.changedIndexes.isEmpty()))) || getOwner().isNew();
    }

    /**
     * This method will be used to merge one record into another.
     */
    @Override
    public void mergeRecord(ChangeRecord mergeFromRecord, UnitOfWorkChangeSet mergeToChangeSet, UnitOfWorkChangeSet mergeFromChangeSet) {
        if (((DeferrableChangeRecord)mergeFromRecord).isDeferred()){
            if (this.hasChanges()){
                //merging into existing change record need to combine changes
                mergeFromRecord.getMapping().calculateDeferredChanges(mergeFromRecord, mergeToChangeSet.getSession());
            }else{
                this.isDeferred = true;
                this.originalCollection = ((DeferrableChangeRecord)mergeFromRecord).originalCollection;
                this.latestCollection = ((DeferrableChangeRecord)mergeFromRecord).latestCollection;
                return;
            }
        }
        HashMap addMapToMerge = ((DirectCollectionChangeRecord)mergeFromRecord).getAddObjectMap();
        HashMap removeMapToMerge = ((DirectCollectionChangeRecord)mergeFromRecord).getRemoveObjectMap();
        //merge additions
        for (Iterator iterator = addMapToMerge.keySet().iterator(); iterator.hasNext();){
            Object added = iterator.next();
            if (!((DirectCollectionChangeRecord)mergeFromRecord).getCommitAddMap().containsKey(added)){
                // we have not recorded a change of this type in this class before so  add it
                this.getCommitAddMap().put(added, ((DirectCollectionChangeRecord)mergeFromRecord).getCommitAddMap().get(added));
            }
            this.addAdditionChange(added, (Integer)addMapToMerge.get(added));
        }
        //merge removals
        for (Iterator iterator = removeMapToMerge.keySet().iterator(); iterator.hasNext();){
            Object removed = iterator.next();
            if (!((DirectCollectionChangeRecord)mergeFromRecord).getCommitAddMap().containsKey(removed)){
                // we have not recorded a change of this type in this class before so  add it
                this.getCommitAddMap().put(removed, Integer.valueOf(1));
            }
            this.addRemoveChange(removed, (Integer)removeMapToMerge.get(removed));
        }

        if(this.changedIndexes != null) {
            if(((DirectCollectionChangeRecord)mergeFromRecord).getChangedIndexes() != null) {
                Iterator<Map.Entry<Object, Set[]>> itEntries = ((DirectCollectionChangeRecord)mergeFromRecord).getChangedIndexes().entrySet().iterator();
                while(itEntries.hasNext()) {
                    Map.Entry<Object, Set[]> entry = itEntries.next();
                    Object obj = entry.getValue();
                    Set[] indexes = entry.getValue();
                    if(this.changedIndexes.containsKey(obj)) {
                        // we assuming that these are two consecutive change records:
                        // oldIndexes[1] should be equal to newIndexes[0]
                        ((Set[])(this.changedIndexes.get(obj)))[1] = indexes[1];
                    } else {
                        this.changedIndexes.put(obj, indexes);
                    }
                }
                this.newSize = ((DirectCollectionChangeRecord)mergeFromRecord).getNewSize();
            }
        } else {
            if(((DirectCollectionChangeRecord)mergeFromRecord).getChangedIndexes() != null) {
                this.changedIndexes = new HashMap(((DirectCollectionChangeRecord)mergeFromRecord).getChangedIndexes());
                this.oldSize = ((DirectCollectionChangeRecord)mergeFromRecord).getOldSize();
                this.newSize = ((DirectCollectionChangeRecord)mergeFromRecord).getNewSize();
            }
        }
   }

    /**
     * This method will be used to update the objectsChangeSets references
     */
    @Override
    public void updateReferences(UnitOfWorkChangeSet mergeToChangeSet, UnitOfWorkChangeSet mergeFromChangeSet) {
        //nothing for this record type to do as it does not reference any changesets
    }

    public static class NULL {
        // This is a placeholder for null instances.
        public NULL(){
        }
        @Override
        public boolean equals(Object object){
            return object instanceof NULL;
        }
    }

    public void setFirstToAddAlreadyInCollection(boolean flag) {
        this.isFirstToAddAlreadyInCollection = flag;
    }
    public boolean isFirstToAddAlreadyInCollection() {
        return this.isFirstToAddAlreadyInCollection;
    }

    public void setFirstToRemoveAlreadyOutCollection(boolean flag) {
        this.isFirstToRemoveAlreadyOutCollection = flag;
    }
    public boolean isFirstToRemoveAlreadyOutCollection() {
        return this.isFirstToRemoveAlreadyOutCollection;
    }

    public void setChangedIndexes(Map changedIndexes) {
        this.changedIndexes = changedIndexes;
    }
    public Map getChangedIndexes() {
        return this.changedIndexes;
    }
    public void setOldSize(int size) {
        this.oldSize = size;
    }
    public int getOldSize() {
        return this.oldSize;
    }
    public void setNewSize(int size) {
        this.newSize = size;
    }
    public int getNewSize() {
        return this.newSize;
    }

   /**
    * Recreates the original state of the collection.
    */
  @Override
public void internalRecreateOriginalCollection(Object currentCollection, AbstractSession session) {
      ContainerPolicy cp = this.mapping.getContainerPolicy();
       if(this.removeObjectMap != null) {
           Iterator it = this.removeObjectMap.entrySet().iterator();
           while(it.hasNext()) {
               Map.Entry entry = (Map.Entry)it.next();
               Object obj = entry.getKey();
               int n = (Integer)entry.getValue();
               for(int i=0; i < n; i++) {
                   cp.addInto(obj, currentCollection, session);
               }
           }
       }
       if(this.addObjectMap != null) {
           Iterator it = this.addObjectMap.entrySet().iterator();
           while(it.hasNext()) {
               Map.Entry entry = (Map.Entry)it.next();
               Object obj = entry.getKey();
               int n = (Integer)entry.getValue();
               for(int i=0; i < n; i++) {
                   cp.removeFrom(obj, currentCollection, session);
               }
           }
       }
   }

  public void setOrderHasBeenRepaired(boolean hasBeenRepaired) {
       this.orderHasBeenRepaired = hasBeenRepaired;
   }
   public boolean orderHasBeenRepaired() {
       return this.orderHasBeenRepaired;
   }

   /**
    * Clears info about added / removed objects set by change tracker.
    */
   @Override
public void clearChanges() {
       if(this.removeObjectMap != null) {
           this.removeObjectMap.clear();
       }
       if(this.addObjectMap != null) {
           this.addObjectMap.clear();
       }
       if(this.addObjectMap != null) {
           this.addObjectMap.clear();
       }
       if(this.removeObjectMap != null) {
           this.removeObjectMap.clear();
       }
       if(this.commitAddMap != null) {
           this.commitAddMap.clear();
       }
   }
}
