#! /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:
        return 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)
    return 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
