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

import java.util.ArrayList;
import java.util.List;

import org.eclipse.persistence.internal.sessions.CollectionChangeRecord;
import org.eclipse.persistence.internal.sessions.ObjectChangeSet;
import org.eclipse.persistence.mappings.DatabaseMapping;

/**
 * INTERNAL:
 * Capture the changes for an ordered collection where
 * the entire collection is simply replaced if it has changed.
 */
public class EISOrderedCollectionChangeRecord extends CollectionChangeRecord implements org.eclipse.persistence.sessions.changesets.EISOrderedCollectionChangeRecord {

    /** The added stuff. */
    private List adds;

    /** The indexes into the new collection of the elements that were added. */
    private int[] addIndexes;

    /** The moved stuff. */
    private List moves;

    /** The index pairs of the elements that were moved (before and after indexes). */
    private int[][] moveIndexPairs;

    /** The removed stuff. */
    private List removes;

    /** The indexes into the old collection of the elements that were removed. */
    private int[] removeIndexes;

    /**
     * Construct a ChangeRecord that can be used to represent the changes to
     * an ordered collection.
     */
    public EISOrderedCollectionChangeRecord(ObjectChangeSet owner, String attributeName, DatabaseMapping mapping) {
        super();
        this.owner = owner;
        this.attribute = attributeName;
        this.mapping = mapping;
    }

    /**
     * Add an added change set.
     */
    public void addAddedChangeSet(Object changeSet, int index) {
        getAdds().add(changeSet);
        setAddIndexes(this.addTo(index, getAddIndexes()));
    }

    /**
     * Add an moved change set.
     */
    public void addMovedChangeSet(Object changeSet, int oldIndex, int newIndex) {
        getMoves().add(changeSet);
        int[] pair = new int[2];
        pair[0] = oldIndex;
        pair[1] = newIndex;
        setMoveIndexPairs(this.addTo(pair, getMoveIndexPairs()));
    }

    /**
     * Add an removed change set.
     */
    public void addRemovedChangeSet(Object changeSet, int index) {
        getRemoves().add(changeSet);
        setRemoveIndexes(this.addTo(index, getRemoveIndexes()));
    }

    /**
     * Add the int to the end of the array.
     * Return the new array.
     */
    private int[] addTo(int newInt, int[] oldArray) {
        int oldCount = oldArray.length;
        int[] newArray = new int[oldCount + 1];
        System.arraycopy(oldArray, 0, newArray, 0, oldCount);
        newArray[oldCount] = newInt;// zero-based index
        return newArray;
    }

    /**
     * Add the int[] to the end of the array.
     * Return the new array.
     */
    private int[][] addTo(int[] newInts, int[][] oldArray) {
        int oldCount = oldArray.length;
        int[][] newArray = new int[oldCount + 1][];
        System.arraycopy(oldArray, 0, newArray, 0, oldCount);
        newArray[oldCount] = newInts;// zero-based index
        return newArray;
    }

    /**
     * Return the specified add.
     */
    private Object getAdd(int index) {
        return this.getAdds().get(index);
    }

    /**
     * ADVANCED:
     * Return the indexes into the new collection of
     * the elements that were added.
     */
    @Override
    public int[] getAddIndexes() {
        if (addIndexes == null) {
            addIndexes = new int[0];
        }
        return addIndexes;
    }

    /**
     * ADVANCED:
     * Return the entries for all the elements added to the new collection.
     * The contents of this collection is determined by the mapping that
     * populated it
     */
    @Override
    public List getAdds() {
        if (adds == null) {
            adds = new ArrayList(2);// keep it as small as possible
        }
        return adds;
    }

    /**
     * Return the index in the adds of the specified change set,
     * without triggering the instantiation of the collection.
     */
    private int getAddsIndexOf(Object changeSet) {
        if (adds == null) {
            return -1;
        }
        return adds.indexOf(changeSet);
    }

    /**
     * Return the number of adds, without triggering
     * the instantiation of the collection.
     */
    private int getAddsSize() {
        if (adds == null) {
            return 0;
        }
        return adds.size();
    }

    /**
     * Return the specified move.
     */
    private Object getMove(int index) {
        return this.getMoves().get(index);
    }

    /**
     * Return the specified "before" move index.
     */
    private int getBeforeMoveIndex(int index) {
        int[][] pairs = getMoveIndexPairs();
        return pairs[index][0];
    }

