# (c) cavaliba.com - data - field - ipv4

from .field import Field


# dataformat: ipv4
# dataformat_ext:  range strict
#   * range: must be a /N range, not a single IP
#   * strict: range must be correct in **2 mask boundary



# 10.1.2.3 
# 10.0.0.0/24    range
# 10.1.2.3/24    range strict=False
# 10.1.2.128/25  range strict=True


def check_valid_ipv4_range(source):

    if type(source) is not str:
        return False

    if '/' not in source:
        return False

    (ip, mask)=source.split("/")

    a = 0
    if mask:
        try:
            a = int(mask)
        except:
            return False
    
    if a <0 or a>32:
        return False


    return check_valid_ipv4(ip)




def check_valid_ipv4(source):


    if type(source) is not str:
        return False

    if '/' in source:
        return False

    try:
        digits = source.split('.')
    except:
        return False

    # digits
    if len(digits) != 4:
        return False

    for i in digits:
        try:
            i2 = int(i)
        except:
            return False
        if i2 <0 or i2 > 255:
            return False

    return True



# -------------
# IPV4
# -------------
class FieldIPV4(Field):

    def __init__(self, fieldname, fieldschema, alljson):
        super().__init__(fieldname, fieldschema, alljson)

        self.subnet = False

        if self.dataformat_ext:
            opts = self.dataformat_ext.split(' ')

            #  subnet only ?
            if "subnet" in opts:
                self.subnet = True



    def get_eav_format(self):
        # ipv4 | ipv4:subnet

        if self.subnet:
            return "ipv4:subnet"
        else:
            return "ipv4"


    def is_valid(self):

        r = super().is_valid()

        for v in self.value:

            if type(v) is str:
                if len(v) == 0:
                    continue 

            if self.subnet:           
                r2 = check_valid_ipv4_range(v)
            else:
                r2 = check_valid_ipv4(v)
            
            if not r2:
                r = False
                break

        return r

