package net.onrc.onos.apps.bgproute;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;

import com.google.common.net.InetAddresses;

public class Prefix {
	private final int MAX_BYTES = 4;
	
	private final int prefixLength;
	private final byte[] address;
	
	//For verifying the arguments and pretty printing
	private final InetAddress inetAddress;
	
	public Prefix(byte[] addr, int prefixLength) {
		if (addr == null || addr.length != MAX_BYTES || 
				prefixLength < 0 || prefixLength > MAX_BYTES * Byte.SIZE) {
			throw new IllegalArgumentException();
		}

		address = canonicalizeAddress(addr, prefixLength);
		this.prefixLength = prefixLength;
		
		try {
			inetAddress = InetAddress.getByAddress(address);
		} catch (UnknownHostException e) {
			throw new IllegalArgumentException();
		}
	}

	public Prefix(String strAddress, int prefixLength) {
		byte[] addr = null;
		addr = InetAddresses.forString(strAddress).getAddress();
				
		if (addr == null || addr.length != MAX_BYTES || 
				prefixLength < 0 || prefixLength > MAX_BYTES * Byte.SIZE) {
			throw new IllegalArgumentException();
		}
		
		address = canonicalizeAddress(addr, prefixLength);
		this.prefixLength = prefixLength;
		
		try {
			inetAddress = InetAddress.getByAddress(address);
		} catch (UnknownHostException e) {
			throw new IllegalArgumentException();
		}
	}
	
	private byte[] canonicalizeAddress(byte[] address, int prefixLength) {
		byte[] result = new byte[address.length];
		
		if (prefixLength == 0) {
			for (int i = 0; i < MAX_BYTES; i++) {
				result[i] = 0;
			}
			
			return result;
		}
		
		result = Arrays.copyOf(address, address.length);
		
		//Set all bytes after the end of the prefix to 0
		int lastByteIndex = (prefixLength - 1) / Byte.SIZE;
		for (int i = lastByteIndex; i < MAX_BYTES; i++) {
			result[i] = 0;
		}
		
		byte lastByte = address[lastByteIndex];
		byte mask = 0;
		byte msb = (byte) 0x80;
		int lastBit = (prefixLength - 1) % Byte.SIZE;
		for (int i = 0; i < Byte.SIZE; i++) {
			if (i <= lastBit) {
				mask |= (msb >> i);
			}
		}

		result[lastByteIndex] = (byte) (lastByte & mask);
		
		return result;
	}

	public int getPrefixLength() {
		return prefixLength;
	}
	
	public byte[] getAddress() {
		return address;
	}
	
	@Override
	public boolean equals(Object other) {
		if (other == null || !(other instanceof Prefix)) {
			return false;
		}
		
		Prefix otherPrefix = (Prefix) other;
		
		return (Arrays.equals(address, otherPrefix.address)) &&
				(prefixLength == otherPrefix.prefixLength);
	}
	
	@Override
	public int hashCode() {
		int hash = 17;
		hash = 31 * hash + prefixLength;
		hash = 31 * hash + Arrays.hashCode(address);
		return hash;
	}
	
	@Override
	public String toString() {
		return inetAddress.getHostAddress() + "/" + prefixLength;
	}
	
	public String printAsBits() {
		String result = "";
		for (int i = 0; i < address.length; i++) {
			byte b = address[i];
			for (int j = 0; j < Byte.SIZE; j++) {
				byte mask = (byte) (0x80 >>> j);
				result += ((b & mask) == 0)? "0" : "1";
				if (i*Byte.SIZE+j == prefixLength-1) {
					return result;
				}
			}
			result += " ";
		}
		return result.substring(0, result.length() - 1);
	}
}