    /**
     * ADVANCED:
     * Return the indexes of the elements that were simply moved
     * within the collection.
     * Each element in the outer array is another two-element
     * array where the first entry [0] is the index of the object in
     * the old collection and the second entry [1] is the index
     * of the object in the new collection. These two indexes
     * can be equal.
     */
    @Override
    public int[][] getMoveIndexPairs() {
        if (moveIndexPairs == null) {
            moveIndexPairs = new int[0][0];
        }
        return moveIndexPairs;
    }

    /**
     * ADVANCED:
     * Return the entries for all the elements that were simply shuffled
     * within the collection.
     * The contents of this collection is determined by the mapping that
     * populated it
     */
    @Override
    public List getMoves() {
        if (moves == null) {
            moves = new ArrayList(2);// keep it as small as possible
        }
        return moves;
    }

    /**
     * Return the index in the moves of the specified change set,
     * without triggering the instantiation of the collection.
     */
    private int getMovesIndexOf(Object changeSet) {
        if (moves == null) {
            return -1;
        }
        return moves.indexOf(changeSet);
    }

    /**
     * Return the number of moves, without triggering
     * the instantiation of the collection.
     */
    private int getMovesSize() {
        if (moves == null) {
            return 0;
        }
        return moves.size();
    }

    /**
     * ADVANCED:
     * Return the entries for all the elements in the new collection.
     * The contents of this collection is determined by the mapping that
     * populated it
     */
    @Override
    public List getNewCollection() {
        int newSize = getNewCollectionSize();
        List newCollection = new ArrayList(newSize);

        int[] localAddIndexes = addIndexes;
        if (localAddIndexes == null) {
            localAddIndexes = new int[0];
        }

        int[][] localMoveIndexPairs = moveIndexPairs;
        if (localMoveIndexPairs == null) {
            localMoveIndexPairs = new int[0][0];
        }

        int addIndex = 0;
        int moveIndex = 0;
        for (int i = 0; i < newSize; i++) {
            if ((addIndex < localAddIndexes.length) && (localAddIndexes[addIndex] == i)) {
                newCollection.add(this.getAdd(addIndex));
                addIndex++;
                continue;
            }
            if ((moveIndex < localMoveIndexPairs.length) && (localMoveIndexPairs[moveIndex][1] == i)) {
                newCollection.add(this.getMove(moveIndex));
                moveIndex++;
                continue;
            }
            throw new IllegalStateException(String.valueOf(i));
        }
        return newCollection;
    }

    /**
     * Return the number of elements in the new collection,
     * without triggering the instantiation of the collections.
     */
    private int getNewCollectionSize() {
        return this.getAddsSize() + this.getMovesSize();
    }

    /**
     * Return the specified remove index.
     */
    private int getRemoveIndex(int index) {
        return this.getRemoveIndexes()[index];
    }

    /**
     * ADVANCED:
     * Return the indexes into the old collection of
     * the elements that were removed.
     */
    @Override
    public int[] getRemoveIndexes() {
        if (removeIndexes == null) {
            removeIndexes = new int[0];
        }
        return removeIndexes;
    }

    /**
     * ADVANCED:
     * Return the entries for all the elements removed from the old collection.
     * The contents of this collection is determined by the mapping that
     * populated it
     */
    @Override
    public List getRemoves() {
        if (removes == null) {
            removes = new ArrayList(2);// keep it as small as possible
        }
        return removes;
    }

    /**
     * Return the index in the removes of the specified change set,
     * without triggering the instantiation of the collection.
     */
    private int getRemovesIndexOf(Object changeSet) {
        if (removes == null) {
            return -1;
        }
        return removes.indexOf(changeSet);
    }

    /**
     * Return whether any adds have been recorded with the change record.
     * Directly reference the instance variable, so as to not trigger the lazy instantiation.
     */
    private boolean hasAdds() {
        return (addIndexes != null) && (addIndexes.length != 0);
    }

