package org.onlab.packet;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.util.Objects;

import com.google.common.net.InetAddresses;
import com.google.common.primitives.UnsignedLongs;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;

/**
 * The class representing an IPv6 address.
 * This class is immutable.
 */
public final class Ip6Address implements Comparable<Ip6Address> {
    private final long valueHigh;    // The higher (more significant) 64 bits
    private final long valueLow;     // The lower (less significant) 64 bits

    /** The length of the address in bytes (octets). */
    public static final int BYTE_LENGTH = 16;

    /** The length of the address in bits. */
    public static final int BIT_LENGTH = BYTE_LENGTH * Byte.SIZE;

    /**
     * Default constructor.
     */
    public Ip6Address() {
        this.valueHigh = 0;
        this.valueLow = 0;
    }

    /**
     * Copy constructor.
     *
     * @param other the object to copy from
     */
    public Ip6Address(Ip6Address other) {
        this.valueHigh = other.valueHigh;
        this.valueLow = other.valueLow;
    }

    /**
     * Constructor from integer values.
     *
     * @param valueHigh the higher (more significant) 64 bits of the address
     * @param valueLow  the lower (less significant) 64 bits of the address
     */
    public Ip6Address(long valueHigh, long valueLow) {
        this.valueHigh = valueHigh;
        this.valueLow = valueLow;
    }

    /**
     * Constructor from a byte array with the IPv6 address stored in network
     * byte order (i.e., the most significant byte first).
     *
     * @param value the value to use
     */
    public Ip6Address(byte[] value) {
        this(value, 0);
    }

    /**
     * Constructor from a byte array with the IPv6 address stored in network
     * byte order (i.e., the most significant byte first), and a given offset
     * from the beginning of the byte array.
     *
     * @param value the value to use
     * @param offset the offset in bytes from the beginning of the byte array
     */
    public Ip6Address(byte[] value, int offset) {
        checkNotNull(value);

        // Verify the arguments
        if ((offset < 0) || (offset + BYTE_LENGTH > value.length)) {
            String msg;
            if (value.length < BYTE_LENGTH) {
                msg = "Invalid IPv6 address array: array length: " +
                    value.length + ". Must be at least " + BYTE_LENGTH;
            } else {
                msg = "Invalid IPv6 address array: array offset: " +
                    offset + ". Must be in the interval [0, " +
                    (value.length - BYTE_LENGTH) + "]";
            }
            throw new IllegalArgumentException(msg);
        }

        // Read the address
        ByteBuffer bb = ByteBuffer.wrap(value);
        bb.position(offset);
        this.valueHigh = bb.getLong();
        this.valueLow = bb.getLong();
    }

    /**
     * Constructs an IPv6 address from a string representation of the address.
     *<p>
     * Example: "1111:2222::8888"
     *
     * @param value the value to use
     */
    public Ip6Address(String value) {
        checkNotNull(value);

        if (value.isEmpty()) {
            final String msg = "Specified IPv6 cannot be an empty string";
            throw new IllegalArgumentException(msg);
        }
        InetAddress addr = null;
        try {
            addr = InetAddresses.forString(value);
        } catch (IllegalArgumentException e) {
            final String msg = "Invalid IPv6 address string: " + value;
            throw new IllegalArgumentException(msg);
        }
        byte[] bytes = addr.getAddress();
        ByteBuffer bb = ByteBuffer.wrap(bytes);
        this.valueHigh = bb.getLong();
        this.valueLow = bb.getLong();
    }

    /**
     * Gets the IPv6 address as a byte array.
     *
     * @return a byte array with the IPv6 address stored in network byte order
     * (i.e., the most significant byte first).
     */
    public byte[] toOctets() {
        return ByteBuffer.allocate(BYTE_LENGTH)
            .putLong(valueHigh).putLong(valueLow).array();
    }

    /**
     * Creates an IPv6 network mask prefix.
     *
     * @param prefixLen the length of the mask prefix. Must be in the interval
     * [0, 128].
     * @return a new IPv6 address that contains a mask prefix of the
     * specified length
     */
    public static Ip6Address makeMaskPrefix(int prefixLen) {
        long vh, vl;

        // Verify the prefix length
        if ((prefixLen < 0) || (prefixLen > Ip6Address.BIT_LENGTH)) {
            final String msg = "Invalid IPv6 prefix length: " + prefixLen +
                ". Must be in the interval [0, 128].";
            throw new IllegalArgumentException(msg);
        }

        if (prefixLen == 0) {
            //
            // NOTE: Apparently, the result of "<< 64" shifting to the left
            // results in all 1s instead of all 0s, hence we handle it as
            // a special case.
            //
            vh = 0;
            vl = 0;
        } else if (prefixLen <= 64) {
            vh = (0xffffffffffffffffL << (64 - prefixLen)) & 0xffffffffffffffffL;
            vl = 0;
        } else {
            vh = -1L;           // All 1s
            vl = (0xffffffffffffffffL << (128 - prefixLen)) & 0xffffffffffffffffL;
        }
        return new Ip6Address(vh, vl);
    }

    /**
     * Creates an IPv6 address by masking it with a network mask of given
     * mask length.
     *
     * @param addr the address to mask
     * @param prefixLen the length of the mask prefix. Must be in the interval
     * [0, 128].
     * @return a new IPv6 address that is masked with a mask prefix of the
     * specified length
     */
    public static Ip6Address makeMaskedAddress(final Ip6Address addr,
                                               int prefixLen) {
        Ip6Address mask = Ip6Address.makeMaskPrefix(prefixLen);
        long vh = addr.valueHigh & mask.valueHigh;
        long vl = addr.valueLow & mask.valueLow;

        return new Ip6Address(vh, vl);
    }

    /**
     * Gets the value of the higher (more significant) 64 bits of the address.
     *
     * @return the value of the higher (more significant) 64 bits of the
     * address
     */
    public long getValueHigh() {
        return valueHigh;
    }

    /**
     * Gets the value of the lower (less significant) 64 bits of the address.
     *
     * @return the value of the lower (less significant) 64 bits of the
     * address
     */
    public long getValueLow() {
        return valueLow;
    }

    /**
     * Converts the IPv6 value to a ':' separated string.
     *
     * @return the IPv6 value as a ':' separated string
     */
    @Override
    public String toString() {
        ByteBuffer bb = ByteBuffer.allocate(Ip6Address.BYTE_LENGTH);
        bb.putLong(valueHigh);
        bb.putLong(valueLow);
        InetAddress inetAddr = null;
        try {
            inetAddr = InetAddress.getByAddress(bb.array());
        } catch (UnknownHostException e) {
            // Should never happen
            checkState(false, "Internal error: Ip6Address.toString()");
            return "::";
        }
        return InetAddresses.toAddrString(inetAddr);
    }

    @Override
    public boolean equals(Object o) {
        if (!(o instanceof Ip6Address)) {
            return false;
        }
        Ip6Address other = (Ip6Address) o;
        return this.valueHigh == other.valueHigh
                && this.valueLow == other.valueLow;
    }

    @Override
    public int hashCode() {
        return Objects.hash(valueHigh, valueLow);
    }

    @Override
    public int compareTo(Ip6Address o) {
        // Compare the high-order 64-bit value
        if (this.valueHigh != o.valueHigh) {
            return UnsignedLongs.compare(this.valueHigh, o.valueHigh);
        }
        // Compare the low-order 64-bit value
        if (this.valueLow != o.valueLow) {
            return UnsignedLongs.compare(this.valueLow, o.valueLow);
        }
        return 0;
    }
}
