/*
 * 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 org.apache.cassandra.locator;

import java.io.IOException;
import java.io.Serializable;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.util.regex.Pattern;

import com.google.common.base.Preconditions;
import com.google.common.net.HostAndPort;

import org.apache.cassandra.io.IVersionedSerializer;
import org.apache.cassandra.io.util.DataInputPlus;
import org.apache.cassandra.io.util.DataOutputPlus;
import org.apache.cassandra.net.MessagingService;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.FBUtilities;
import org.apache.cassandra.utils.FastByteOperations;

/**
 * A class to replace the usage of InetAddress to identify hosts in the cluster.
 * Opting for a full replacement class so that in the future if we change the nature
 * of the identifier the refactor will be easier in that we don't have to change the type
 * just the methods.
 *
 * Because an IP might contain multiple C* instances the identification must be done
 * using the IP + port. InetSocketAddress is undesirable for a couple of reasons. It's not comparable,
 * it's toString() method doesn't correctly bracket IPv6, it doesn't handle optional default values,
 * and a couple of other minor behaviors that are slightly less troublesome like handling the
 * need to sometimes return a port and sometimes not.
 *
 */
@SuppressWarnings("UnstableApiUsage")
public final class InetAddressAndPort implements Comparable<InetAddressAndPort>, Serializable
{
    private static final long serialVersionUID = 0;

    //Store these here to avoid requiring DatabaseDescriptor to be loaded. DatabaseDescriptor will set
    //these when it loads the config. A lot of unit tests won't end up loading DatabaseDescriptor.
    //Tools that might use this class also might not load database descriptor. Those tools are expected
    //to always override the defaults.
    static volatile int defaultPort = 7000;

    public final InetAddress address;
    public final byte[] addressBytes;
    public final int port;

    private InetAddressAndPort(InetAddress address, byte[] addressBytes, int port)
    {
        Preconditions.checkNotNull(address);
        Preconditions.checkNotNull(addressBytes);
        validatePortRange(port);
        this.address = address;
        this.port = port;
        this.addressBytes = addressBytes;
    }

    public InetAddressAndPort withPort(int port)
    {
        return new InetAddressAndPort(address, addressBytes, port);
    }

    private static void validatePortRange(int port)
    {
        if (port < 0 | port > 65535)
        {
            throw new IllegalArgumentException("Port " + port + " is not a valid port number in the range 0-65535");
        }
    }

    @Override
    public boolean equals(Object o)
    {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        InetAddressAndPort that = (InetAddressAndPort) o;

        if (port != that.port) return false;
        return address.equals(that.address);
    }

    @Override
    public int hashCode()
    {
        int result = address.hashCode();
        result = 31 * result + port;
        return result;
    }

    @Override
    public int compareTo(InetAddressAndPort o)
    {
        int retval = FastByteOperations.compareUnsigned(addressBytes, 0, addressBytes.length, o.addressBytes, 0, o.addressBytes.length);
        if (retval != 0)
        {
            return retval;
        }

        return Integer.compare(port, o.port);
    }

    public String getHostAddressAndPort()
    {
        return getHostAddress(true);
    }

    private static final Pattern JMX_INCOMPATIBLE_CHARS = Pattern.compile("[\\[\\]:]");


    /**
     * Return a version of getHostAddressAndPort suitable for use in JMX object names without
     * requiring any escaping.  Replaces each character invalid for JMX names with an underscore.
     *
     * @return String with JMX-safe representation of the IP address and port
     */
    public String getHostAddressAndPortForJMX()
    {
        return JMX_INCOMPATIBLE_CHARS.matcher(getHostAddressAndPort()).replaceAll("_");
    }

    public String getHostAddress(boolean withPort)
    {
        if (withPort)
        {
            return HostAndPort.fromParts(address.getHostAddress(), port).toString();
        }
        else
        {
            return address.getHostAddress();
        }
    }

    @Override
    public String toString()
    {
        return toString(true);
    }

    public String toString(boolean withPort)
    {
        if (withPort)
        {
            return toString(address, port);
        }
        else
        {
            return address.toString();
        }
    }

