#! /usr/bin/env python3
import argparse
import sys
import logging
import socket
import struct

logger = logging.getLogger(__name__)


def main() -> int:
    # Handle program arguments
    ap = argparse.ArgumentParser(prog="wol", description="Wake On LAN")
    ap.add_argument("mac", help="MAC address of the target machine")
    ap.add_argument(
        "-p", "--port", help="UDP port to send the magic packet to", type=int, default=9
    )
    ap.add_argument(
        "-v", "--verbose", help="Enable verbose logging", action="store_true"
    )
    args = ap.parse_args()

    # Configure logging
    logging.basicConfig(
        level=logging.DEBUG if args.verbose else logging.INFO,
        format="%(levelname)s:	%(message)s",
    )

    # Parse MAC address
    mac = args.mac.replace(":", "").replace("-", "").replace(".", "")
    if len(mac) != 12:
        logger.error("Invalid MAC address")
        return 1
    mac = bytes.fromhex(mac)

    # Create magic packet
    magic_packet = b"\xff" * 6 + mac * 16

    # Try to broadcast magic packet over both IPv4 and IPv6
    try:
        with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
            s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
            s.sendto(magic_packet, ("<broadcast>", args.port))
    except OSError as e:
        logger.error("Failed to broadcast magic packet over IPv4: %s", e)
    try:
        with socket.socket(socket.AF_INET6, socket.SOCK_DGRAM) as s:
            s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
            s.sendto(magic_packet, ("ff02::1", args.port))
    except OSError as e:
        logger.error("Failed to broadcast magic packet over IPv6: %s", e)

    return 0


if __name__ == "__main__":
    sys.exit(main())