/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.cassandra.utils.btree;

import org.apache.cassandra.utils.ObjectSizes;

import java.util.Arrays;
import java.util.Comparator;

import static org.apache.cassandra.utils.btree.BTree.*;

/**
 * Represents a level / stack item of in progress modifications to a BTree.
 */
final class NodeBuilder
{
    private static final int MAX_KEYS = 1 + (FAN_FACTOR * 2);

    // parent stack
    private NodeBuilder parent, child;

    // buffer for building new nodes
    private Object[] buildKeys = new Object[MAX_KEYS];  // buffers keys for branches and leaves
    private Object[] buildChildren = new Object[1 + MAX_KEYS]; // buffers children for branches only
    private int buildKeyPosition;
    private int buildChildPosition;
    // we null out the contents of buildKeys/buildChildren when clear()ing them for re-use; this is where
    // we track how much we actually have to null out
    private int maxBuildKeyPosition;

    // current node of the btree we're modifying/copying from
    private Object[] copyFrom;
    // the index of the first key in copyFrom that has not yet been copied into the build arrays
    private int copyFromKeyPosition;
    // the index of the first child node in copyFrom that has not yet been copied into the build arrays
    private int copyFromChildPosition;

    private UpdateFunction updateFunction;
    private Comparator comparator;

    // upper bound of range owned by this level; lets us know if we need to ascend back up the tree
    // for the next key we update when bsearch gives an insertion point past the end of the values
    // in the current node
    private Object upperBound;

    // ensure we aren't referencing any garbage
    void clear()
    {
        NodeBuilder current = this;
        while (current != null && current.upperBound != null)
        {
            current.clearSelf();
            current = current.child;
        }
        current = parent;
        while (current != null && current.upperBound != null)
        {
            current.clearSelf();
            current = current.parent;
        }
    }

    void clearSelf()
    {
        reset(null, null, null, null);
        Arrays.fill(buildKeys, 0, maxBuildKeyPosition, null);
        Arrays.fill(buildChildren, 0, maxBuildKeyPosition + 1, null);
        maxBuildKeyPosition = 0;
    }

    // reset counters/setup to copy from provided node
    void reset(Object[] copyFrom, Object upperBound, UpdateFunction updateFunction, Comparator comparator)
    {
        this.copyFrom = copyFrom;
        this.upperBound = upperBound;
        this.updateFunction = updateFunction;
        this.comparator = comparator;
        maxBuildKeyPosition = Math.max(maxBuildKeyPosition, buildKeyPosition);
        buildKeyPosition = 0;
        buildChildPosition = 0;
        copyFromKeyPosition = 0;
        copyFromChildPosition = 0;
    }

    NodeBuilder finish()
    {
        assert copyFrom != null;
        int copyFromKeyEnd = getKeyEnd(copyFrom);

        if (buildKeyPosition + buildChildPosition > 0)
        {
            // only want to copy if we've already changed something, otherwise we'll return the original
            copyKeys(copyFromKeyEnd);
            if (!isLeaf(copyFrom))
                copyChildren(copyFromKeyEnd + 1);
        }
        return isRoot() ? null : ascend();
    }

