/*
 * 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.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; // either ObjectChangeSet or String (simple type)

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

    /** The moved stuff. */
    private List moves; // either ObjectChangeSet or String (simple type)

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

    /** The removed stuff. */
    private List removes; // either ObjectChangeSet or String (simple type)

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