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_BYTES = 4;

    /**
     * The length of addresses this class can represent prefixes of, in bits.
     */
    public static final int MAX_PREFIX_LENGTH = Byte.SIZE * ADDRESS_LENGTH_BYTES;

    public static final int MIN_PREFIX_LENGTH = 0;

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

    // 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_BYTES}.
     * <p/>
     * A valid addr array satisfies
     * {@code addr.length == }{@value #ADDRESS_LENGTH_BYTES}.
     * <p/>
     * A valid prefixLength satisfies
     * {@code (prefixLength >= 0 && prefixLength <=} {@link Byte#SIZE}
     * {@code * }{@value #ADDRESS_LENGTH_BYTES}{@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_BYTES ||
                prefixLength < MIN_PREFIX_LENGTH ||
                prefixLength > MAX_PREFIX_LENGTH) {
            throw new IllegalArgumentException();
        }

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

        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_BYTES ||
                prefixLength < MIN_PREFIX_LENGTH ||
                prefixLength > MAX_PREFIX_LENGTH) {
            throw new IllegalArgumentException();
        }

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

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

    /**
     * This method takes a byte array passed in by the user and ensures it
     * conforms to the format we want. The byte array can contain anything,
     * but only some of the bits are significant. The bits after
     * prefixLengthValue are not significant, and this method will zero them
     * out in order to ensure there is a canonical representation for each
     * prefix. This simplifies the equals and hashcode methods, because once we
     * have a canonical byte array representation we can simply compare byte
     * arrays to test equality.
     *
     * @param addressValue the byte array to canonicalize
     * @param prefixLengthValue The length of the prefix. Bits up to and including
     * prefixLength are significant, bits following prefixLength are not
     * significant and will be zeroed out.
     * @return the canonicalized representation of the prefix
     */
    private byte[] canonicalizeAddress(byte[] addressValue,
                                       int prefixLengthValue) {
        byte[] result = new byte[addressValue.length];

        if (prefixLengthValue == 0) {
            for (int i = 0; i < ADDRESS_LENGTH_BYTES; 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_BYTES; 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;
    }

    /**
     * Creates the binary string representation of the prefix.
     * The strings length is equal to prefixLength.
     *
     * @return the binary string representation
     */
    private String createBinaryString() {
        if (prefixLength == 0) {
            return "";
        }

        StringBuilder result = new StringBuilder(prefixLength);
        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();
                }
            }
        }
        return result.toString();
    }

    /**
     * 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;
    }

    /**
     * Gets a binary string representation of the prefix.
     *
     * @return a binary string representation
     */
    public String toBinaryString() {
        return binaryString;
    }

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