package net.onrc.onos.apps.sdnip;

import java.util.Iterator;
import java.util.NoSuchElementException;

/**
 * Implements a patricia tree. See {@link IPatriciaTree} for a description of
 * how the tree works and its usage.
 *
 * @param <V> the type of objects that will be stored in the tree
 */
public class PatriciaTree<V> implements IPatriciaTree<V> {
    private final byte[] maskBits = {(byte) 0x00, (byte) 0x80, (byte) 0xc0, (byte) 0xe0, (byte) 0xf0,
            (byte) 0xf8, (byte) 0xfc, (byte) 0xfe, (byte) 0xff};

    private final int maxPrefixLength;

    private Node top;

    /**
     * Class constructor which takes the maximum length of strings that can be
     * stored in the tree. This is used as a sanity check to prevent
     * excessively long strings from being added, as this could slow down
     * lookups.
     *
     * @param maxPrefixLength the maximum length of prefixes
     */
    public PatriciaTree(int maxPrefixLength) {
        this.maxPrefixLength = maxPrefixLength;
    }

    @Override
    public V put(Prefix prefix, V value) {
        synchronized (this) {
            if (prefix == null || value == null) {
                throw new IllegalArgumentException("Null argument");
            }

            if (prefix.getPrefixLength() > maxPrefixLength) {
                throw new IllegalArgumentException(String.format(
                        "Prefix length %d is greater than max prefix length %d",
                        prefix.getPrefixLength(), maxPrefixLength));
            }

            Node node = top;
            Node match = null;

            while (node != null
                    && node.prefix.getPrefixLength() <= prefix.getPrefixLength()
                    && checkKeyMatch(node.prefix.getAddress(),
                            node.prefix.getPrefixLength(),
                            prefix.getAddress(),
                            prefix.getPrefixLength())) {
                if (node.prefix.getPrefixLength() == prefix.getPrefixLength()) {
                    /*
                     * Prefix is already in tree. This may be an aggregate node, in which case
                     * we are inserting a new prefix, or it could be an actual node, in which
                     * case we are inserting a new nexthop for the prefix and should return
                     * the old nexthop.
                     */
                    V oldValue = node.value;
                    node.value = value;
                    return oldValue;
                }

                match = node;

                if (checkBit(prefix.getAddress(), node.prefix.getPrefixLength())) {
                    node = node.right;
                } else {
                    node = node.left;
                }
            }

            Node add = null;

            if (node == null) {
                //add = new Node(p, r);
                add = new Node(prefix);
                add.value = value;

                if (match == null) {
                    top = add;
                } else {
                    linkNodes(match, add);
                }
            } else {
                add = findCommonNode(node, prefix.getAddress(), prefix.getPrefixLength());

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

                if (add.prefix.getPrefixLength() == prefix.getPrefixLength()) {
                    add.value = value;
                } else {
                    match = add;

                    //add = new Node(p, r);
                    add = new Node(prefix);
                    add.value = value;
                    linkNodes(match, add);
                }
            }

            //If we added a new Node, there was no previous mapping
            return null;
            //return addReference(add);
        }
    }

    /*exact match*/
    @Override
    public V lookup(Prefix prefix) {
        synchronized (this) {
            if (prefix.getPrefixLength() > maxPrefixLength) {
                return null;
            }

            /*
            Node node = top;

            while (node != null
                    && node.prefix.getPrefixLength() <= p.getPrefixLength()
                    && key_match(node.prefix.getAddress(), node.prefix.getPrefixLength(), p.getAddress(), p.getPrefixLength()) == true) {
                if (node.prefix.getPrefixLength() == p.getPrefixLength()) {
                    //return addReference(node);
                    return node.rib;
                }

                if (bit_check(p.getAddress(), node.prefix.getPrefixLength()) == true) {
                    node = node.right;
                } else {
                    node = node.left;
                }
            }
            */

            Node node = findNode(prefix);

            return node == null ? null : node.value;
        }
    }

    // closest containing prefix
    @Override
    public V match(Prefix prefix) {
        //TODO
        synchronized (this) {
            if (prefix.getPrefixLength() > maxPrefixLength) {
                return null;
            }

            Node closestNode = findClosestNode(prefix);

            return closestNode == null ? null : closestNode.value;
        }
    }