    /**
     * Return whether any changes have been recorded with the change record.
     */
    @Override
    public boolean hasChanges() {
        if (this.hasAdds() || this.hasRemoves() || this.getOwner().isNew()) {
            return true;
        }

        // BUG#.... the moves always contain everything, must check if any indexes are different.
        if (hasMoves()) {
            for (int index = 0; index < moveIndexPairs.length; index++) {
                if (moveIndexPairs[index][0] != moveIndexPairs[index][1]) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * Return whether any moves have been recorded with the change record.
     * Directly reference the instance variable, so as to not trigger the lazy instantiation.
     */
    private boolean hasMoves() {
        return (moveIndexPairs != null) && (moveIndexPairs.length != 0);
    }

    /**
     * Return whether any removes have been recorded with the change record.
     * Directly reference the instance variable, so as to not trigger the lazy instantiation.
     */
    private boolean hasRemoves() {
        return (removeIndexes != null) && (removeIndexes.length != 0);
    }

    /**
     * Remove the specified slot from the array.
     * Return the new array.
     */
    private int[] removeFrom(int removeIndex, int[] oldArray) {
        int oldCount = oldArray.length;
        int[] newArray = new int[oldCount - 1];
        System.arraycopy(oldArray, 0, newArray, 0, removeIndex);
        System.arraycopy(oldArray, removeIndex + 1, newArray, removeIndex, oldCount - removeIndex - 1);
        return newArray;
    }

    /**
     * Remove the specified slot from the array.
     * Return the new array.
     */
    private int[][] removeFrom(int removeIndex, int[][] oldArray) {
        int oldCount = oldArray.length;
        int[][] newArray = new int[oldCount - 1][];
        System.arraycopy(oldArray, 0, newArray, 0, removeIndex);
        System.arraycopy(oldArray, removeIndex + 1, newArray, removeIndex, oldCount - removeIndex - 1);
        return newArray;
    }

    /**
     * The specified change set was added earlier;
     * cancel it out.
     */
    private void cancelAddedChangeSet(Object changeSet) {
        int changeSetIndex = this.getAddsIndexOf(changeSet);
        if (changeSetIndex == -1) {
            throw new IllegalStateException(changeSet.toString());
        }
        this.getAdds().remove(changeSetIndex);
        this.setAddIndexes(this.removeFrom(changeSetIndex, this.getAddIndexes()));
    }

    /**
     * Attempt to remove the specified change set
     * from the collection of moved change sets.
     * Return true if the change set was moved earlier
     * and was successfully removed.
     */
    private boolean removeMovedChangeSet(Object changeSet) {
        int changeSetIndex = this.getMovesIndexOf(changeSet);
        if (changeSetIndex == -1) {
            return false;
        }
        this.getMoves().remove(changeSetIndex);
        int beforeMoveIndex = this.getBeforeMoveIndex(changeSetIndex);
        this.setMoveIndexPairs(this.removeFrom(changeSetIndex, this.getMoveIndexPairs()));
        // now move the change set over to the collection of removes
        this.addRemovedChangeSet(changeSet, beforeMoveIndex);
        return true;
    }

    /**
     * Attempt to restore the specified change set.
     * Return true if the change set was removed earlier
     * and was successfully restored to the end of
     * the collection.
     */
    private boolean restoreRemovedChangeSet(Object changeSet) {
        int changeSetIndex = this.getRemovesIndexOf(changeSet);
        if (changeSetIndex == -1) {
            return false;
        }
        this.getRemoves().remove(changeSetIndex);
        int removeIndex = this.getRemoveIndex(changeSetIndex);
        this.setRemoveIndexes(this.removeFrom(changeSetIndex, this.getRemoveIndexes()));
        // now move the change set over to the collection of moves
        this.addMovedChangeSet(changeSet, removeIndex, this.getNewCollectionSize());
        return true;
    }

    /**
     * Set the indexes into the new collection of
     * the elements that were added.
     */
    private void setAddIndexes(int[] addIndexes) {
        this.addIndexes = addIndexes;
    }

    /**
     * Set the indexes of the elements that were moved.
     */
    private void setMoveIndexPairs(int[][] moveIndexPairs) {
        this.moveIndexPairs = moveIndexPairs;
    }

    /**
     * Set the indexes into the old collection of
     * the elements that were removed.
     */
    private void setRemoveIndexes(int[] removeIndexes) {
        this.removeIndexes = removeIndexes;
    }

    /**
     * Add a change set after it has been applied.
     */
    public void simpleAddChangeSet(Object changeSet) {
        // check whether the change set was removed earlier
        if (!this.restoreRemovedChangeSet(changeSet)) {
            // the change set is tacked on the end of the new collection
            this.addAddedChangeSet(changeSet, this.getNewCollectionSize());
        }
    }

    /**
     * Remove a change set after it has been applied.
     */
    public void simpleRemoveChangeSet(Object changeSet) {
        // the change set must have been either moved or added earlier
        if (!this.removeMovedChangeSet(changeSet)) {
            this.cancelAddedChangeSet(changeSet);
        }
    }
}
