package org.projectfloodlight.openflow.types;

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

import javax.annotation.Nonnull;

import org.jboss.netty.buffer.ChannelBuffer;

import com.google.common.base.Preconditions;
import com.google.common.hash.PrimitiveSink;
import com.google.common.primitives.UnsignedInts;

import org.projectfloodlight.openflow.protocol.Writeable;
import org.projectfloodlight.openflow.protocol.OFMessageReader;
import org.projectfloodlight.openflow.exceptions.OFParseError;

/**
 * Wrapper around an IPv4Address address
 *
 * @author Andreas Wundsam {@literal <}andreas.wundsam@bigswitch.com{@literal >}
 */
public class IPv4Address extends IPAddress<IPv4Address> implements Writeable {
    static final int LENGTH = 4;
    private final int rawValue;

    private static final int NOT_A_CIDR_MASK = -1;
    private static final int CIDR_MASK_CACHE_UNSET = -2;
    // Must appear before the static IPv4Address constant assignments
    private volatile int cidrMaskLengthCache = CIDR_MASK_CACHE_UNSET;

    private final static int NONE_VAL = 0x0;
    public final static IPv4Address NONE = new IPv4Address(NONE_VAL);

    public static final IPv4Address NO_MASK = IPv4Address.of(0xFFFFFFFF);
    public static final IPv4Address FULL_MASK = IPv4Address.of(0x00000000);

    private IPv4Address(final int rawValue) {
        this.rawValue = rawValue;
    }

    public final static Reader READER = new Reader();

    private static class Reader implements OFMessageReader<IPv4Address> {
        @Override
        public IPv4Address readFrom(ChannelBuffer bb) throws OFParseError {
            return new IPv4Address(bb.readInt());
        }
    }

    @Override
    public IPVersion getIpVersion() {
        return IPVersion.IPv4;
    }

    private int asCidrMaskLengthInternal() {
        if (cidrMaskLengthCache == CIDR_MASK_CACHE_UNSET) {
            // No lock required. We only write cidrMaskLengthCache once
            int maskint = getInt();
            if (maskint == 0) {
                cidrMaskLengthCache = 0;
            } else if (Integer.bitCount((~maskint) + 1) == 1) {
                // IP represents a true CIDR prefix length
                cidrMaskLengthCache = Integer.bitCount(maskint);
            } else {
                cidrMaskLengthCache = NOT_A_CIDR_MASK;
            }
        }
        return cidrMaskLengthCache;
    }

    @Override
    public boolean isCidrMask() {
        return asCidrMaskLengthInternal() != NOT_A_CIDR_MASK;
    }

    @Override
    public int asCidrMaskLength() {
        if (!isCidrMask()) {
            throw new IllegalStateException("IP is not a valid CIDR prefix " +
                    "mask " + toString());
        } else {
            return asCidrMaskLengthInternal();
        }
    }

    @Override
    public boolean isBroadcast() {
        return this.equals(NO_MASK);
    }

    @Override
    public IPv4Address and(IPv4Address other) {
        Preconditions.checkNotNull(other, "other must not be null");

        IPv4Address otherIp = other;
        return IPv4Address.of(rawValue & otherIp.rawValue);
    }

    @Override
    public IPv4Address or(IPv4Address other) {
        Preconditions.checkNotNull(other, "other must not be null");

        IPv4Address otherIp = other;
        return IPv4Address.of(rawValue | otherIp.rawValue);
    }

    @Override
    public IPv4Address not() {
        return IPv4Address.of(~rawValue);
    }

    /**
     * Returns an {@code IPv4Address} object that represents the given
     * IP address. The argument is in network byte order: the highest
     * order byte of the address is in {@code address[0]}.
     * <p>
     * The address byte array must be 4 bytes long (32 bits long).
     * <p>
     * Similar to {@link InetAddress#getByAddress(byte[])}.
     *
     * @param address  the raw IP address in network byte order
     * @return         an {@code IPv4Address} object that represents the given
     *                 raw IP address
     * @throws NullPointerException      if the given address was {@code null}
     * @throws IllegalArgumentException  if the given address was of an invalid
     *                                   byte array length
     * @see InetAddress#getByAddress(byte[])
     */
    @Nonnull
    public static IPv4Address of(@Nonnull final byte[] address) {
        Preconditions.checkNotNull(address, "address must not be null");

        if (address.length != LENGTH) {
            throw new IllegalArgumentException(
                    "Invalid byte array length for IPv4 address: " + address.length);
        }

        int raw =
                (address[0] & 0xFF) << 24 | (address[1] & 0xFF) << 16
                        | (address[2] & 0xFF) << 8 | (address[3] & 0xFF) << 0;
        return IPv4Address.of(raw);
    }

    /**
     * Returns an {@code IPv4Address} object that represents the given
     * IP address.
     *
     * @param raw  the raw IP address represented as a 32-bit integer
     * @return     an {@code IPv4Address} object that represents the given
     *             raw IP address
     */
    @Nonnull
    public static IPv4Address of(final int raw) {
        if(raw == NONE_VAL)
            return NONE;
        return new IPv4Address(raw);
    }

