#!/usr/bin/env python

import argparse
import asyncio
import logging
import os
import sys

import cmdr

from upb_lib import UpbPim

LOG = logging.getLogger(__name__)


class StdOutWrapper:
    def __init__(self, cmdr):
        sys.stdout = self
        sys.stderr = self
        self.cmdr = cmdr
        self.log = None

    def write(self, txt):
        txt = txt.rstrip()
        if len(txt) > 0:
            self.cmdr.output(txt)
            if self.log:
                print(txt, file=self.log)

    def flush(self):
        pass


class SmartFormatter(argparse.HelpFormatter):
    def _split_lines(self, text, width):
        if text.startswith("R|"):
            return text[2:].splitlines()
        return argparse.HelpFormatter._split_lines(self, text, width)


def parse_args():
    parser = argparse.ArgumentParser("pim", formatter_class=SmartFormatter)

    parser.add_argument(
        "-i",
        "--interactive",
        action="store_true",
        default=False,
        dest="interactive",
        help="Run in interactive mode (type help for more info)",
    )
    parser.add_argument(
        "-u",
        "--url",
        action="store",
        dest="url",
        help=(
            "R|URL to connect to in one of the following formats:\n"
            "  tcp://host[:port] -- connect to PIM over Ethernet\n"
            "  serial://port[:baud] -- connect to PIM over serial port\n"
        ),
    )
    parser.add_argument(
        "-x",
        "--tx_count",
        type=int,
        action="store",
        dest="tx_count",
        help=("The number of times every UPB message is transmitted.\n"),
    )
    parser.add_argument(
        "-f",
        "--flags",
        action="store",
        dest="flags",
        help=("A comma separated list of key=value flags to pass to the PIM.\n"),
    )

    results = parser.parse_args()
    return results


async def main():
    config = {}

    args = parse_args()
    url = args.url if args.url else os.environ.get("UPBPIM_URL")
    if url:
        config["url"] = url
    if args.tx_count:
        config["tx_count"] = args.tx_count
    if args.flags:
        config["flags"] = args.flags
    config["UPStartExportFile"] = "bin/upb.upe"

    pim = UpbPim(config)

    console = None
    if args.interactive:
        console = cmdr.Commander("PIM console", cmd_cb=cmdr.Commands(pim))
        stream = sys.stdout
        stream = StdOutWrapper(console)
        logging.basicConfig(
            stream=stream,
            format="%(asctime)s.%(msecs)03d %(levelname)s  %(message)s",
            datefmt="%Y-%m-%d %H:%M:%S",
            level=logging.DEBUG,
        )
    else:
        logging.basicConfig(
            format="%(asctime)s.%(msecs)03d %(levelname)s  %(message)s",
            datefmt="%Y-%m-%d %H:%M:%S",
            level=logging.DEBUG,
        )

    try:
        await pim.load_upstart_file()
        await pim.async_connect()
        if args.interactive and console:
            console.loop()
        else:
            await asyncio.Event().wait()  # wait forever
    except (asyncio.CancelledError, KeyboardInterrupt) as _:
        exit(0)


if __name__ == "__main__":
    asyncio.run(main())
