package net.onrc.onos.apps.sdnip;

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

import com.google.common.net.InetAddresses;

/**
 * Represents an IP prefix.
 * <p/>
 * It is made up of an IP address and a number of significant bits in the
 * prefix (i.e. the size of the network part of the address).
 * E.g. {@code 192.168.0.0/16}.
 * <p/>
 * Currently only IPv4 is supported, so a prefix length can be up to 32 bits.
 */
public class Prefix {
    /**
     * The length of addresses this class can represent prefixes of, in bytes.
     */
    public static final int ADDRESS_LENGTH = 4;

    private final int prefixLength;
    private final byte[] address;

    // For verifying the arguments and pretty printing
    private final InetAddress inetAddress;

    /**
     * Class constructor, taking an byte array representing and IP address and
     * a prefix length.
     * <p/>
     * The valid values for addr and prefixLength are bounded by
     * {@link #ADDRESS_LENGTH}.
     * <p/>
     * A valid addr array satisfies
     * {@code addr.length == }{@value #ADDRESS_LENGTH}.
     * <p/>
     * A valid prefixLength satisfies
     * {@code (prefixLength > 0 && prefixLength <=} {@link Byte#SIZE}
     * {@code * }{@value #ADDRESS_LENGTH}{@code )}.
     *
     * @param addr a byte array representing the address
     * @param prefixLength length of the prefix of the specified address
     */
    public Prefix(byte[] addr, int prefixLength) {
        if (addr == null || addr.length != ADDRESS_LENGTH ||
                prefixLength < 0 || prefixLength > ADDRESS_LENGTH * Byte.SIZE) {
            throw new IllegalArgumentException();
        }

        address = canonicalizeAddress(addr, prefixLength);
        this.prefixLength = prefixLength;

        try {
            inetAddress = InetAddress.getByAddress(address);
        } catch (UnknownHostException e) {
            throw new IllegalArgumentException("Couldn't parse IP address", e);
        }
    }

    /**
     * Class constructor, taking an address in String format and a prefix
     * length. The address must be in dot-notation form (e.g. {@code 0.0.0.0}).
     *
     * @param strAddress a String representing the address
     * @param prefixLength length of the prefix of the specified address
     */
    public Prefix(String strAddress, int prefixLength) {
        byte[] addr = null;
        addr = InetAddresses.forString(strAddress).getAddress();

        if (addr == null || addr.length != ADDRESS_LENGTH ||
                prefixLength < 0 || prefixLength > ADDRESS_LENGTH * Byte.SIZE) {
            throw new IllegalArgumentException();
        }

        address = canonicalizeAddress(addr, prefixLength);
        this.prefixLength = prefixLength;

        try {
            inetAddress = InetAddress.getByAddress(address);
        } catch (UnknownHostException e) {
            throw new IllegalArgumentException("Couldn't parse IP address", e);
        }
    }

    private byte[] canonicalizeAddress(byte[] addressValue,
                                       int prefixLengthValue) {
        byte[] result = new byte[addressValue.length];

        if (prefixLengthValue == 0) {
            for (int i = 0; i < ADDRESS_LENGTH; i++) {
                result[i] = 0;
            }

            return result;
        }

        result = Arrays.copyOf(addressValue, addressValue.length);

        //Set all bytes after the end of the prefix to 0
        int lastByteIndex = (prefixLengthValue - 1) / Byte.SIZE;
        for (int i = lastByteIndex; i < ADDRESS_LENGTH; i++) {
            result[i] = 0;
        }

        byte lastByte = addressValue[lastByteIndex];
        byte mask = 0;
        byte msb = (byte) 0x80;
        int lastBit = (prefixLengthValue - 1) % Byte.SIZE;
        for (int i = 0; i < Byte.SIZE; i++) {
            if (i <= lastBit) {
                mask |= (msb >> i);
            }
        }

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

        return result;
    }

    /**
     * Gets the length of the prefix of the address.
     *
     * @return the prefix length
     */
    public int getPrefixLength() {
        return prefixLength;
    }

    /**
     * Gets the address.
     *
     * @return the address as a byte array
     */
    public byte[] getAddress() {
        return Arrays.copyOf(address, address.length);
    }

    @Override
    public boolean equals(Object other) {
        if (!(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;
    }

    /**
     * Print the prefix to a String showing the bits of the address.
     *
     * @return the bit-string of the prefix
     */
    public String printAsBits() {
        StringBuilder result = new StringBuilder();
        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.append(((b & mask) == 0) ? "0" : "1");
                if (i * Byte.SIZE + j == prefixLength - 1) {
                    return result.toString();
                }
            }
            result.append(' ');
        }
        return result.substring(0, result.length() - 1);
    }
}