    @Override
    public boolean remove(Prefix prefix, V value) {
        synchronized (this) {
            if (prefix == null || value == null) {
                return false;
            }

            Node node = findNode(prefix);

            if (node == null || node.isAggregate() || !node.value.equals(value)) {
                //Given <prefix, nexthop> mapping is not in the tree
                return false;
            }

            if (node.left != null && node.right != null) {
                //Remove the RibEntry entry and leave this node as an aggregate node
                //In the future, maybe we should re-evaluate what the aggregate prefix should be?
                //It shouldn't necessarily stay the same.
                //More complicated if the above prefix is also aggregate.
                node.value = null;
                return true;
            }

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

            Node 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;
            }

            /*
             * TODO not sure what to do here. I think this is lazily deleting aggregate nodes,
             * notice that it used to do nothing if it detected both children were not null earlier.
             * But here, what we really should do is reevaluate the aggregate prefix of the parent
             * node (if it is indeed an aggregate). Because at the moment, no aggregate node will ever
             * be removed. BUT, I don't actually think this presents a correctness problem, at
             * least from an external point of view.
             */
            //if (parent != null && parent.refCount == 0) {
            //node_remove(parent);
            //}

            return true;
        }
    }

    @Override
    public Iterator<Entry<V>> iterator() {
        return new PatriciaTreeIterator(top);
    }

    private Node findNode(Prefix prefix) {
        Node node = top;

        while (node != null
                && node.prefix.getPrefixLength() <= prefix.getPrefixLength()
                && checkKeyMatch(node.prefix.getAddress(),
                        node.prefix.getPrefixLength(),
                        prefix.getAddress(), prefix.getPrefixLength())) {
            if (node.prefix.getPrefixLength() == prefix.getPrefixLength()) {
                //return addReference(node);
                return node;
            }

            if (checkBit(prefix.getAddress(), node.prefix.getPrefixLength())) {
                node = node.right;
            } else {
                node = node.left;
            }
        }

        return null;
    }

    private Node findClosestNode(Prefix prefix) {
        Node node = top;
        Node match = null;

        while (node != null
                && node.prefix.getPrefixLength() <= prefix.getPrefixLength()
                && checkKeyMatch(node.prefix.getAddress(),
                        node.prefix.getPrefixLength(),
                        prefix.getAddress(), prefix.getPrefixLength())) {
            if (!node.isAggregate()) {
                match = node;
            }

            if (checkBit(prefix.getAddress(), node.prefix.getPrefixLength())) {
                node = node.right;
            } else {
                node = node.left;
            }
        }

        return match;
    }

    /*
     * Receives a 1-based bit index
     * Returns a 1-based byte index
     * eg. (0 => 1), 1 => 1, 8 => 1, 9 => 2, 17 => 3
     */
    private int getByteContainingBit(int bitNumber) {
        return Math.max((bitNumber + 7) / 8, 1);
    }

    private boolean checkKeyMatch(byte[] key1, int key1Length, byte[] key2, int key2Length) {
        //int offset;
        //int shift;

        if (key1Length > key2Length) {
            return false;
        }

        int offset = (Math.min(key1Length, key2Length)) / 8;
        int shift = (Math.min(key1Length, key2Length)) % 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 checkBit(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 linkNodes(Node node, Node add) {
        boolean bit = checkBit(add.prefix.getAddress(), node.prefix.getPrefixLength());

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

    private Node findCommonNode(Node node, byte[] key, int keyBits) {
        int i;
        int limit = Math.min(node.prefix.getPrefixLength(), keyBits) / 8;

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

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

        if (commonLen != keyBits) {
            byte diff = (byte) (node.prefix.getAddress()[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++;
            }
        }

        //Creating a new Prefix with a prefix length of common_len
        //Bits are copied from node's up until the common_len'th bit
        //RibEntry is null, because this is an aggregate prefix - it's not
        //actually been added to the tree.

        byte[] newPrefix = new byte[getByteContainingBit(maxPrefixLength)];

        int j;
        for (j = 0; j < i; j++) {
            newPrefix[j] = node.prefix.getAddress()[j];
        }

        if (boundary != 0) {
            newPrefix[j] =
                    (byte) (node.prefix.getAddress()[j] & maskBits[commonLen % 8]);
        }

        //return new Node(new Prefix(newPrefix, common_len), null);
        return new Node(new Prefix(newPrefix, commonLen));
        //return add;
    }

    private class Node {
        public Node parent;
        public Node left;
        public Node right;

        public final Prefix prefix;
        public V value;

        //public Node(Prefix p, RibEntry r) {
        //      this.prefix = p;
        //      this.rib = r;
        //}
        public Node(Prefix p) {
            this.prefix = p;
        }

        public boolean isAggregate() {
            return value == null;
        }

        public Entry<V> getEntry() {
            return new PatriciaTreeEntry(prefix, value);
        }
    }

    private class PatriciaTreeEntry implements Entry<V> {
        private final Prefix prefix;
        private final V value;

        public PatriciaTreeEntry(Prefix prefix, V value) {
            this.prefix = prefix;
            this.value = value;
        }

        @Override
        public Prefix getPrefix() {
            return prefix;
        }

        @Override
        public V getValue() {
            return value;
        }
    }

    private class PatriciaTreeIterator implements Iterator<Entry<V>> {
        private Node current;
        private boolean started; // initialized to false

        public PatriciaTreeIterator(Node start) {
            current = start;

            //If the start is an aggregate node fast forward to find the next valid node
            if (current != null && current.isAggregate()) {
                current = findNext(current);
            }
        }

        @Override
        public boolean hasNext() {
            if (current == null) {
                return false;
            }

            if (!started) {
                return true;
            }

            return findNext(current) != null;
        }

        @Override
        public Entry<V> next() {
            if (current == null) {
                throw new NoSuchElementException();
            }

            if (!started) {
                started = true;
                return current.getEntry();
            }

            current = findNext(current);
            if (current == null) {
                throw new NoSuchElementException();
            }

            return current.getEntry();
        }

        @Override
        public void remove() {
            // TODO This could be implemented, if it were needed
            throw new NoSuchElementException();
        }

        private Node findNext(Node node) {
            Node next = null;

            if (node.left != null) {
                next = node.left;
                //addReference(next);
                //delReference(node);
                //return next;
            } else if (node.right != null) {
                next = node.right;
                //addReference(next);
                //delReference(node);
                //return next;
            } else {
                //Node 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;
                        break;
                    }
                    node = node.parent;
                }
            }

            if (next == null) {
                return null;
            }

            //If the node doesn't have a value, it's not an actual node, it's an artifically
            //inserted aggregate node. We don't want to return these to the user.
            if (next.isAggregate()) {
                return findNext(next);
            }

            return next;
        }
    }
}
