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

def mactobytes(buf):
    # IETF-style (and potential NIS-style "no leading zeros") addresses
    if m := re.match(r"^[0-9a-f]{1,2}(:[0-9a-f]{1,2}){5,}$", buf, re.I):
        return bytes(int(x, 16) for x in buf.split(":"))
    # Windows-style addresses
    if m := re.match(r"^[0-9a-f]{2}(-[0-9a-f]{2}){5,}$", buf, re.I):
        return bytes(int(x, 16) for x in buf.split("-"))
    # Cisco-style addresses
    if m := re.match(r"^[0-9a-f]{4}(\.[0-9a-f]{4}){2,}$", buf, re.I):
        return bytes.fromhex(buf.replace(".", ""))
    # No separator
    if m := re.match(r"^([0-9a-f]{2}){6,}$", buf, re.I):
        return bytes.fromhex(buf)
    raise ValueError

class EtherAddress:
    def __init__(self, value):
        self.buf = mactobytes(value)

    def __str__(self):
        return ":".join("%02X" % x for x in self.buf)

    def __repr__(self):
        return "%s(%r)" % (self.__class__.__name__, str(self))

    def __eq__(self, other):
        return self.buf == other.buf

parser = argparse.ArgumentParser()
parser.add_argument("-e", "--edit", action="store_true",
                        help="open in text editor")
parser.add_argument("-q", "--quiet", action="store_true",
                        help="output just the name")
parser.add_argument("address", nargs="*", type=EtherAddress)
args = parser.parse_args()

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

path = os.path.expanduser("~/Dropbox/Notes/Nullroute/MAC addresses.txt")
if not os.path.exists(path):
    path = "/net/ember/" + path

lineno = 0
found = False

with open(path, "r") as fh:
    for i, line in enumerate(fh, start=1):
        if re.match(r"^$|^[#;]", line):
            continue
        mac = line.split()[0]
        desc = line.rstrip()
        if args.quiet:
            desc = desc.split(None, 1)[1]
        if EtherAddress(mac) in args.address:
            print(desc)
            lineno = i
            found = True

if args.edit:
    cmd = ["nvim", path, "+:setl cursorline", f"+{lineno}"]
    subprocess.run(cmd)
    exit()

if not found:
    if args.quiet:
        exit(1)
    else:
        addrs = ", ".join(map(str, args.address))
        exit(f"whatmac: no results for {addrs}")