    /** Format an InetAddressAndPort in the same style as InetAddress.toString.
     *  The string returned is of the form: hostname / literal IP address : port
     *  (without the whitespace). Literal IPv6 addresses will be wrapped with [ ]
     *  to make the port number clear.
     *
     *  If the host name is unresolved, no reverse name service lookup
     *  is performed. The hostname part will be represented by an empty string.
     *
     * @param address InetAddress to convert String
     * @param port Port number to convert to String
     * @return String representation of the IP address and port
     */
    public static String toString(InetAddress address, int port)
    {
        String addressToString = address.toString(); // cannot use getHostName as it resolves
        int nameLength = addressToString.lastIndexOf('/'); // use last index to prevent ambiguity if host name contains /
        assert nameLength >= 0 : "InetAddress.toString format may have changed, expecting /";

        // Check if need to wrap address with [ ] for IPv6 addresses
        if (addressToString.indexOf(':', nameLength) >= 0)
        {
            StringBuilder sb = new StringBuilder(addressToString.length() + 16);
            sb.append(addressToString, 0, nameLength + 1); // append optional host and / char
            sb.append('[');
            sb.append(addressToString, nameLength + 1, addressToString.length());
            sb.append("]:");
            sb.append(port);
            return sb.toString();
        }
        else // can just append :port
        {
            StringBuilder sb = new StringBuilder(addressToString); // will have enough capacity for port
            sb.append(":");
            sb.append(port);
            return sb.toString();
        }
    }

    public static InetAddressAndPort getByName(String name) throws UnknownHostException
    {
        return getByNameOverrideDefaults(name, null);
    }

    /**
     *
     * @param name Hostname + optional ports string
     * @param port Port to connect on, overridden by values in hostname string, defaults to DatabaseDescriptor default if not specified anywhere.
     */
    public static InetAddressAndPort getByNameOverrideDefaults(String name, Integer port) throws UnknownHostException
    {
        HostAndPort hap = HostAndPort.fromString(name);
        if (hap.hasPort())
        {
            port = hap.getPort();
        }
        return getByAddressOverrideDefaults(InetAddress.getByName(hap.getHost()), port);
    }

    public static InetAddressAndPort getByAddress(byte[] address) throws UnknownHostException
    {
        return getByAddressOverrideDefaults(InetAddress.getByAddress(address), address, null);
    }

    public static InetAddressAndPort getByAddress(InetAddress address)
    {
        return getByAddressOverrideDefaults(address, null);
    }

    public static InetAddressAndPort getByAddressOverrideDefaults(InetAddress address, Integer port)
    {
        if (port == null)
        {
            port = defaultPort;
        }

        return new InetAddressAndPort(address, address.getAddress(), port);
    }

    public static InetAddressAndPort getByAddressOverrideDefaults(InetAddress address, byte[] addressBytes, Integer port)
    {
        if (port == null)
        {
            port = defaultPort;
        }

        return new InetAddressAndPort(address, addressBytes, port);
    }

    public static InetAddressAndPort getLoopbackAddress()
    {
        return InetAddressAndPort.getByAddress(InetAddress.getLoopbackAddress());
    }

    public static InetAddressAndPort getLocalHost()
    {
        return FBUtilities.getLocalAddressAndPort();
    }

    public static void initializeDefaultPort(int port)
    {
        defaultPort = port;
    }

    static int getDefaultPort()
    {
        return defaultPort;
    }

    /**
     * As of version 4.0 the endpoint description includes a port number as an unsigned short
     * This serializer matches the 3.0 CompactEndpointSerializationHelper, encoding the number of address bytes
     * in a single byte before the address itself.
     */
    public static final class Serializer implements IVersionedSerializer<InetAddressAndPort>
    {
        public static final int MAXIMUM_SIZE = 19;

        // We put the static instance here, to avoid complexity with dtests.
        // InetAddressAndPort is one of the only classes we share between instances, which is possible cleanly
        // because it has no type-dependencies in its public API, however Serializer requires DataOutputPlus, which requires...
        // and the chain becomes quite unwieldy
        public static final Serializer inetAddressAndPortSerializer = new Serializer();

        private Serializer() {}

        public void serialize(InetAddressAndPort endpoint, DataOutputPlus out, int version) throws IOException
        {
            byte[] buf = endpoint.addressBytes;

            if (version >= MessagingService.VERSION_40)
            {
                out.writeByte(buf.length + 2);
                out.write(buf);
                out.writeShort(endpoint.port);
            }
            else
            {
                out.writeByte(buf.length);
                out.write(buf);
            }
        }

