#
# Copyright (c) 2022 Pim van Pelt
#
# Licensed 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.
#
"""A vppcfg configuration module that validates vxlan_tunnels"""
import logging
import ipaddress


def get_by_name(yaml, ifname):
    """Return the VXLAN by name, if it exists. Return None otherwise."""
    try:
        if ifname in yaml["vxlan_tunnels"]:
            return ifname, yaml["vxlan_tunnels"][ifname]
    except KeyError:
        pass
    return None, None


def is_vxlan_tunnel(yaml, ifname):
    """Returns True if the interface name is an existing VXLAN Tunnel."""
    ifname, iface = get_by_name(yaml, ifname)
    return iface is not None


def vni_unique(yaml, vni):
    """Return True if the VNI is unique amongst all VXLANs"""
    if not "vxlan_tunnels" in yaml:
        return True

    ncount = 0
    for _ifname, iface in yaml["vxlan_tunnels"].items():
        if iface["vni"] == vni:
            ncount = ncount + 1

    return ncount < 2


def get_vxlan_tunnels(yaml):
    """Returns a list of all VXLAN tunnel interface names."""
    ret = []
    if not "vxlan_tunnels" in yaml:
        return ret

    for ifname, _iface in yaml["vxlan_tunnels"].items():
        ret.append(ifname)
    return ret


def validate_vxlan_tunnels(yaml):
    """Validate the semantics of all YAML 'vxlan_tunnels' entries"""
    result = True
    msgs = []
    logger = logging.getLogger("vppcfg.config")
    logger.addHandler(logging.NullHandler())

    if not "vxlan_tunnels" in yaml:
        return result, msgs

    for ifname, iface in yaml["vxlan_tunnels"].items():
        logger.debug(f"vxlan_tunnel {ifname}: {iface}")
        instance = int(ifname[12:])
        if instance > 2147483647:
            msgs.append(
                f"vxlan_tunnel {ifname} has instance {int(instance)} which is too large"
            )
            result = False

        vni = iface["vni"]
        if not vni_unique(yaml, vni):
            msgs.append(f"vxlan_tunnel {ifname} VNI {int(vni)} is not unique")
            result = False
        local = ipaddress.ip_address(iface["local"])
        remote = ipaddress.ip_address(iface["remote"])
        if local.version != remote.version:
            msgs.append(
                f"vxlan_tunnel {ifname} local and remote are not the same address family"
            )
            result = False

    return result, msgs
