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