        public InetAddressAndPort deserialize(DataInputPlus in, int version) throws IOException
        {
            int size = in.readByte() & 0xFF;
            switch(size)
            {
                //The original pre-4.0 serialiation of just an address
                case 4:
                case 16:
                {
                    byte[] bytes = new byte[size];
                    in.readFully(bytes, 0, bytes.length);
                    return getByAddress(bytes);
                }
                //Address and one port
                case 6:
                case 18:
                {
                    byte[] bytes = new byte[size - 2];
                    in.readFully(bytes);

                    int port = in.readShort() & 0xFFFF;
                    return getByAddressOverrideDefaults(InetAddress.getByAddress(bytes), bytes, port);
                }
                default:
                    throw new AssertionError("Unexpected size " + size);

            }
        }

        /**
         * Extract {@link InetAddressAndPort} from the provided {@link ByteBuffer} without altering its state.
         */
        public InetAddressAndPort extract(ByteBuffer buf, int position) throws IOException
        {
            int size = buf.get(position++) & 0xFF;
            if (size == 4 || size == 16)
            {
                byte[] bytes = new byte[size];
                ByteBufferUtil.copyBytes(buf, position, bytes, 0, size);
                return getByAddress(bytes);
            }
            else if (size == 6 || size == 18)
            {
                byte[] bytes = new byte[size - 2];
                ByteBufferUtil.copyBytes(buf, position, bytes, 0, size - 2);
                position += (size - 2);
                int port = buf.getShort(position) & 0xFFFF;
                return getByAddressOverrideDefaults(InetAddress.getByAddress(bytes), bytes, port);
            }

            throw new AssertionError("Unexpected pre-4.0 InetAddressAndPort size " + size);
        }

        public long serializedSize(InetAddressAndPort from, int version)
        {
            //4.0 includes a port number
            if (version >= MessagingService.VERSION_40)
            {
                if (from.address instanceof Inet4Address)
                    return 1 + 4 + 2;
                assert from.address instanceof Inet6Address;
                return 1 + 16 + 2;
            }
            else
            {
                if (from.address instanceof Inet4Address)
                    return 1 + 4;
                assert from.address instanceof Inet6Address;
                return 1 + 16;
            }
        }
    }

    /** Serializer for handling FWD_FRM message parameters. Pre-4.0 deserialization is a special
     * case in the message
     */
    public static final class FwdFrmSerializer implements IVersionedSerializer<InetAddressAndPort>
    {
        public static final FwdFrmSerializer fwdFrmSerializer = new FwdFrmSerializer();
        private FwdFrmSerializer() { }

        public void serialize(InetAddressAndPort endpoint, DataOutputPlus out, int version) throws IOException
        {
            byte[] buf = endpoint.addressBytes;

            if (version >= MessagingService.VERSION_40)
            {
                out.writeByte(buf.length + 2);
                out.write(buf);
                out.writeShort(endpoint.port);
            }
            else
            {
                out.write(buf);
            }
        }

        public long serializedSize(InetAddressAndPort from, int version)
        {
            //4.0 includes a port number
            if (version >= MessagingService.VERSION_40)
            {
                if (from.address instanceof Inet4Address)
                    return 1 + 4 + 2;
                assert from.address instanceof Inet6Address;
                return 1 + 16 + 2;
            }
            else
            {
                if (from.address instanceof Inet4Address)
                    return 4;
                assert from.address instanceof Inet6Address;
                return 16;
            }
        }

        @Override
        public InetAddressAndPort deserialize(DataInputPlus in, int version) throws IOException
        {
            if (version >= MessagingService.VERSION_40)
            {
                int size = in.readByte() & 0xFF;
                switch (size)
                {
                    //Address and one port
                    case 6:
                    case 18:
                    {
                        byte[] bytes = new byte[size - 2];
                        in.readFully(bytes);

                        int port = in.readShort() & 0xFFFF;
                        return getByAddressOverrideDefaults(InetAddress.getByAddress(bytes), bytes, port);
                    }
                    default:
                        throw new AssertionError("Unexpected size " + size);
                }
            }
            else
            {
                throw new IllegalStateException("FWD_FRM deserializations should be special-cased pre-4.0");
            }
        }

        public InetAddressAndPort pre40DeserializeWithLength(DataInputPlus in, int version, int length) throws IOException
        {
            assert length == 4 || length == 16 : "unexpected length " + length;
            byte[] from = new byte[length];
            in.readFully(from, 0, length);
            return InetAddressAndPort.getByAddress(from);
        }
    }
}
