#!/usr/bin/env python3 -u
#
# Scan for all network addresses

import hmtl.HMTLprotocol as HMTLprotocol
from hmtl.client import HMTLClient
from hmtl.TimedLogger import TimedLogger


from optparse import OptionParser, OptionGroup


def handle_args():
    parser = OptionParser()

    parser.add_option("-v", "--verbose", dest="verbose", action="store_true",
                      help="Verbose output", default=False)
    parser.add_option("-p", "--port", dest="port", type="int",
                      help="Port to bind to", default=6000)
    parser.add_option("-a", "--address", dest="address",
                      help="Address to bind to", default="localhost")

    # General options
    parser.add_option("-A", "--hmtladdress", dest="hmtladdress", type="int",
                      help="Address to which messages are sent [default=BROADCAST]")

    # Scan options
    parser.add_option("-e", "--scanevery", dest="scanevery", action="store_true",
                      help="Individual scan through address", default=False)

    (options, args) = parser.parse_args()
    logger.log("options:" + str(options) + " args:" + str(args))

    return options, args


def handle_poll_resp(data, modules):
    (text, msg) = HMTLprotocol.decode_msg(data)
    if (isinstance(msg, HMTLprotocol.PollHdr)):
        logger.log("Poll response: dev=%d addr=%d msg=%s" % (msg.device_id, msg.address, HMTLprotocol.decode_data(data)
))
        modules.append(msg)
    else:
        logger.log("Not a poll response, class: %s " % (msg.__class__.__name__))


def poll_one(client, modules, hmtladdress, verbose=True):
    if verbose:
        logger.log("Polling address: %d" % (hmtladdress))
    msg = HMTLprotocol.get_poll_msg(hmtladdress)
    (messages, headers) = client.send_and_ack(msg, True)
    if messages and messages[0] is not None:
        handle_poll_resp(messages[0], modules)
        return True
    else:
        if verbose:
            logger.log("No response from: %d" % (hmtladdress))
        return False


def scan_every(client):
    modules = []
    for address in range(0,255):
        if poll_one(client, modules, address):
            print("Modules: %s" % [(msg.device_id, msg.address) for msg in modules])
    return modules


def scan_broadcast(client):
    modules = []
    msg = HMTLprotocol.get_poll_msg(HMTLprotocol.BROADCAST)
    
    ret = client.send_and_ack(msg, False)
    while (True):
        msg = client.get_response_data()
        if (msg == None):
            break
        handle_poll_resp(msg, modules)

    return modules
    

def main():
    global logger
    logger = TimedLogger()

    (options, args) = handle_args()

    client = HMTLClient(address=options.address, port=options.port, hmtladdress=options.hmtladdress)

    if options.hmtladdress:
        modules = []
        poll_one(client, modules, options.hmtladdress)
    elif options.scanevery:
        modules = scan_every(client)
    else:
        modules = scan_broadcast(client)

    client.close()

    logger.log("\nFound %d modules:" % (len(modules)))
    logger.log("  %s" % (HMTLprotocol.PollHdr.headers()))
    for m in modules:
        logger.log("  %s" % (m.dump()))

    exit(0)

main()
