#! /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 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
