/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You 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 java.net;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamField;
import java.util.Enumeration;

/**
 * An IPv6 address. See {@link InetAddress}.
 */
public final class Inet6Address extends InetAddress {

    private static final long serialVersionUID = 6880410070516793377L;

    private static final int AF_INET6 = 10;

    static final InetAddress ANY = new Inet6Address(new byte[]
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 });
    static final InetAddress LOOPBACK = new Inet6Address(new byte[]
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, "localhost");

    int scope_id;

    boolean scope_id_set;

    boolean scope_ifname_set;

    String ifname;

    /*
     * scoped interface.
     */
    transient NetworkInterface scopedIf;

    Inet6Address(byte[] address) {
        family = AF_INET6;
        ipaddress = address;
        scope_id = 0;
    }

    Inet6Address(byte[] address, String name) {
        family = AF_INET6;
        hostName = name;
        ipaddress = address;
        scope_id = 0;
    }

    /**
     * Constructs an {@code InetAddress} representing the {@code address} and
     * {@code name} and {@code scope_id}.
     *
     * @param address
     *            the network address.
     * @param name
     *            the name associated with the address.
     * @param scope_id
     *            the scope id for link- or site-local addresses.
     */
    Inet6Address(byte[] address, String name, int scope_id) {
        family = AF_INET6;
        hostName = name;
        ipaddress = address;
        this.scope_id = scope_id;
        if (scope_id != 0) {
            scope_id_set = true;
        }
    }

    /**
     * Constructs an IPv6 address according to the given {@code host}, {@code
     * addr} and {@code scope_id}.
     *
     * @param host
     *            the host name associated with the address.
     * @param addr
     *            the network address.
     * @param scope_id
     *            the scope id for link- or site-local addresses.
     * @return the Inet6Address instance representing the IP address.
     * @throws UnknownHostException
     *             if the address is null or has an invalid length.
     */
    public static Inet6Address getByAddress(String host, byte[] addr,
            int scope_id) throws UnknownHostException {
        if (addr == null || addr.length != 16) {
            throw new UnknownHostException("Illegal IPv6 address");
        }
        if (scope_id < 0) {
            scope_id = 0;
        }
        return new Inet6Address(addr, host, scope_id);
    }

    /**
     * Gets an IPv6 address instance according to the given {@code host},
     * {@code addr} and {@code nif}. {@code scope_id} is set according to the
     * given {@code nif} and the {@code addr} type (for example site-local or
     * link-local).
     *
     * @param host
     *            the hostname associated with the address.
     * @param addr
     *            the network address.
     * @param nif
     *            the network interface that this address is associated with.
     * @return the Inet6Address instance representing the IP address.
     * @throws UnknownHostException
     *             if the address is {@code null} or has an invalid length or
     *             the interface doesn't have a numeric scope id for the given
     *             address type.
     */
    public static Inet6Address getByAddress(String host, byte[] addr,
            NetworkInterface nif) throws UnknownHostException {

        Inet6Address address = Inet6Address.getByAddress(host, addr, 0);

        // if nif is null, nothing needs to be set.
        if (null == nif) {
            return address;
        }

        // find the first address which matches the type addr,
        // then set the scope_id, ifname and scopedIf.
        Enumeration<InetAddress> addressList = nif.getInetAddresses();
        while (addressList.hasMoreElements()) {
            InetAddress ia = addressList.nextElement();
            if (ia.getAddress().length == 16) {
                Inet6Address v6ia = (Inet6Address) ia;
                boolean isSameType = v6ia.compareLocalType(address);
                if (isSameType) {
                    address.scope_id_set = true;
                    address.scope_id = v6ia.scope_id;
                    address.scope_ifname_set = true;
                    address.ifname = nif.getName();
                    address.scopedIf = nif;
                    break;
                }
            }
        }
        // if no address matches the type of addr, throws an
        // UnknownHostException.
        if (!address.scope_id_set) {
            throw new UnknownHostException("Scope id not found for the given address");
        }
        return address;
    }

    /**
     * Returns {@code true} if one of following cases applies:
     * <p>
     * <ol>
     *  <li>both addresses are site local</li>
     *  <li>both addresses are link local</li>
     *  <li>{@code ia} is neither site local nor link local</li>
     * </ol>
     */
    private boolean compareLocalType(Inet6Address ia) {
        if (ia.isSiteLocalAddress() && isSiteLocalAddress()) {
            return true;
        }
        if (ia.isLinkLocalAddress() && isLinkLocalAddress()) {
            return true;
        }
        if (!ia.isSiteLocalAddress() && !ia.isLinkLocalAddress()) {
            return true;
        }
        return false;
    }

    /**
     * Constructs an {@code InetAddress} representing the {@code address} and
     * {@code scope_id}.
     *
     * @param address
     *            the network address.
     * @param scope_id
     *            the scope id for link- or site-local addresses.
     */
    Inet6Address(byte[] address, int scope_id) {
        ipaddress = address;
        this.scope_id = scope_id;
        if (scope_id != 0) {
            scope_id_set = true;
        }
    }

    /**
     * Returns whether this address is an IP multicast address or not. Valid
     * IPv6 multicast addresses are binary prefixed with 11111111 or FF (hex).
     *
     * @return {@code true} if this address is in the multicast group, {@code
     *         false} otherwise.
     */
    @Override
    public boolean isMulticastAddress() {
        // Multicast addresses are prefixed with 11111111 (255)
        return ipaddress[0] == -1;
    }

    /**
     * Returns whether this address is a unspecified wildcard address "::" or
     * not.
     *
     * @return {@code true} if this instance represents a wildcard address,
     *         {@code false} otherwise.
     */
    @Override
    public boolean isAnyLocalAddress() {
        for (int i = 0; i < ipaddress.length; i++) {
            if (ipaddress[i] != 0) {
                return false;
            }
        }
        return true;
    }

    /**
     * Returns whether this address is the loopback address or not. The only
     * valid IPv6 loopback address is "::1".
     *
     * @return {@code true} if this instance represents the loopback address,
     *         {@code false} otherwise.
     */
    @Override
    public boolean isLoopbackAddress() {

        // The last word must be 1
        if (ipaddress[15] != 1) {
            return false;
        }

        // All other words must be 0
        for (int i = 0; i < 15; i++) {
            if (ipaddress[i] != 0) {
                return false;
            }
        }

        return true;
    }

    /**
     * Returns whether this address is a link-local address or not. A valid IPv6
     * link-local address is prefixed with 1111111010.
     *
     * @return {@code true} if this instance represents a link-local address,
     *         {@code false} otherwise.
     */
    @Override
    public boolean isLinkLocalAddress() {

        // the first 10 bits need to be 1111111010 (1018)
        return (ipaddress[0] == -2) && ((ipaddress[1] & 255) >>> 6) == 2;
    }

    /**
     * Returns whether this address is a site-local address or not. A valid IPv6
     * site-local address is prefixed with 1111111011.
     *
     * @return {@code true} if this instance represents a site-local address,
     *         {@code false} otherwise.
     */
    @Override
    public boolean isSiteLocalAddress() {

        // the first 10 bits need to be 1111111011 (1019)
        return (ipaddress[0] == -2) && ((ipaddress[1] & 255) >>> 6) == 3;
    }

    /**
     * Returns whether this address is a global multicast address or not. A
     * valid IPv6 global multicast address is 11111111xxxx1110 or FF0E hex.
     *
     * @return {@code true} if this instance represents a global multicast
     *         address, {@code false} otherwise.
     */
    @Override
    public boolean isMCGlobal() {
        // the first byte should be 0xFF and the lower 4 bits
        // of the second byte should be 0xE
        return (ipaddress[0] == -1) && (ipaddress[1] & 15) == 14;
    }

    /**
     * Returns whether this address is a node-local multicast address or not. A
     * valid IPv6 node-local multicast address is prefixed with
     * 11111111xxxx0001.
     *
     * @return {@code true} if this instance represents a node-local multicast
     *         address, {@code false} otherwise.
     */
    @Override
    public boolean isMCNodeLocal() {
        // the first byte should be 0xFF and the lower 4 bits
        // of the second byte should be 0x1
        return (ipaddress[0] == -1) && (ipaddress[1] & 15) == 1;
    }

    /**
     * Returns whether this address is a link-local multicast address or not. A
     * valid IPv6 link-local multicast address is prefixed with
     * 11111111xxxx0010.
     *
     * @return {@code true} if this instance represents a link-local multicast
     *         address, {@code false} otherwise.
     */
    @Override
    public boolean isMCLinkLocal() {
        // the first byte should be 0xFF and the lower 4 bits
        // of the second byte should be 0x2
        return (ipaddress[0] == -1) && (ipaddress[1] & 15) == 2;
    }

    /**
     * Returns whether this address is a site-local multicast address or not. A
     * valid IPv6 site-local multicast address is prefixed with
     * 11111111xxxx0101.
     *
     * @return {@code true} if this instance represents a site-local multicast
     *         address, {@code false} otherwise.
     */
    @Override
    public boolean isMCSiteLocal() {
        // the first byte should be 0xFF and the lower 4 bits
        // of the second byte should be 0x5
        return (ipaddress[0] == -1) && (ipaddress[1] & 15) == 5;
    }

    /**
     * Returns whether this address is a organization-local multicast address or
     * not. A valid IPv6 org-local multicast address is prefixed with
     * 11111111xxxx1000.
     *
     * @return {@code true} if this instance represents a org-local multicast
     *         address, {@code false} otherwise.
     */
    @Override
    public boolean isMCOrgLocal() {
        // the first byte should be 0xFF and the lower 4 bits
        // of the second byte should be 0x8
        return (ipaddress[0] == -1) && (ipaddress[1] & 15) == 8;
    }

    // BEGIN android-removed
    // public String getHostAddress() {
    // }
    // END android-removed

    /**
     * Gets the scope id as a number if this address is linked to an interface.
     * Otherwise returns {@code 0}.
     *
     * @return the scope_id of this address or 0 when not linked with an
     *         interface.
     */
    public int getScopeId() {
        if (scope_id_set) {
            return scope_id;
        }
        return 0;
    }

    /**
     * Gets the network interface if this address is instanced with a scoped
     * network interface. Otherwise returns {@code null}.
     *
     * @return the scoped network interface of this address.
     */
    public NetworkInterface getScopedInterface() {
        if (scope_ifname_set) {
            return scopedIf;
        }
        return null;
    }

    // BEGIN android-removed
    // public int hashCode() {}
    // END android-removed

    // BEGIN android-removed
    // public boolean equals(Object obj) {}
    // END android-removed

    /**
     * Returns whether this address is IPv4 compatible or not. An IPv4
     * compatible address is prefixed with 96 bits of 0's. The last 32-bits are
     * varied corresponding with the 32-bit IPv4 address space.
     *
     * @return {@code true} if this instance represents an IPv4 compatible
     *         address, {@code false} otherwise.
     */
    public boolean isIPv4CompatibleAddress() {
        for (int i = 0; i < 12; i++) {
            if (ipaddress[i] != 0) {
                return false;
            }
        }
        return true;
    }

    private static final ObjectStreamField[] serialPersistentFields = {
            new ObjectStreamField("ipaddress", new byte[0].getClass()),
            new ObjectStreamField("scope_id", Integer.TYPE),
            new ObjectStreamField("scope_id_set", Boolean.TYPE),
            new ObjectStreamField("scope_ifname_set", Boolean.TYPE),
            new ObjectStreamField("ifname", String.class), };

    private void writeObject(ObjectOutputStream stream) throws IOException {
        ObjectOutputStream.PutField fields = stream.putFields();
        if (ipaddress == null) {
            fields.put("ipaddress", null);
        } else {
            fields.put("ipaddress", ipaddress);
        }

        fields.put("scope_id", scope_id);
        fields.put("scope_id_set", scope_id_set);
        fields.put("scope_ifname_set", scope_ifname_set);
        fields.put("ifname", ifname);
        stream.writeFields();
    }

    private void readObject(ObjectInputStream stream) throws IOException,
            ClassNotFoundException {
        ObjectInputStream.GetField fields = stream.readFields();
        ipaddress = (byte[]) fields.get("ipaddress", null);
        scope_id = fields.get("scope_id", 0);
        scope_id_set = fields.get("scope_id_set", false);
        ifname = (String) fields.get("ifname", null);
        scope_ifname_set = fields.get("scope_ifname_set", false);
        if (scope_ifname_set && null != ifname) {
            scopedIf = NetworkInterface.getByName(ifname);
        }
    }

    /**
     * Returns a string containing a concise, human-readable description of this
     * IP address.
     *
     * @return the description, as host/address.
     */
    @Override
    public String toString() {
        if (ifname != null) {
            return super.toString() + "%" + ifname;
        }
        if (scope_id != 0) {
            return super.toString() + "%" + scope_id;
        }
        return super.toString();
    }
}
