#!/usr/bin/env python3
# whatip -- Look up an IP address in the "IP addresses.txt" database
import argparse
import ipaddress
import os
import re
import subprocess

def ipmatch(ip, net):
    if ".x" in net:
        # Transform 10.147.0.x into a regex
        net = net.split("/")[0]
        net = re.escape(net).replace("x", r"[0-9]+")
        if re.fullmatch(net, str(ip)):
            return True
    elif "/" in net:
        net = ipaddress.ip_network(net)
        if ip in net:
            return True
    else:
        net = ipaddress.ip_address(net)
        if ip == net:
            return True
    return False

parser = argparse.ArgumentParser()
parser.add_argument("-f", "--file",
                        help="alternate file to search")
parser.add_argument("-e", "--edit", action="store_true",
                        help="open in text editor")
parser.add_argument("address", nargs="*", type=ipaddress.ip_address,
                        help="IP address to search for")
args = parser.parse_args()

if not (args.edit or args.address):
    exit("whatip: address not specified")

if args.file:
    path = args.file
else:
    path = os.path.expanduser("~/Dropbox/Notes/Nullroute/IP address assignments.txt")
    if not os.path.exists(path):
        path = "/net/ember/" + path

lineno = 0
found = False

with open(path, "r") as fh:
    within = False
    for i, line in enumerate(fh, start=1):
        if not args.file:
            # For the default file, only search a specific section.
            if line.startswith("Main IPv4 private range"):
                lineno = i
                within = True
            elif line.startswith("=== Additional networks") and found:
                within = False
            elif not within:
                continue

        if re.match(r"^\d+\.\d+\.\d+\.\d+|^2[0-9a-f]{3}:", line.strip()):
            net = line.split()[0].rstrip(":")
            desc = line.rstrip()
            try:
                if any(ipmatch(a, net) for a in args.address):
                    print(desc)
                    lineno = i
                    found = True
            except ValueError as e:
                print(f"whatip: line {i}: {e}", file=sys.stderr)

if args.edit:
    cmd = ["nvim", path, "+:setl cursorline", f"+{lineno}"]
    subprocess.run(cmd)
else:
    if not found:
        addrs = ", ".join(map(str, args.address))
        exit(f"whatip: no data for {addrs}")
