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 (add == null) {
				//I think this is -ENOMEM?
				//return null;
			}				
			
			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 common_len = i * 8;
		int boundary = 0;

		if (common_len != key_bits) {
			byte diff = (byte)(node.prefix.getAddress()[i] ^ key[i]);
			byte mask = (byte)0x80;
			int shift_mask = 0;
			
			while (common_len < key_bits && ((mask & diff) == 0)) {
				boundary = 1;

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

				common_len++;
			}
		}
		
		//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[common_len % 8]);
		
		//return new Node(new Prefix(newPrefix, common_len), null);
		return new Node(new Prefix(newPrefix, common_len));
		//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;
		}
	}
}