    /**
     * Inserts or replaces the provided key, copying all not-yet-visited keys prior to it into our buffer.
     *
     * @param key key we are inserting/replacing
     * @return the NodeBuilder to retry the update against (a child if we own the range being updated,
     * a parent if we do not -- we got here from an earlier key -- and we need to ascend back up),
     * or null if we finished the update in this node.
     */
    NodeBuilder update(Object key)
    {
        assert copyFrom != null;
        int copyFromKeyEnd = getKeyEnd(copyFrom);

        int i = copyFromKeyPosition;
        boolean found; // exact key match?
        boolean owns = true; // true if this node (or a child) should contain the key
        if (i == copyFromKeyEnd)
        {
            found = false;
        }
        else
        {
            // this optimisation is for the common scenario of updating an existing row with the same columns/keys
            // and simply avoids performing a binary search until we've checked the proceeding key;
            // possibly we should disable this check if we determine that it fails more than a handful of times
            // during any given builder use to get the best of both worlds
            int c = -comparator.compare(key, copyFrom[i]);
            if (c >= 0)
            {
                found = c == 0;
            }
            else
            {
                i = Arrays.binarySearch(copyFrom, i + 1, copyFromKeyEnd, key, comparator);
                found = i >= 0;
                if (!found)
                    i = -i - 1;
            }
        }

        if (found)
        {
            Object prev = copyFrom[i];
            Object next = updateFunction.apply(prev, key);
            // we aren't actually replacing anything, so leave our state intact and continue
            if (prev == next)
                return null;
            key = next;
        }
        else if (i == copyFromKeyEnd && compareUpperBound(comparator, key, upperBound) >= 0)
            owns = false;

        if (isLeaf(copyFrom))
        {

            if (owns)
            {
                // copy keys from the original node up to prior to the found index
                copyKeys(i);

                if (found)
                {
                    // if found, we've applied updateFunction already
                    replaceNextKey(key);
                }
                else
                {
                    // if not found, we need to apply updateFunction still, which is handled in addNewKey
                    addNewKey(key);
                }

                // done, so return null
                return null;
            }
            else
            {
                // we don't want to copy anything if we're ascending and haven't copied anything previously,
                // as in this case we can return the original node. Leaving buildKeyPosition as 0 indicates
                // to buildFromRange that it should return the original instead of building a new node
                if (buildKeyPosition > 0)
                    copyKeys(i);
            }

            // if we don't own it, all we need to do is ensure we've copied everything in this node
            // (which we have done, since not owning means pos >= keyEnd), ascend, and let Modifier.update
            // retry against the parent node.  The if/ascend after the else branch takes care of that.
        }
        else
        {
            // branch
            if (found)
            {
                copyKeys(i);
                replaceNextKey(key);
                copyChildren(i + 1);
                return null;
            }
            else if (owns)
            {
                copyKeys(i);
                copyChildren(i);

                // belongs to the range owned by this node, but not equal to any key in the node
                // so descend into the owning child
                Object newUpperBound = i < copyFromKeyEnd ? copyFrom[i] : upperBound;
                Object[] descendInto = (Object[]) copyFrom[copyFromKeyEnd + i];
                ensureChild().reset(descendInto, newUpperBound, updateFunction, comparator);
                return child;
            }
            else if (buildKeyPosition > 0 || buildChildPosition > 0)
            {
                // ensure we've copied all keys and children, but only if we've already copied something.
                // otherwise we want to return the original node
                copyKeys(copyFromKeyEnd);
                copyChildren(copyFromKeyEnd + 1); // since we know that there are exactly 1 more child nodes, than keys
            }
        }

        return ascend();
    }

    private static <V> int compareUpperBound(Comparator<V> comparator, Object value, Object upperBound)
    {
        return upperBound == POSITIVE_INFINITY ? -1 : comparator.compare((V)value, (V)upperBound);
    }

    // UTILITY METHODS FOR IMPLEMENTATION OF UPDATE/BUILD/DELETE

    boolean isRoot()
    {
        // if parent == null, or parent.upperBound == null, then we have not initialised a parent builder,
        // so we are the top level builder holding modifications; if we have more than FAN_FACTOR items, though,
        // we are not a valid root so we would need to spill-up to create a new root
        return (parent == null || parent.upperBound == null) && buildKeyPosition <= FAN_FACTOR;
    }

    // ascend to the root node, splitting into proper node sizes as we go; useful for building
    // where we work only on the newest child node, which may construct many spill-over parents as it goes
    NodeBuilder ascendToRoot()
    {
        NodeBuilder current = this;
        while (!current.isRoot())
            current = current.ascend();
        return current;
    }

    // builds a new root BTree node - must be called on root of operation
    Object[] toNode()
    {
        // we permit building empty trees as some constructions do not know in advance how many items they will contain
        assert buildKeyPosition <= FAN_FACTOR : buildKeyPosition;
        return buildFromRange(0, buildKeyPosition, isLeaf(copyFrom), false);
    }

    // finish up this level and pass any constructed children up to our parent, ensuring a parent exists
    private NodeBuilder ascend()
    {
        ensureParent();
        boolean isLeaf = isLeaf(copyFrom);
        if (buildKeyPosition > FAN_FACTOR)
        {
            // split current node and move the midpoint into parent, with the two halves as children
            int mid = buildKeyPosition / 2;
            parent.addExtraChild(buildFromRange(0, mid, isLeaf, true), buildKeys[mid]);
            parent.finishChild(buildFromRange(mid + 1, buildKeyPosition - (mid + 1), isLeaf, false));
        }
        else
        {
            parent.finishChild(buildFromRange(0, buildKeyPosition, isLeaf, false));
        }
        return parent;
    }

    // copy keys from copyf to the builder, up to the provided index in copyf (exclusive)
    private void copyKeys(int upToKeyPosition)
    {
        if (copyFromKeyPosition >= upToKeyPosition)
            return;

        int len = upToKeyPosition - copyFromKeyPosition;
        assert len <= FAN_FACTOR : upToKeyPosition + "," + copyFromKeyPosition;

        ensureRoom(buildKeyPosition + len);
        if (len > 0)
        {
            System.arraycopy(copyFrom, copyFromKeyPosition, buildKeys, buildKeyPosition, len);
            copyFromKeyPosition = upToKeyPosition;
            buildKeyPosition += len;
        }
    }

    // skips the next key in copyf, and puts the provided key in the builder instead
    private void replaceNextKey(Object with)
    {
        // (this first part differs from addNewKey in that we pass the replaced object to replaceF as well)
        ensureRoom(buildKeyPosition + 1);
        buildKeys[buildKeyPosition++] = with;

        copyFromKeyPosition++;
    }

