#!/usr/bin/python3

import argparse
import logging
import sys
from xmlrpc.server import SimpleXMLRPCServer
import attenuator

DEFAULT_PORT = "8231"

logging.basicConfig(level=logging.INFO, format='%(levelname)s %(message)s')
LOG = logging.getLogger("att_ctrl_srv")

# Array of attenuator devices and their i2c bus and gpio pin numbers.
attenuators = [
    attenuator.Attenuator(
        attenuator.Pin(0x20, 1),
        attenuator.Pin(0x20, 2),
        attenuator.Pin(0x20, 3),
        attenuator.Pin(0x20, 4),
        attenuator.Pin(0x20, 5),
        attenuator.Pin(0x20, 6)
    ),
    attenuator.Attenuator(
        attenuator.Pin(0x20, 7),
        attenuator.Pin(0x20, 8),
        attenuator.Pin(0x20, 9),
        attenuator.Pin(0x20, 10),
        attenuator.Pin(0x20, 11),
        attenuator.Pin(0x20, 12)
    ),
    attenuator.Attenuator(
        attenuator.Pin(0x20, 13),
        attenuator.Pin(0x20, 14),
        attenuator.Pin(0x20, 15),
        attenuator.Pin(0x20, 16),
        attenuator.Pin(0x21, 1),
        attenuator.Pin(0x21, 2)
    ),
    attenuator.Attenuator(
        attenuator.Pin(0x21, 3),
        attenuator.Pin(0x21, 4),
        attenuator.Pin(0x21, 5),
        attenuator.Pin(0x21, 6),
        attenuator.Pin(0x21, 7),
        attenuator.Pin(0x21, 8)
    ),
    attenuator.Attenuator(
        attenuator.Pin(0x21, 9),
        attenuator.Pin(0x21, 10),
        attenuator.Pin(0x21, 11),
        attenuator.Pin(0x21, 12),
        attenuator.Pin(0x21, 13),
        attenuator.Pin(0x21, 14)
    ),
    attenuator.Attenuator(
        attenuator.Pin(0x21, 15),
        attenuator.Pin(0x21, 16),
        attenuator.Pin(0x22, 1),
        attenuator.Pin(0x22, 2),
        attenuator.Pin(0x22, 3),
        attenuator.Pin(0x22, 4)
    ),
    attenuator.Attenuator(
        attenuator.Pin(0x22, 5),
        attenuator.Pin(0x22, 6),
        attenuator.Pin(0x22, 7),
        attenuator.Pin(0x22, 8),
        attenuator.Pin(0x22, 9),
        attenuator.Pin(0x22, 10)
    ),
    attenuator.Attenuator(
        attenuator.Pin(0x22, 11),
        attenuator.Pin(0x22, 12),
        attenuator.Pin(0x22, 13),
        attenuator.Pin(0x22, 14),
        attenuator.Pin(0x22, 15),
        attenuator.Pin(0x22, 16)
    ),
]

def parse_args():
    """Command line argument parser"""
    parser = argparse.ArgumentParser()
    parser.add_argument("host", help="Hostname or ip address the server is \
                        serving on. (e.g. 'attctrl:8231 or 192.168.1.16'")

    return parser.parse_args()

def host_port(data):
    '''Determine hostname/address and port.

    Args:
        data (str): Hostname/address with optional port (e.g. 'localhost:1234'
                    or '192.168.0.1').

    Returns:
        str: Hostname/address
        str: Port
    '''
    tmp = data.split(":")
    port = DEFAULT_PORT
    host = tmp[0]

    if len(tmp) > 1:
        port = tmp[1]
    return host, port

def set_attenuation(attenuator, attenuation):
    """Set the attenuation of the choosen attenuator
    
    Args:
        attenuator (int):       Index of the attenuator device [0..8]
        attenuation (float):    Value of attenuation to be set [0.0..31.5]
    """
    try:
        dev = int(attenuator)
    except ValueError:
        LOG.error("attenuator needs to be convertible into int.")
        return 1
    try:
        val = float(attenuation)
    except ValueError:
        LOG.error("attenuation needs to be convertible into float.")
        return 1

    attenuators[dev].set_attenuation(val)
    LOG.info("xmlrpcserver: set attenuation of attenuator {} to {}".format(attenuator, attenuation))
    return 0

def main():
    args = parse_args()
    host, port = host_port(args.host)
    server = SimpleXMLRPCServer((host, int(port)))
    server.register_function(set_attenuation)
    LOG.info("xmlrpcserver: registering 'set_attenuation'.")
    try:
        LOG.info("xmlrpcserver: start serving on %s:%s.", str(host), str(port))
        server.serve_forever()
    except KeyboardInterrupt:
        LOG.info("xmlrpcserver: Keyboard interrupt catched - shutting down.")
        return 0

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