/*
 * Copyright 2014-present Open Networking Laboratory
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.onlab.packet;

import java.net.InetAddress;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.nio.ByteBuffer;
import java.util.Arrays;

import com.google.common.net.InetAddresses;

/**
 * A class representing an IPv4 address.
 * This class is immutable.
 */
public final class Ip4Address extends IpAddress {
    public static final IpAddress.Version VERSION = IpAddress.Version.INET;
    public static final int BYTE_LENGTH = IpAddress.INET_BYTE_LENGTH;
    public static final int BIT_LENGTH = IpAddress.INET_BIT_LENGTH;

    /**
     * All-zero unspecified IPv4 address.
     */
    public static final Ip4Address ZERO = Ip4Address.valueOf("0.0.0.0");

    /**
     * Constructor for given IP address version and address octets.
     *
     * @param value the IP address value stored in network byte order
     * (i.e., the most significant byte first)
     * @throws IllegalArgumentException if the arguments are invalid
     */
    private Ip4Address(byte[] value) {
        super(VERSION, value);
    }

    /**
     * Returns the integer value of this IPv4 address.
     *
     * @return the IPv4 address's value as an integer
     */
    public int toInt() {
        ByteBuffer bb = ByteBuffer.wrap(super.toOctets());
        return bb.getInt();
    }

    /**
     * Converts an integer into an IPv4 address.
     *
     * @param value an integer representing an IPv4 address value
     * @return an IPv4 address
     */
    public static Ip4Address valueOf(int value) {
        byte[] bytes =
            ByteBuffer.allocate(INET_BYTE_LENGTH).putInt(value).array();
        return new Ip4Address(bytes);
    }

    /**
     * Converts a byte array into an IPv4 address.
     *
     * @param value the IPv4 address value stored in network byte order
     * (i.e., the most significant byte first)
     * @return an IPv4 address
     * @throws IllegalArgumentException if the argument is invalid
     */
    public static Ip4Address valueOf(byte[] value) {
        return new Ip4Address(value);
    }

    /**
     * Converts a byte array and a given offset from the beginning of the
     * array into an IPv4 address.
     * <p>
     * The IP address is stored in network byte order (i.e., the most
     * significant byte first).
     * </p>
     * @param value the value to use
     * @param offset the offset in bytes from the beginning of the byte array
     * @return an IPv4 address
     * @throws IllegalArgumentException if the arguments are invalid
     */
    public static Ip4Address valueOf(byte[] value, int offset) {
        IpAddress.checkArguments(VERSION, value, offset);
        byte[] bc = Arrays.copyOfRange(value, offset, value.length);
        return Ip4Address.valueOf(bc);
    }

    /**
     * Converts an InetAddress into an IPv4 address.
     *
     * @param inetAddress the InetAddress value to use. It must contain an IPv4
     * address
     * @return an IPv4 address
     * @throws IllegalArgumentException if the argument is invalid
     */
    public static Ip4Address valueOf(InetAddress inetAddress) {
        byte[] bytes = inetAddress.getAddress();
        if (inetAddress instanceof Inet4Address) {
            return new Ip4Address(bytes);
        }
        if ((inetAddress instanceof Inet6Address) ||
            (bytes.length == INET6_BYTE_LENGTH)) {
            final String msg = "Invalid IPv4 version address string: " +
                inetAddress.toString();
            throw new IllegalArgumentException(msg);
        }
        // Use the number of bytes as a hint
        if (bytes.length == INET_BYTE_LENGTH) {
            return new Ip4Address(bytes);
        }
        final String msg = "Unrecognized IP version address string: " +
            inetAddress.toString();
        throw new IllegalArgumentException(msg);
    }

    /**
     * Converts an IPv4 string literal (e.g., "10.2.3.4") into an IP address.
     *
     * @param value an IPv4 address value in string form
     * @return an IPv4 address
     * @throws IllegalArgumentException if the argument is invalid
     */
    public static Ip4Address valueOf(String value) {
        InetAddress inetAddress = null;
        try {
            inetAddress = InetAddresses.forString(value);
        } catch (IllegalArgumentException e) {
            final String msg = "Invalid IP address string: " + value;
            throw new IllegalArgumentException(msg);
        }
        return valueOf(inetAddress);
    }

    /**
     * Creates an IPv4 network mask prefix.
     *
     * @param prefixLength the length of the mask prefix. Must be in the
     * interval [0, 32]
     * @return a new IPv4 address that contains a mask prefix of the
     * specified length
     * @throws IllegalArgumentException if the argument is invalid
     */
    public static Ip4Address makeMaskPrefix(int prefixLength) {
        byte[] mask = IpAddress.makeMaskPrefixArray(VERSION, prefixLength);
        return new Ip4Address(mask);
    }

    /**
     * Creates an IPv4 address by masking it with a network mask of given
     * mask length.
     *
     * @param address the address to mask
     * @param prefixLength the length of the mask prefix. Must be in the
     * interval [0, 32]
     * @return a new IPv4 address that is masked with a mask prefix of the
     * specified length
     * @throws IllegalArgumentException if the prefix length is invalid
     */
    public static Ip4Address makeMaskedAddress(final Ip4Address address,
                                               int prefixLength) {
        byte[] net = makeMaskedAddressArray(address, prefixLength);
        return Ip4Address.valueOf(net);
    }
}
