package org.onlab.packet;

import java.util.Arrays;

/**
 * A class representing an IPv4 address.
 */
public final class IpAddress {

    //IP Versions
    public enum Version { INET, INET6 };

    //lengths of address, in bytes
    public static final int INET_LEN = 4;
    public static final int INET6_LEN = 16;

    //maximum CIDR value
    public static final int MAX_INET_MASK = 32;
    public static final int DEFAULT_MASK = 0;

    /**
     * Default value indicating an unspecified address.
     */
    public static final byte [] ANY = new byte [] {0, 0, 0, 0};

    protected Version version;

    protected byte[] octets;
    protected int netmask;

    private IpAddress(Version ver, byte[] octets, int netmask) {
        this.version = ver;
        this.octets = Arrays.copyOf(octets, INET_LEN);
        this.netmask = netmask;
    }

    private IpAddress(Version ver, byte[] octets) {
        this.version = ver;
        this.octets = Arrays.copyOf(octets, INET_LEN);
        this.netmask = DEFAULT_MASK;
    }

    /**
     * Converts a byte array into an IP address.
     *
     * @param address a byte array
     * @return an IP address
     */
    public static IpAddress valueOf(byte [] address) {
        return new IpAddress(Version.INET, address);
    }

    /**
     * Converts a byte array into an IP address.
     *
     * @param address a byte array
     * @param netmask the CIDR value subnet mask
     * @return an IP address
     */
    public static IpAddress valueOf(byte [] address, int netmask) {
        return new IpAddress(Version.INET, address, netmask);
    }

    /**
     * Helper to convert an integer into a byte array.
     *
     * @param address the integer to convert
     * @return a byte array
     */
    private static byte [] bytes(int address) {
        byte [] bytes = new byte [INET_LEN];
        for (int i = 0; i < INET_LEN; i++) {
            bytes[i] = (byte) ((address >> (INET_LEN - (i + 1)) * 8) & 0xff);
        }

        return bytes;
    }

    /**
     * Converts an integer into an IPv4 address.
     *
     * @param address an integer representing an IP value
     * @return an IP address
     */
    public static IpAddress valueOf(int address) {
        return new IpAddress(Version.INET, bytes(address));
    }

    /**
     * Converts an integer into an IPv4 address.
     *
     * @param address an integer representing an IP value
     * @param netmask the CIDR value subnet mask
     * @return an IP address
     */
    public static IpAddress valueOf(int address, int netmask) {
        return new IpAddress(Version.INET, bytes(address), netmask);
    }

    /**
     * Converts a dotted-decimal string (x.x.x.x) into an IPv4 address. The
     * string can also be in CIDR (slash) notation.
     *
     * @param address a IP address in string form, e.g. "10.0.0.1", "10.0.0.1/24"
     * @return an IP address
     */
    public static IpAddress valueOf(String address) {

        final String [] parts = address.split("\\/");
        if (parts.length > 2) {
            throw new IllegalArgumentException("Malformed IP address string; "
                    + "Addres must take form \"x.x.x.x\" or \"x.x.x.x/y\"");
        }

        int mask = DEFAULT_MASK;
        if (parts.length == 2) {
            mask = Integer.valueOf(parts[1]);
            if (mask > MAX_INET_MASK) {
                throw new IllegalArgumentException(
                        "Value of subnet mask cannot exceed "
                                + MAX_INET_MASK);
            }
        }

        final String [] net = parts[0].split("\\.");
        if (net.length != INET_LEN) {
            throw new IllegalArgumentException("Malformed IP address string; "
                    + "Addres must have four decimal values separated by dots (.)");
        }
        final byte [] bytes = new byte[INET_LEN];
        for (int i = 0; i < INET_LEN; i++) {
            bytes[i] = (byte) Short.parseShort(net[i], 10);
        }
        return new IpAddress(Version.INET, bytes, mask);
    }

    /**
     * Returns the IP version of this address.
     *
     * @return the version
     */
    public Version version() {
        return this.version;
    }

    /**
     * Returns the IP address as a byte array.
     *
     * @return a byte array
     */
    public byte [] toOctets() {
        return Arrays.copyOf(this.octets, INET_LEN);
    }

    /**
     * Returns the integral value of this IP address.
     *
     * @return the IP address's value as an integer
     */
    public int toInt() {
        int address = 0;
        for (int i = 0; i < INET_LEN; i++) {
            address |= octets[i] << ((INET_LEN - (i + 1)) * 8);
        }
        return address;
    }

    /**
     * Helper for computing the mask value from CIDR.
     *
     * @return an integer bitmask
     */
    private int mask() {
        int shift = MAX_INET_MASK - this.netmask;
        return ((Integer.MAX_VALUE >>> (shift - 1)) << shift);
    }

    /**
     * Returns the subnet mask in IpAddress form. The netmask value for
     * the returned IpAddress is 0, as the address itself is a mask.
     *
     * @return the subnet mask
     */
    public IpAddress netmask() {
        return new IpAddress(Version.INET, bytes(mask()));
    }

    /**
     * Returns the network portion of this address as an IpAddress.
     * The netmask of the returned IpAddress is the current mask. If this
     * address doesn't have a mask, this returns an all-0 IpAddress.
     *
     * @return the network address or null
     */
    public IpAddress network() {
        if (netmask == DEFAULT_MASK) {
            return new IpAddress(version, ANY, DEFAULT_MASK);
        }

        byte [] net = new byte [4];
        byte [] mask = bytes(mask());
        for (int i = 0; i < INET_LEN; i++) {
            net[i] = (byte) (octets[i] & mask[i]);
        }
        return new IpAddress(version, net, netmask);
    }

    /**
     * Returns the host portion of the IPAddress, as an IPAddress.
     * The netmask of the returned IpAddress is the current mask. If this
     * address doesn't have a mask, this returns a copy of the current
     * address.
     *
     * @return the host address
     */
    public IpAddress host() {
        if (netmask == DEFAULT_MASK) {
            new IpAddress(version, octets, netmask);
        }

        byte [] host = new byte [INET_LEN];
        byte [] mask = bytes(mask());
        for (int i = 0; i < INET_LEN; i++) {
            host[i] = (byte) (octets[i] & ~mask[i]);
        }
        return new IpAddress(version, host, netmask);
    }

    public boolean isMasked() {
        return mask() != 0;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + netmask;
        result = prime * result + Arrays.hashCode(octets);
        result = prime * result + ((version == null) ? 0 : version.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        IpAddress other = (IpAddress) obj;
        if (netmask != other.netmask) {
            return false;
        }
        if (!Arrays.equals(octets, other.octets)) {
            return false;
        }
        if (version != other.version) {
            return false;
        }
        return true;
    }

    @Override
    /*
     * (non-Javadoc)
     * format is "x.x.x.x" for non-masked (netmask 0) addresses,
     * and "x.x.x.x/y" for masked addresses.
     *
     * @see java.lang.Object#toString()
     */
    public String toString() {
        final StringBuilder builder = new StringBuilder();
        for (final byte b : this.octets) {
            if (builder.length() > 0) {
                builder.append(".");
            }
            builder.append(String.format("%d", b & 0xff));
        }
        if (netmask != DEFAULT_MASK) {
            builder.append("/");
            builder.append(String.format("%d", netmask));
        }
        return builder.toString();
    }

}
