"""Network related utilities for CTS."""

__all__ = ["next_ip"]
__copyright__ = "Copyright 2000-2024 the Pacemaker project contributors"
__license__ = "GNU General Public License version 2 or later (GPLv2+) WITHOUT ANY WARRANTY"

# pylint: disable=global-statement
CURRENT_IP = None


def next_ip(ip_base=None, reset=False):
    """
    Return the next available IP address.

    This function only increments the last portion of the IP address.  Once it
    has hit the upper limit, ValueError will be raised.

    Arguments:
    ip_base -- The initial IP address to start from.  The first call to next_ip
               will return the next IP address from this base.  Each subsequent
               call will return the next address from the previous call, so you
               can just omit this argument for subsequent calls.
    reset   -- Force next_ip to start from ip_base again.  This requires also
               passing the ip_base argument.  (Mostly useful for unit testing,
               but may be useful elsewhere).
    """
    global CURRENT_IP

    if CURRENT_IP is None or reset:
        CURRENT_IP = ip_base

    new_ip = None

    # Split the existing IP address up into a tuple of:
    # (everything except the last part of the addr, the separator, the last part of the addr).
    # For instance, "192.168.1.2" becomes ("192.168.1", ".", "2").  Then,
    # increment the last part of the address and paste everything back
    # together.
    if ":" in CURRENT_IP:
        # This is an IPv6 address
        fields = CURRENT_IP.rpartition(":")
        new_ip = int(fields[2], 16) + 1

        if new_ip > 0xffff:
            raise ValueError("No more available IP addresses")

        # hex() puts "0x" at the front of the string, so strip it off.
        new_ip = hex(new_ip)[2:]

    else:
        # This is an IPv4 address
        fields = CURRENT_IP.rpartition(".")
        new_ip = int(fields[2]) + 1

        if new_ip > 255:
            raise ValueError("No more available IP addresses")

    CURRENT_IP = "%s%s%s" % (fields[0], fields[1], new_ip)
    return CURRENT_IP
