package net.onrc.onos.apps.sdnip;

/*
 * TODO This Ptree needs to be refactored if we're going to use it permenantly.
 *
 * The biggest problem is it leaks PTreeNode references - these need to stay within
 * the Ptree as they contain data fundamental to the structure of the tree.
 * You should put RIB entries in and get RIB entries out.
 * Also we need to get rid of the referencing scheme to determine when to delete nodes.
 * Deletes should be explicit, and there's no need to keep track of references if
 * we don't leak them out the the Ptree.
 */
public class Ptree {
    private int maxKeyBits;
    private int maxKeyOctets;
    //private int refCount;
    private PtreeNode top;
    private byte[] maskBits =
        {(byte) 0x00, (byte) 0x80, (byte) 0xc0, (byte) 0xe0, (byte) 0xf0,
         (byte) 0xf8, (byte) 0xfc, (byte) 0xfe, (byte) 0xff};

    public Ptree(int maxKeyBits) {
        this.maxKeyBits = maxKeyBits;
        maxKeyOctets = bitToOctet(maxKeyBits);
        //refCount = 0;
    }

    public synchronized PtreeNode acquire(byte[] key) {
        return acquire(key, maxKeyBits);
    }

    public synchronized PtreeNode acquire(byte[] key, int keyBits) {
        if (keyBits > maxKeyBits) {
            return null;
        }

        PtreeNode node = top;
        PtreeNode match = null;

        while (node != null
                && node.keyBits <= keyBits
                && keyMatch(node.key, node.keyBits, key, keyBits)) {
            if (node.keyBits == keyBits) {
                return addReference(node);
            }

            match = node;

            if (bitCheck(key, node.keyBits)) {
                node = node.right;
            } else {
                node = node.left;
            }
        }

        PtreeNode add = null;

        if (node == null) {
            add = new PtreeNode(key, keyBits, maxKeyOctets);

            if (match != null) {
                nodeLink(match, add);
            } else {
                top = add;
            }
        } else {
            add = nodeCommon(node, key, keyBits);

            if (match != null) {
                nodeLink(match, add);
            } else {
                top = add;
            }
            nodeLink(add, node);

            if (add.keyBits != keyBits) {
                match = add;

                add = new PtreeNode(key, keyBits, maxKeyOctets);
                nodeLink(match, add);
            }
        }

        return addReference(add);
    }

    public synchronized PtreeNode lookup(byte[] key, int keyBits) {
        if (keyBits > maxKeyBits) {
            return null;
        }

        PtreeNode node = top;

        while (node != null
                && node.keyBits <= keyBits
                && keyMatch(node.key, node.keyBits, key, keyBits)) {
            if (node.keyBits == keyBits) {
                return addReference(node);
            }

            if (bitCheck(key, node.keyBits)) {
                node = node.right;
            } else {
                node = node.left;
            }
        }
        return null;
    }

    public synchronized PtreeNode match(byte[] key, int keyBits) {
        if (keyBits > maxKeyBits) {
            return null;
        }
        PtreeNode node = top;
        PtreeNode matched = null;

        if (node != null) {

            while (node != null
                    && node.keyBits <= keyBits
                    && keyMatch(node.key, node.keyBits, key, keyBits)) {
                matched = node;

                if (bitCheck(key, node.keyBits)) {
                    node = node.right;
                } else {
                    node = node.left;
                }
            }
        }

        if (matched != null) {
            return addReference(matched);
        }

        return null;
    }

    public synchronized PtreeNode begin() {
        if (top == null) {
            return null;
        }
        return addReference(top);
    }

    public synchronized PtreeNode next(PtreeNode node) {
        PtreeNode next;

        if (node.left != null) {
            next = node.left;
            addReference(next);
            delReference(node);
            return next;
        }
        if (node.right != null) {
            next = node.right;
            addReference(next);
            delReference(node);
            return next;
        }

        PtreeNode start = node;
        while (node.parent != null) {
            if (node.parent.left == node && node.parent.right != null) {
                next = node.parent.right;
                addReference(next);
                delReference(start);
                return next;
            }
            node = node.parent;
        }

        delReference(start);

        return null;
    }

    public static int bitToOctet(int keyBits) {
        return Math.max((keyBits + 7) / 8, 1);
    }

    private PtreeNode addReference(PtreeNode node) {
        node.refCount++;
        return node;
    }

    public synchronized void delReference(PtreeNode node) {
        if (node.refCount > 0) {
            node.refCount--;
        }
        if (node.refCount == 0) {
            nodeRemove(node);
        }
    }

    private boolean keyMatch(byte[] key1, int key1Len, byte[] key2, int key2Len) {
        int offset;
        int shift;

        if (key1Len > key2Len) {
            return false;
        }

        offset = (Math.min(key1Len, key2Len)) / 8;
        shift = (Math.min(key1Len, key2Len)) % 8;

        if (shift != 0) {
            if ((maskBits[shift] & (key1[offset] ^ key2[offset])) != 0) {
                return false;
            }
        }

        while (offset != 0) {
            offset--;
            if (key1[offset] != key2[offset]) {
                return false;
            }
        }
        return true;
    }

    private boolean bitCheck(byte[] key, int keyBits) {
        int offset = keyBits / 8;
        int shift = 7 - (keyBits % 8);
        int bit = key[offset] & 0xff;

        bit >>= shift;

        return ((bit & 1) == 1);
    }

    private void nodeLink(PtreeNode node, PtreeNode add) {
        boolean bit = bitCheck(add.key, node.keyBits);

        if (bit) {
            node.right = add;
        } else {
            node.left = add;
        }
        add.parent = node;
    }

    private PtreeNode nodeCommon(PtreeNode node, byte[] key, int keyBits) {
        int i;
        int limit = Math.min(node.keyBits, keyBits) / 8;

        for (i = 0; i < limit; i++) {
            if (node.key[i] != key[i]) {
                break;
            }
        }

        int commonLen = i * 8;
        int boundary = 0;

        if (commonLen != keyBits) {
            byte diff = (byte) (node.key[i] ^ key[i]);
            byte mask = (byte) 0x80;
            int shiftMask = 0;

            while (commonLen < keyBits && ((mask & diff) == 0)) {
                boundary = 1;

                shiftMask = (mask & 0xff);
                shiftMask >>= 1;
                mask = (byte) shiftMask;

                commonLen++;
            }
        }

        PtreeNode add = new PtreeNode(null, commonLen, maxKeyOctets);

        int j;
        for (j = 0; j < i; j++) {
            add.key[j] = node.key[j];
        }

        if (boundary != 0) {
            add.key[j] = (byte) (node.key[j] & maskBits[add.keyBits % 8]);
        }

        return add;
    }

    private void nodeRemove(PtreeNode node) {
        PtreeNode child;
        PtreeNode parent;

        if (node.left != null && node.right != null) {
            return;
        }

        if (node.left != null) {
            child = node.left;
        } else {
            child = node.right;
        }

        parent = node.parent;

        if (child != null) {
            child.parent = parent;
        }

        if (parent != null) {
            if (parent.left == node) {
                parent.left = child;
            } else {
                parent.right = child;
            }
        } else {
            top = child;
        }

        if (parent != null && parent.refCount == 0) {
            nodeRemove(parent);
        }
    }
}
