package net.onrc.onos.apps.bgproute;

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

public class PatriciaTrie<V> implements IPatriciaTrie<V> {
    private final byte[] maskBits = {(byte) 0x00, (byte) 0x80, (byte) 0xc0, (byte) 0xe0, (byte) 0xf0,
            (byte) 0xf8, (byte) 0xfc, (byte) 0xfe, (byte) 0xff};

    private int maxPrefixLength;

    private Node top;

    public PatriciaTrie(int maxPrefixLength) {
        this.maxPrefixLength = maxPrefixLength;
    }

    @Override
    public synchronized V put(Prefix prefix, V value) {
        if (prefix == null || value == null) {
            throw new NullPointerException();
        }

        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()
                && key_match(node.prefix.getAddress(), node.prefix.getPrefixLength(), prefix.getAddress(), prefix.getPrefixLength()) == true) {
            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 (bit_check(prefix.getAddress(), node.prefix.getPrefixLength()) == true) {
                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) {
                node_link(match, add);
            } else {
                top = add;
            }
        } else {
            add = node_common(node, prefix.getAddress(), prefix.getPrefixLength());

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

            if (add.prefix.getPrefixLength() != prefix.getPrefixLength()) {
                match = add;

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

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

    /*exact match*/
    @Override
    public synchronized V lookup(Prefix prefix) {
        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 synchronized V match(Prefix prefix) {
        //TODO
        if (prefix.getPrefixLength() > maxPrefixLength) {
            return null;
        }

        Node closestNode = findClosestNode(prefix);

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

    @Override
    public synchronized boolean remove(Prefix prefix, V value) {
        Node child;
        Node parent;

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

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

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

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

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

            if (bit_check(prefix.getAddress(), node.prefix.getPrefixLength()) == true) {
                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()
                && key_match(node.prefix.getAddress(), node.prefix.getPrefixLength(), prefix.getAddress(), prefix.getPrefixLength()) == true) {
            if (!node.isAggregate()) {
                match = node;
            }

            if (bit_check(prefix.getAddress(), node.prefix.getPrefixLength()) == true) {
                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 key_match(byte[] key1, int key1_len, byte[] key2, int key2_len) {
        //int offset;
        //int shift;

        if (key1_len > key2_len) {
            return false;
        }

        int offset = (Math.min(key1_len, key2_len)) / 8;
        int shift = (Math.min(key1_len, key2_len)) % 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 bit_check(byte[] key, int key_bits) {
        int offset = key_bits / 8;
        int shift = 7 - (key_bits % 8);
        int bit = key[offset] & 0xff;

        bit >>= shift;

        if ((bit & 1) == 1) {
            return true;
        } else {
            return false;
        }
    }

    private void node_link(Node node, Node add) {
        boolean bit = bit_check(add.prefix.getAddress(), node.prefix.getPrefixLength());

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

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

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

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

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

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

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

                commonLen++;
            }
        }

        //Node add = new Node(null, common_len, maxKeyOctets);
        //if (add == null)
        //Another -ENOMEM;
        //return null;

        //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 trie.

        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 = null;
        public Node left = null;
        public Node right = null;

        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 PatriciaTrieEntry(prefix, value);
        }
    }

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

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

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

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

    private class PatriciaTrieIterator implements Iterator<Entry<V>> {

        private Node current;
        private boolean started = false;

        public PatriciaTrieIterator(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;
        }
    }
}
