#! /usr/bin/env python3

import itertools
import os
import pathlib
import signal
import sys
import threading

import logging
logger = logging.getLogger("RunFVP")

# Add meta-arm/lib/ to path
libdir = pathlib.Path(__file__).parents[1] / "meta-arm" / "lib"
sys.path.insert(0, str(libdir))

from fvp import conffile, terminal, runner

def parse_args(arguments):
    import argparse
    terminals = terminal.terminals

    parser = argparse.ArgumentParser(description="Run images in a FVP")
    parser.add_argument("config", nargs="?", help="Machine name or path to .fvpconf file")
    group = parser.add_mutually_exclusive_group()
    group.add_argument("-t", "--terminals", choices=terminals.all_terminals(), default=terminals.preferred_terminal(), help="Automatically start terminals (default: %(default)s)")
    group.add_argument("-c", "--console", action="store_true", help="Attach the first uart to stdin/stdout")
    parser.add_argument("--verbose", action="store_true", help="Output verbose logging")
    parser.usage = f"{parser.format_usage().strip()} -- [ arguments passed to FVP ]"
    # TODO option for telnet vs netcat

    # If the arguments contains -- then everything after it should be passed to the FVP binary directly.
    if "--" in arguments:
        i = arguments.index("--")
        fvp_args = arguments[i+1:]
        arguments = arguments[:i]
    else:
        fvp_args = []

    args = parser.parse_args(args=arguments)
    logging.basicConfig(level=args.verbose and logging.DEBUG or logging.WARNING,
                        format='\033[G%(levelname)s: %(message)s')

    # If we're hooking up the console, don't start any terminals
    if args.console:
        args.terminals = "none"

    logger.debug(f"Parsed arguments: {vars(args)}")
    logger.debug(f"FVP arguments: {fvp_args}")
    return args, fvp_args

def start_fvp(args, fvpconf, extra_args):
    fvp = runner.FVPRunner(logger)
    try:
        fvp.start(fvpconf, extra_args, args.terminals)

        if args.console:
            config = fvp.getConfig()
            expected_terminal = config["consoles"].get("default")
            if expected_terminal is None:
                logger.error("--console used but FVP_CONSOLE not set in machine configuration")
                return 1
            port_stdout, log_stdout = itertools.tee(fvp.stdout, 2)
            parser = runner.ConsolePortParser(port_stdout)
            port = parser.parse_port(expected_terminal)

            def debug_log():
                for line in log_stdout:
                    line = line.strip().decode(errors='ignore')
                    logger.debug(f'FVP output: {line}')
            log_thread = threading.Thread(None, debug_log)
            log_thread.start()

            telnet = fvp.create_telnet(port)
            telnet.wait()
            logger.debug(f"Telnet quit, cancelling tasks")
        else:
            for line in fvp.stdout:
                print(line.strip().decode(errors='ignore'))

    finally:
        fvp.stop()


def runfvp(cli_args):
    args, extra_args = parse_args(cli_args)
    if args.config and pathlib.Path(args.config).exists():
        config_file = args.config
    else:
        config_file = conffile.find(args.config)
    start_fvp(args, config_file, extra_args)


if __name__ == "__main__":
    try:
        # Set the process group so that it's possible to kill runfvp and
        # everything it spawns easily.
        # Ignore permission errors happening when spawned from an other process
        # for example run from except
        try:
            os.setpgid(0, 0)
        except PermissionError:
            pass
        if sys.stdin.isatty():
            signal.signal(signal.SIGTTOU, signal.SIG_IGN)
            os.tcsetpgrp(sys.stdin.fileno(), os.getpgrp())
        sys.exit(runfvp(sys.argv[1:]))
    except KeyboardInterrupt:
        pass
