package net.floodlightcontroller.bgproute;

public class Ptree {
	int maxKeyBits;
	int maxKeyOctets;
	int refCount;
	PtreeNode top;
	byte maskBits[] = { (byte)0x00, (byte)0x80, (byte)0xc0, (byte)0xe0, (byte)0xf0, (byte)0xf8, (byte)0xfc, (byte)0xfe, (byte)0xff };
	
	// Constructor.
	Ptree(int max_key_bits) {
		maxKeyBits = max_key_bits;
		maxKeyOctets = bit_to_octet(max_key_bits); 
		refCount = 0;
	}
	
	public PtreeNode acquire(byte [] key) {
		return acquire(key, maxKeyBits);
	}
	
	public PtreeNode acquire(byte [] key, int key_bits) {
		if (key_bits > maxKeyBits) {
			return null;
		}
		
		PtreeNode node = top;
		PtreeNode match = null;
		
		while (node != null
				&& node.keyBits <= key_bits
				&& key_match(node.key, node.keyBits, key, key_bits) == true) {
		    if (node.keyBits == key_bits) {
				return addReference(node);
			}

			match = node;
			
			if (bit_check(key, node.keyBits) == true) {
				node = node.right;
			} else {
				node = node.left;
			}
		}

		PtreeNode add = null;
		
		if (node == null) {
			add = new PtreeNode(key, key_bits, maxKeyOctets);
			
			if (match != null) {
				node_link(match, add);
			} else {
				top = add;
			}
		} else {
			add = node_common(node, key, key_bits);
			if (add == null) {
				return null;
			}				
			
			if (match != null) {
				node_link(match, add);
			} else {
				top = add;
			}
			node_link(add, node);
			
			if (add.keyBits != key_bits) {
				match = add;
				
				add = new PtreeNode(key, key_bits, maxKeyOctets);
				node_link(match, add);
			}
		}
		
		return addReference(add);
	}

	public PtreeNode lookup(byte [] key, int key_bits) {
		if (key_bits > maxKeyBits) {
			return null;
		}
		
		PtreeNode node = top;
		
		while (node != null
				&& node.keyBits <= key_bits
				&& key_match(node.key, node.keyBits, key, key_bits) == true) {
			if (node.keyBits == key_bits) {
				return addReference(node);
			}
			
			if (bit_check(key, node.keyBits) == true) {
				node = node.right;
			} else {
				node = node.left;
			}
		}
		return null;
	}
	
	public PtreeNode match(byte [] key, int key_bits) {
		if (key_bits > maxKeyBits) {
			return null;
		}
		PtreeNode node = top;
		PtreeNode matched = null;

		if(node!=null)
		
		while (node != null
				&& node.keyBits <= key_bits
				&& key_match(node.key, node.keyBits, key, key_bits) == true) {
			matched = node;
			
			if (bit_check(key, node.keyBits) == true) {
				node = node.right;
			} else {
				node = node.left;
			}
		}
		
		if (matched != null) {
			return addReference(matched);
		}
		
		return null;
	}
	
	public PtreeNode begin() {
		if (top == null) {
			return null;
		}
		return addReference(top);
	}
	
	public 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;
	}

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

	private PtreeNode addReference(PtreeNode node) {
		node.refCount++;
		return node;
	}
	
	public void delReference(PtreeNode node) {
		if (node.refCount > 0) {
			node.refCount--;
		}
		if (node.refCount == 0) {
			node_remove(node);
		}
	}
	
	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;
		}
		
		offset = (Math.min(key1_len, key2_len)) / 8;
		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(PtreeNode node, PtreeNode add) {
		boolean bit = bit_check(add.key, node.keyBits);
		
		if (bit == true) {
			node.right = add;
		} else {
			node.left = add;
		}
		add.parent = node;
	}
	
	@SuppressWarnings("unused")
    private PtreeNode node_common(PtreeNode node, byte [] key, int key_bits) {
		int i;
		int limit = Math.min(node.keyBits, key_bits) / 8;

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

		if (common_len != key_bits) {
			byte diff = (byte)(node.key[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++;
			}
		}
		
		PtreeNode add = new PtreeNode(null, common_len, maxKeyOctets);
		if (add == null)
			return null;
		
		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;
	}
	//add by linpp
	private void clear() {
	
	}
	
	private void node_remove(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) {
			node_remove(parent);
		}
	}
}
