from netaddr import IPAddress

import netaddr.core

from bspump.declarative.abc import Expression, evaluate


class IP_FORMAT(Expression):
    """
    Parses IP address to its string representation.
    """

    Attributes = {
        "Value": ["*"],  # TODO: This ...
        "Subnet": ["*"],  # TODO: This ...
    }

    Category = "IP"

    def __init__(self, app, *, arg_what, arg_format="auto"):
        super().__init__(app)
        self.Value = arg_what

        assert arg_format in frozenset("ipv4", "ipv6", "auto")
        self.Format = arg_format

    def __call__(self, context, event, *args, **kwargs):
        try:
            ip = IPAddress(evaluate(self.Value, context, event, *args, **kwargs))
        except netaddr.core.AddrFormatError:
            # IP address could not be detected
            return None

        if self.Format == "ipv6":
            return str(ip.ipv6())
        elif self.Format == "ipv4":
            return str(ip.ipv4())
        else:  # auto
            if (0xFFFF00000000 & ip.ipv6().value) == 0xFFFF00000000:
                return str(ip.ipv4())
            else:
                return str(ip.ipv6())