    /**
     * Returns an {@code IPv4Address} object that represents the given
     * IP address. The argument is in the canonical quad-dotted notation.
     * For example, {@code 1.2.3.4}.
     *
     * @param string  the IP address in the canonical quad-dotted notation
     * @return        an {@code IPv4Address} object that represents the given
     *                IP address
     * @throws NullPointerException      if the given string was {@code null}
     * @throws IllegalArgumentException  if the given string was not a valid
     *                                   IPv4 address
     */
    @Nonnull
    public static IPv4Address of(@Nonnull final String string) throws IllegalArgumentException {
        Preconditions.checkNotNull(string, "string must not be null");

        int start = 0;
        int shift = 24;

        int raw = 0;
        while (shift >= 0) {
            int end = string.indexOf('.', start);
            if (end == start || !((shift > 0) ^ (end < 0)))
                throw new IllegalArgumentException("IP Address not well formed: " + string);

            String substr =
                    end > 0 ? string.substring(start, end) : string.substring(start);
            int val = Integer.parseInt(substr);
            if (val < 0 || val > 255)
                throw new IllegalArgumentException("IP Address not well formed: " + string);

            raw |= val << shift;

            shift -= 8;
            start = end + 1;
        }
        return IPv4Address.of(raw);
    }

    /**
     * Returns an {@code IPv4Address} object that represents the given
     * IP address. The argument is given as an {@code Inet4Address} object.
     *
     * @param address  the IP address as an {@code Inet4Address} object
     * @return         an {@code IPv4Address} object that represents the
     *                 given IP address
     * @throws NullPointerException  if the given {@code Inet4Address} was
     *                               {@code null}
     */
    @Nonnull
    public static IPv4Address of(@Nonnull final Inet4Address address) {
        Preconditions.checkNotNull(address, "address must not be null");
        return IPv4Address.of(address.getAddress());
    }

    /**
     * Returns an {@code IPv4Address} object that represents the
     * CIDR subnet mask of the given prefix length.
     *
     * @param cidrMaskLength  the prefix length of the CIDR subnet mask
     *                        (i.e. the number of leading one-bits),
     *                        where {@code 0 <= cidrMaskLength <= 32}
     * @return                an {@code IPv4Address} object that represents the
     *                        CIDR subnet mask of the given prefix length
     * @throws IllegalArgumentException  if the given prefix length was invalid
     */
    @Nonnull
    public static IPv4Address ofCidrMaskLength(final int cidrMaskLength) {
        Preconditions.checkArgument(
                cidrMaskLength >= 0 && cidrMaskLength <= 32,
                "Invalid IPv4 CIDR mask length: %s", cidrMaskLength);

        if (cidrMaskLength == 32) {
            return IPv4Address.NO_MASK;
        } else if (cidrMaskLength == 0) {
            return IPv4Address.FULL_MASK;
        } else {
            int mask = (-1) << (32 - cidrMaskLength);
            return IPv4Address.of(mask);
        }
    }

    /**
     * Returns an {@code IPv4AddressWithMask} object that represents this
     * IP address masked by the given IP address mask.
     *
     * @param mask  the {@code IPv4Address} object that represents the mask
     * @return      an {@code IPv4AddressWithMask} object that represents this
     *              IP address masked by the given mask
     * @throws NullPointerException  if the given mask was {@code null}
     */
    @Nonnull
    @Override
    public IPv4AddressWithMask withMask(@Nonnull final IPv4Address mask) {
        return IPv4AddressWithMask.of(this, mask);
    }

    /**
     * Returns an {@code IPv4AddressWithMask} object that represents this
     * IP address masked by the CIDR subnet mask of the given prefix length.
     *
     * @param cidrMaskLength  the prefix length of the CIDR subnet mask
     *                        (i.e. the number of leading one-bits),
     *                        where {@code 0 <= cidrMaskLength <= 32}
     * @return                an {@code IPv4AddressWithMask} object that
     *                        represents this IP address masked by the CIDR
     *                        subnet mask of the given prefix length
     * @throws IllegalArgumentException  if the given prefix length was invalid
     * @see #ofCidrMaskLength(int)
     */
    @Nonnull
    @Override
    public IPv4AddressWithMask withMaskOfLength(final int cidrMaskLength) {
        return this.withMask(IPv4Address.ofCidrMaskLength(cidrMaskLength));
    }

    public int getInt() {
        return rawValue;
    }

    private volatile byte[] bytesCache = null;

    @Override
    public byte[] getBytes() {
        if (bytesCache == null) {
            synchronized (this) {
                if (bytesCache == null) {
                    bytesCache =
                            new byte[] { (byte) ((rawValue >>> 24) & 0xFF),
                                    (byte) ((rawValue >>> 16) & 0xFF),
                                    (byte) ((rawValue >>> 8) & 0xFF),
                                    (byte) ((rawValue >>> 0) & 0xFF) };
                }
            }
        }
        return Arrays.copyOf(bytesCache, bytesCache.length);
    }

    @Override
    public int getLength() {
        return LENGTH;
    }

    @Override
    public String toString() {
        StringBuilder res = new StringBuilder();
        res.append((rawValue >> 24) & 0xFF).append('.');
        res.append((rawValue >> 16) & 0xFF).append('.');
        res.append((rawValue >> 8) & 0xFF).append('.');
        res.append((rawValue >> 0) & 0xFF);
        return res.toString();
    }

    public void write4Bytes(ChannelBuffer c) {
        c.writeInt(rawValue);
    }

    public static IPv4Address read4Bytes(ChannelBuffer c) {
        return IPv4Address.of(c.readInt());
    }

    @Override
    public IPv4Address applyMask(IPv4Address mask) {
        return and(mask);
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + rawValue;
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        IPv4Address other = (IPv4Address) obj;
        if (rawValue != other.rawValue)
            return false;
        return true;
    }

    @Override
    public int compareTo(IPv4Address o) {
        return UnsignedInts.compare(rawValue, o.rawValue);
    }

    @Override
    public void putTo(PrimitiveSink sink) {
        sink.putInt(rawValue);
    }

    @Override
    public void writeTo(ChannelBuffer bb) {
        bb.writeInt(rawValue);
    }
}
