import argparse
import logging
import logging.config
import socket
import time
import zmq
from hedgehog.utils.discovery.service_node import ServiceNode
from pyre import zhelper

from . import handlers
from .hedgehog_server import HedgehogServer
from .handlers.hardware import HardwareHandler
from .handlers.process import ProcessHandler
from .hardware.serial import SerialHardwareAdapter

logger = logging.getLogger(__name__)


def parse_args():
    parser = argparse.ArgumentParser()
    parser.add_argument('-n', '--name', default=None,
                        help="Node name for discovery; the default incorporates a MAC address for identification")
    parser.add_argument('-p', '--port', type=int, default=0,
                        help="The port to use, 0 means random port; default: %(default)s")
    parser.add_argument('--svc', '--service', dest='services', action='append', default=['hedgehog_server'],
                        help="Additional service identifiers, may appear multiple times; %(default)s is always registered")
    parser.add_argument('--logging-conf', dest='logging_conf',
                        help="If given, logging is configured from this file")
    return parser.parse_args()


def get_default_name(simulator=False):
    # get dict of interfaces
    netinf = {iface: data
              for netinf in zhelper.get_ifaddrs()
              for iface, data in netinf.items()}

    # consider only wired interfaces - TODO cross platform testing
    wired = {iface: data
             for iface, data in netinf.items()
             if any(iface.startswith(prefix) for prefix in ('eth', 'en'))}

    # get MAC addresses, predictably sorted by interface name
    addrs = [data[socket.AF_PACKET]['addr']
             for iface, data in sorted(netinf.items())
             if socket.AF_PACKET in data]

    # choose first interface, use last three octets in server name
    suffix = " " + addrs[0][9:] if addrs else ""
    kind = "Hedgehog Simulator" if simulator else "Hedgehog Server"
    return kind + suffix


def launch(hardware):
    args = parse_args()

    if args.logging_conf:
        logging.config.fileConfig(args.logging_conf)
    start(hardware, name=args.name, port=args.port, services=args.services)


def start(hardware, name=None, port=0, services=('hedgehog_server',)):
    if name is None:
        from hedgehog.server.hardware.simulated import SimulatedHardwareAdapter
        name = get_default_name(hardware == SimulatedHardwareAdapter)

    ctx = zmq.Context.instance()

    handler = handlers.to_dict(HardwareHandler(hardware()), ProcessHandler())

    server = HedgehogServer(ctx, 'tcp://*:{}'.format(port), handler)
    with server:
        logger.info("{} started on {}".format(name, server.socket.last_endpoint.decode('utf-8')))

        # TODO clean way to exit
        while True:
            logger.info("Starting Node for discovery...")

            node = ServiceNode(ctx, name)
            with node:
                for service in services:
                    node.join(service)
                    node.add_service(service, server.socket)

                while True:
                    command, *args = node.evt_pipe.recv_multipart()
                    if command == b'BEACON TERM':
                        logger.info("Beacon terminated (network gone?). Retry in 3 seconds...")
                        time.sleep(3)
                        node.restart_beacon()
                    if command == b'$TERM':
                        break

            logger.info("Node terminated. Retry in 3 seconds...")
            time.sleep(3)

@@ -591,65 +591,76 @@
 ry; 
-the default incorporates a MAC address for identification
+can use %7Bmode%7D and %7Bmac%7D to include server/simulator and MAC address
 %22)%0A 
@@ -1222,32 +1222,31 @@
 )%0A%0A%0Adef 
-get_default_name
+name_fmt_kwargs
 (simulat
@@ -1905,74 +1905,34 @@
     
-suffix = %22 %22 + addrs%5B0%5D%5B9:%5D if addrs else %22%22%0A    kind = %22Hedgehog 
+return %7B%0A        'mode': %22
 Simu
@@ -1961,49 +1961,68 @@
 se %22
-Hedgehog 
 Server%22
+,
 %0A    
-return kind + suffix
+    'mac': addrs%5B0%5D%5B9:%5D if addrs else %22%22,%0A    %7D
 %0A%0A%0Ad
@@ -2316,24 +2316,60 @@
 s None:%0A    
+    name = 'Hedgehog %7Bmode%7D %7Bmac%7D'%0A%0A
     from hed
@@ -2432,20 +2432,16 @@
 Adapter%0A
-    
     name
@@ -2447,24 +2447,37 @@
 e = 
-get_default_name
+name.format(**name_fmt_kwargs
 (har
@@ -2510,16 +2510,17 @@
 Adapter)
+)
 %0A%0A    ct

use format string for name, so that even with manually setting the name, computed parts can be incorporated