    // applies the updateFunction
    // puts the resulting key into the builder
    // splits the parent if necessary via ensureRoom
    void addNewKey(Object key)
    {
        ensureRoom(buildKeyPosition + 1);
        buildKeys[buildKeyPosition++] = updateFunction.apply(key);
    }

    // copies children from copyf to the builder, up to the provided index in copyf (exclusive)
    private void copyChildren(int upToChildPosition)
    {
        // (ensureRoom isn't called here, as we should always be at/behind key additions)
        if (copyFromChildPosition >= upToChildPosition)
            return;
        int len = upToChildPosition - copyFromChildPosition;
        if (len > 0)
        {
            System.arraycopy(copyFrom, getKeyEnd(copyFrom) + copyFromChildPosition, buildChildren, buildChildPosition, len);
            copyFromChildPosition = upToChildPosition;
            buildChildPosition += len;
        }
    }

    // adds a new and unexpected child to the builder - called by children that overflow
    private void addExtraChild(Object[] child, Object upperBound)
    {
        ensureRoom(buildKeyPosition + 1);
        buildKeys[buildKeyPosition++] = upperBound;
        buildChildren[buildChildPosition++] = child;
    }

    // adds a replacement expected child to the builder - called by children prior to ascending
    private void finishChild(Object[] child)
    {
        buildChildren[buildChildPosition++] = child;
        copyFromChildPosition++;
    }

    // checks if we can add the requested keys+children to the builder, and if not we spill-over into our parent
    private void ensureRoom(int nextBuildKeyPosition)
    {
        if (nextBuildKeyPosition < MAX_KEYS)
            return;

        // flush even number of items so we don't waste leaf space repeatedly
        Object[] flushUp = buildFromRange(0, FAN_FACTOR, isLeaf(copyFrom), true);
        ensureParent().addExtraChild(flushUp, buildKeys[FAN_FACTOR]);
        int size = FAN_FACTOR + 1;
        assert size <= buildKeyPosition : buildKeyPosition + "," + nextBuildKeyPosition;
        System.arraycopy(buildKeys, size, buildKeys, 0, buildKeyPosition - size);
        buildKeyPosition -= size;
        maxBuildKeyPosition = buildKeys.length;
        if (buildChildPosition > 0)
        {
            System.arraycopy(buildChildren, size, buildChildren, 0, buildChildPosition - size);
            buildChildPosition -= size;
        }
    }

    // builds and returns a node from the buffered objects in the given range
    private Object[] buildFromRange(int offset, int keyLength, boolean isLeaf, boolean isExtra)
    {
        // if keyLength is 0, we didn't copy anything from the original, which means we didn't
        // modify any of the range owned by it, so can simply return it as is
        if (keyLength == 0)
            return copyFrom;

        Object[] a;
        if (isLeaf)
        {
            a = new Object[keyLength | 1];
            System.arraycopy(buildKeys, offset, a, 0, keyLength);
        }
        else
        {
            a = new Object[2 + (keyLength * 2)];
            System.arraycopy(buildKeys, offset, a, 0, keyLength);
            System.arraycopy(buildChildren, offset, a, keyLength, keyLength + 1);

            // calculate the indexOffsets of each key in this node, within the sub-tree rooted at this node
            int[] indexOffsets = new int[keyLength + 1];
            int size = BTree.size((Object[]) a[keyLength]);
            for (int i = 0 ; i < keyLength ; i++)
            {
                indexOffsets[i] = size;
                size += 1 + BTree.size((Object[]) a[keyLength + 1 + i]);
            }
            indexOffsets[keyLength] = size;
            a[a.length - 1] = indexOffsets;
        }
        if (isExtra)
            updateFunction.allocated(ObjectSizes.sizeOfArray(a));
        else if (a.length != copyFrom.length)
            updateFunction.allocated(ObjectSizes.sizeOfArray(a) -
                                     (copyFrom.length == 0 ? 0 : ObjectSizes.sizeOfArray(copyFrom)));
        return a;
    }

    // checks if there is an initialised parent, and if not creates/initialises one and returns it.
    // different to ensureChild, as we initialise here instead of caller, as parents in general should
    // already be initialised, and only aren't in the case where we are overflowing the original root node
    private NodeBuilder ensureParent()
    {
        if (parent == null)
        {
            parent = new NodeBuilder();
            parent.child = this;
        }
        if (parent.upperBound == null)
            parent.reset(EMPTY_BRANCH, upperBound, updateFunction, comparator);
        return parent;
    }

    // ensures a child level exists and returns it
    NodeBuilder ensureChild()
    {
        if (child == null)
        {
            child = new NodeBuilder();
            child.parent = this;
        }
        return child;
    }
}
