from ipaddress import ip_interface


defaults = {
    'apt': {
        'packages': {
            'bind9': {},
        },
    },
    'bind': {
        'zones': {},
    },
}


@metadata_reactor.provides(
    'bind/zones',
)
def dns(metadata):
    return {
        'dns': {
            metadata.get('bind/domain'): {
                'A': [
                    str(ip_interface(network['ipv4']).ip)
                        for network in metadata.get('network').values()
                        if 'ipv4' in network
                ],
                'AAAA': [
                    str(ip_interface(network['ipv6']).ip)
                        for network in metadata.get('network').values()
                        if 'ipv6' in network
                ]
            },
        },
    }


@metadata_reactor.provides(
    'bind/zones',
)
def collect_records(metadata):
    zones = {}
    
    for other_node in repo.nodes:
        for fqdn, records in other_node.metadata.get('dns').items():
            matching_zones = sorted(
                filter(
                    lambda potential_zone: fqdn.endswith(potential_zone),
                    metadata.get('bind/zones').keys()
                ),
                key=len,
            )
            if matching_zones:
                zone = matching_zones[-1]
            else:
                continue

            name = fqdn[0:-len(zone) - 1]

            for type, values in records.items():
                for value in values:
                    zones\
                        .setdefault(zone, [])\
                        .append(
                            {'name': name, 'type': type, 'value': value}
                        )
    
    return {
        'bind': {
            'zones': zones,
        },
    }


@metadata_reactor.provides(
    'bind/zones',
)
def ns_records(metadata):
    return {
        'bind': {
            'zones': {
                zone: [
                    {'name': '@', 'type': 'NS', 'value': f"{metadata.get('bind/domain')}."},
                ] for zone in metadata.get('bind/zones').keys()
            },
        },
    }