#!/usr/bin/env python3

"""
This example configures CSP on the host machine and establishes a CSP route to
the DUT via KISS. Some of the prop functions are then demonstrated.

Refer to lib/prop-client/python/bindings/prop_client_python.c for a complete
list of available prop bindings and the function docstrings for more
information about a specific function.

Prerequisites:

Python bindings shall be enabled when building ``satctl`` and installed on the
system or in a virtual environment. See the ``README`` file for details.

The routing table on the DUT shall be configured to respond to node 5 via KISS,
the routing table below routes traffic to node 5 via KISS, and traffic to all
other nodes via CAN.

    [polaris] prop list sys
    Property        Type  Stat  Flag  Value
    ...
    csp.routes      str   B     -     0/0 CAN, 5/5 KISS
    ...
"""

import argparse

import csp


def example(args):
    if args.dut == 'ais':
        from satlab import polaris_ais_client
        dut_addr = polaris_ais_client.DEFAULT_ADDRESS  # 20
        client = polaris_ais_client.PolarisAIS()
    elif args.dut == 'adsb':
        from satlab import polaris_adsb_client
        dut_addr = polaris_adsb_client.DEFAULT_ADDRESS  # 23
        client = polaris_adsb_client.PolarisADSB()
    elif args.dut == 'srs3':
        from satlab import srs3_client
        dut_addr = srs3_client.DEFAULT_ADDRESS  # 21
        client = srs3_client.SRS3()
    elif args.dut == 'srs4':
        from satlab import srs4_client
        dut_addr = srs4_client.DEFAULT_ADDRESS  # 24
        client = srs4_client.SRS4()
    else:
        raise NotImplementedError(f"DUT {args.dut} not supported")

    host_csp_addr = 5

    csp.init(host_csp_addr)

    csp.kiss_init(args.kiss_device, args.kiss_rate)
    csp.route_start_task()
    # Route all packets to DUT via KISS
    csp.rtable_set(dut_addr, 5, 'KISS')

    # Get the can.rate prop found in the sys table
    default_rate = client.prop.get('sys.can.rate')
    print(f'Default CAN rate {default_rate}')
    # It is also possible to get the prop without using .get
    assert client.prop['sys.can.rate'] == default_rate
    # Setting the prop to something else, note that sys properties are not saved
    # unless prop.save() is called, changes in the sys table also only loaded on reboot.
    # The sys.can.rate prop is used in this example since it exists for all products.
    client.prop.set('sys.can.rate', 250000)
    print(f"CAN rate is now {client.prop['sys.can.rate']}")
    # setting it back to default
    client.prop.reset('sys.can.rate')
    assert client.prop['sys.can.rate'] == default_rate
    print(f"CAN rate is now back to {client.prop['sys.can.rate']}")

    # It is also possible to set and get multiple props with the same call.
    # NOTE: Some of these parameters do not exist on SRS products.
    if args.dut in ['ais', 'adsb']:
        ret = client.prop.get(['tm.temp.mcu', 'sys.net.ip'])
        default_ip = ret['sys.net.ip']

        client.prop.set(['conf.fs.mount', 'sys.net.ip'],
                        [True, '192.168.100.25'])

        print(f"Multi prop get {client.prop.get(['tm.temp.mcu', 'sys.net.ip'])}")

        # prop.set|get accept iterables as input
        client.prop.set({'conf.fs.mount': False, 'sys.net.ip': default_ip})

    # Unlock the sys prop group, save and load it, then lock it again
    client.prop.unlock('sys')
    client.prop.save('sys', fallback=False)
    client.prop.load('sys', fallback=False)
    client.prop.lock('sys')


def main():
    # Parse arguments
    parser = argparse.ArgumentParser()

    parser.add_argument('--dut', help='Target DUT', type=str, choices=['ais', 'adsb', 'srs3', 'srs4'], required=True)
    parser.add_argument('--kiss-device', help='Path to KISS device on host PC', type=str, default='/dev/ttyUSB1')
    parser.add_argument('--kiss-rate', help='Data rate of the KISS device, must match sys.uart.rate on DUT',
                        type=int, default=3000000)

    args = parser.parse_args()

    example(args)


if __name__ == '__main__':
    main()
