#! /usr/bin/env python3

# Copyright (c) 2017 Linaro Limited.
# Copyright (c) 2017 Open Source Foundries Limited.
#
# SPDX-License-Identifier: Apache-2.0

"""Zephyr flash/debug script

This helper script is the build system's entry point to Zephyr's
"runner" Python package. This package provides ZephyrBinaryRunner,
which is a standard interface for flashing and debugging boards
supported by Zephyr, as well as backend-specific scripts for tools
such as OpenOCD, pyOCD, etc.
"""

import argparse
import functools
import sys
import os

from runner.core import ZephyrBinaryRunner


def print_runners_handler(args):
    for cls in ZephyrBinaryRunner.get_runners():
        print(cls.name())


def runner_handler(cls, args):
    runner = cls.create_from_args(args)
    # This relies on ZephyrBinaryRunner.add_parser() having command as
    # its single positional argument; see its docstring for details.
    runner.run(args.command)


def main():
    # Argument handling is split into a two-level structure, with
    # common options to the script first, then a sub-command (i.e.  a
    # runner name), then options and arguments for that sub-command
    # (like 'flash --some-option=value').
    #
    # For top-level help (including a list of runners), run:
    #
    # $ZEPHYR_BASE/.../SCRIPT.py -h
    #
    # For help on a particular RUNNER (like 'pyocd'), run:
    #
    # $ZEPHYR_BASE/.../SCRIPT.py RUNNER -h
    #
    # For verbose output, use:
    #
    # $ZEPHYR_BASE/.../SCRIPT.py [-v|--verbose] RUNNER [--runner-options]
    #
    # Note that --verbose comes *before* RUNNER, not after!
    #
    # Other commands (for now just the "runners" command, which prints
    # the available runners) are handled the same way:
    #
    # $ZEPHYR_BASE/.../SCRIPT.py runners
    top_parser = argparse.ArgumentParser()
    top_parser.add_argument('-v', '--verbose',
                            default=False, action='store_true',
                            help='If set, enable verbose output.')
    sub_parsers = top_parser.add_subparsers(dest='top_command')

    # Handlers for each subcommand.
    handlers = {}

    # The 'runners' command just prints the runners. It takes no arguments.
    sub_parsers.add_parser('runners')
    handlers['runners'] = print_runners_handler

    # Add a sub-command for each runner. (It's a bit hackish for runners
    # to know about argparse, but it's good enough for now.)
    for cls in ZephyrBinaryRunner.get_runners():
        if cls.name() in handlers:
            print('Runner {} name is already a top-level command'.format(
                      cls.name()),
                  file=sys.sterr)
            sys.exit(1)
        sub_parser = sub_parsers.add_parser(cls.name())
        cls.add_parser(sub_parser)
        handlers[cls.name()] = functools.partial(runner_handler, cls)

    args = top_parser.parse_args()
    if "VERBOSE" in os.environ:
        args.verbose = 1

    if args.top_command is None:
        choices = ', '.join(handlers.keys())
        print('Missing command or runner; choices: {}'.format(choices),
              file=sys.stderr)
        sys.exit(1)
    try:
        handlers[args.top_command](args)
    except Exception as e:
        if args.verbose:
            raise
        else:
            print('Error: {}'.format(e), file=sys.stderr)
            print(('(Re-run as "{} --verbose {} ..." '
                   'or set CMAKE_VERBOSE_MAKEFILE for a stack trace.)').format(
                       sys.argv[0], args.top_command),
                  file=sys.stderr)
            sys.exit(1)


if __name__ == '__main__':
    main()
