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

'''Runner for debugging with J-Link.'''

from .core import ZephyrBinaryRunner, RunnerCaps

DEFAULT_JLINK_GDB_PORT = 2331


class JLinkBinaryRunner(ZephyrBinaryRunner):
    '''Runner front-end for the J-Link GDB server.'''

    def __init__(self, device,
                 gdbserver='JLinkGDBServer', iface='swd', speed='auto',
                 elf_name=None, gdb=None, gdb_port=DEFAULT_JLINK_GDB_PORT,
                 tui=False, debug=False):
        super(JLinkBinaryRunner, self).__init__(debug=debug)
        self.device = device
        self.gdbserver_cmd = [gdbserver]
        self.iface = iface
        self.speed = speed
        self.elf_name = elf_name
        self.gdb_cmd = [gdb] if gdb is not None else None
        self.gdb_port = gdb_port
        self.tui_arg = ['-tui'] if tui else []

    @classmethod
    def name(cls):
        return 'jlink'

    @classmethod
    def capabilities(cls):
        return RunnerCaps(commands={'debug', 'debugserver'})

    @classmethod
    def do_add_parser(cls, parser):
        # Required:
        parser.add_argument('--device', required=True, help='device name')

        # Optional:
        parser.add_argument('--iface', default='swd',
                            help='interface to use, default is swd')
        parser.add_argument('--speed', default='auto',
                            help='interface speed, default is autodetect')
        parser.add_argument('--tui', default=False, action='store_true',
                            help='if given, GDB uses -tui')
        parser.add_argument('--gdbserver', default='JLinkGDBServer',
                            help='GDB server, default is JLinkGDBServer')
        parser.add_argument('--gdb-port', default=DEFAULT_JLINK_GDB_PORT,
                            help='pyocd gdb port, defaults to {}'.format(
                                DEFAULT_JLINK_GDB_PORT))

    @classmethod
    def create_from_args(cls, args):
        return JLinkBinaryRunner(args.device, gdbserver=args.gdbserver,
                                 iface=args.iface, speed=args.speed,
                                 elf_name=args.kernel_elf,
                                 gdb=args.gdb, gdb_port=args.gdb_port,
                                 tui=args.tui, debug=args.verbose)

    def print_gdbserver_message(self):
        print('J-Link GDB server running on port {}'.format(self.gdb_port))

    def do_run(self, command, **kwargs):
        server_cmd = (self.gdbserver_cmd +
                      ['-select', 'usb', # only USB connections supported
                       '-port', str(self.gdb_port),
                       '-if', self.iface,
                       '-speed', self.speed,
                       '-device', self.device,
                       '-silent',
                       '-singlerun'])

        if command == 'debugserver':
            self.print_gdbserver_message()
            self.check_call(server_cmd)
        else:
            if self.gdb_cmd is None:
                raise ValueError('Cannot debug; gdb is missing')
            if self.elf_name is None:
                raise ValueError('Cannot debug; elf is missing')
            client_cmd = (self.gdb_cmd +
                          self.tui_arg +
                          [self.elf_name] +
                          ['-ex', 'target remote :{}'.format(self.gdb_port),
                           '-ex', 'monitor halt',
                           '-ex', 'monitor reset',
                           '-ex', 'load'])
            self.print_gdbserver_message()
            self.run_server_and_client(server_cmd, client_cmd)
