#!/usr/bin/env python

import sys

import time

import dns.zone
import dns.name
import dns.rdataclass
import dns.rdatatype

from dns.node import Node
from dns.rdataset import from_rdata as rdataset_from_rdata
from dns.rdataset import from_rdata_list as rdataset_from_rdata_list

from dns.rdtypes.ANY.PTR import PTR
from dns.rdtypes.ANY.SOA import SOA
from dns.rdtypes.ANY.NS  import NS

from dns.zone import Zone
from dns.zone import from_file as zone_from_file

#
# Terrible hack. Multiple A records for the same address will result in
# ambiguity. List the ones we don't want PTRs for here.
#
IGNORE = (
    dns.name.from_text('ignore.domain'),
)

NAME_SERVERS = (
    dns.name.from_text('ns0.domain'),
)

TTL = 1 * 60 * 60 # 1h

SOA_REFRESH = 24 * 60 * 60 # 24h
SOA_RETRY   =  2 * 60 * 60 # 2h
SOA_EXPIRE  = 24 * 60 * 60 # 24h
SOA_MINIMUM = 24 * 60 * 60 # 24h
SOA_RESPONSIBLE = 'noc.domain'

def usage():
    print """usage: %s <input_origin> <input_filename> <output_origin>""" % sys.argv[0]
    sys.exit(1)

def main(argv):
    try:
        input_origin   = argv[1]
        input_filename = argv[2]
        output_origin  = argv[3]
    except IndexError:
        usage()

    fwd_zone = zone_from_file(input_filename, input_origin, relativize=False)
    rev_zone = Zone(dns.name.from_text(output_origin))

    node = Node()

    soa = SOA(
        dns.rdataclass.IN,
        dns.rdatatype.SOA,
        dns.name.from_text(SOA_RESPONSIBLE),
        int(time.time()),
        SOA_EXPIRE,
        SOA_MINIMUM,
        SOA_REFRESH,
        SOA_RETRY,
    )
    node.rdatasets.append(rdataset_from_rdata(TTL, soa))

    ns_rdata = []
    for nameserver in NAME_SERVERS:
        ns_rdata.append(
            NS(
                dns.rdataclass.IN,
                dns.rdatatype.NS,
                nameserver,
            )
        )
    node.rdatasets.append(rdataset_from_rdata_list(TTL, ns_rdata))

    rev_zone[rev_zone.origin] = node

    for name, rdataset in fwd_zone.iterate_rdatasets('A'):
        # PTRs can't point to wildcard records
        if '*' in name or name in IGNORE:
            continue

        ip = rdataset.items[0].address
        
        ptr = PTR(dns.rdataclass.IN, dns.rdatatype.PTR, name)

        ptr_name_parts = ip.split('.')
        ptr_name_parts.reverse()
        ptr_name_parts.extend(('in-addr', 'arpa'))
        ptr_name = dns.name.from_text('.'.join(ptr_name_parts))
        
        node = Node()
        node.rdatasets.append(rdataset_from_rdata(TTL, ptr))
        try:
            rev_zone[ptr_name] = node
        except KeyError:
            continue

    rev_zone.to_file(sys.stdout)

if __name__ == '__main__':
    main(sys.argv)
