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

'''Runner for openocd.'''

from os import path
import os
import shlex

from .core import ZephyrBinaryRunner, get_env_or_bail, get_env_strip_or

DEFAULT_OPENOCD_TCL_PORT = 6333
DEFAULT_OPENOCD_TELNET_PORT = 4444
DEFAULT_OPENOCD_GDB_PORT = 3333


class OpenOcdBinaryRunner(ZephyrBinaryRunner):
    '''Runner front-end for openocd.'''

    def __init__(self, openocd_config,
                 openocd='openocd', default_path=None,
                 bin_name=None, elf_name=None,
                 load_cmd=None, verify_cmd=None, pre_cmd=None, post_cmd=None,
                 extra_init=None,
                 tcl_port=DEFAULT_OPENOCD_TCL_PORT,
                 telnet_port=DEFAULT_OPENOCD_TELNET_PORT,
                 gdb_port=DEFAULT_OPENOCD_GDB_PORT,
                 gdb=None, tui=None, debug=False):
        super(OpenOcdBinaryRunner, self).__init__(debug=debug)
        self.openocd_config = openocd_config

        search_args = []
        if default_path is not None:
            search_args = ['-s', default_path]
        self.openocd_cmd = [openocd] + search_args
        self.bin_name = bin_name
        self.elf_name = elf_name
        self.load_cmd = load_cmd
        self.verify_cmd = verify_cmd
        self.pre_cmd = pre_cmd
        self.post_cmd = post_cmd
        self.extra_init = extra_init if extra_init is not None else []
        self.tcl_port = tcl_port
        self.telnet_port = telnet_port
        self.gdb_port = gdb_port
        self.gdb_cmd = [gdb] if gdb is not None else None
        self.tui_arg = [tui] if tui is not None else []

    def replaces_shell_script(shell_script, command):
        return (command in {'flash', 'debug', 'debugserver'} and
                shell_script == 'openocd.sh')

    def create_from_env(command, debug):
        '''Create runner from environment.

        Required:

        - ZEPHYR_BASE: zephyr Git repository base directory
        - ARCH: board architecture
        - BOARD_NAME: zephyr name of board

        Optional:

        - OPENOCD: path to openocd, defaults to openocd
        - OPENOCD_DEFAULT_PATH: openocd search path to use

        Required for 'flash':

        - O: build output directory
        - KERNEL_BIN_NAME: zephyr kernel binary
        - OPENOCD_LOAD_CMD: command to load binary into flash
        - OPENOCD_VERIFY_CMD: command to verify flash executed correctly

        Optional for 'flash':

        - OPENOCD_PRE_CMD: command to run before any others
        - OPENOCD_POST_CMD: command to run after verifying flash write

        Required for 'debug':

        - GDB: GDB executable
        - O: build output directory
        - KERNEL_ELF_NAME: zephyr kernel binary, ELF format

        Optional for 'debug':

        - TUI: one additional argument to GDB (e.g. -tui)
        - OPENOCD_EXTRA_INIT: additional arguments to pass to openocd
        - TCL_PORT: openocd TCL port, defaults to 6333
        - TELNET_PORT: openocd telnet port, defaults to 4444
        - GDB_PORT: openocd gdb port, defaults to 3333
        '''
        zephyr_base = get_env_or_bail('ZEPHYR_BASE')
        arch = get_env_or_bail('ARCH')
        board_name = get_env_or_bail('BOARD_NAME')
        openocd_config = path.join(zephyr_base, 'boards', arch,
                                   board_name, 'support', 'openocd.cfg')

        openocd = os.environ.get('OPENOCD', 'openocd')
        default_path = os.environ.get('OPENOCD_DEFAULT_PATH', None)

        o = os.environ.get('O', None)
        bin_ = os.environ.get('KERNEL_BIN_NAME', None)
        elf = os.environ.get('KERNEL_ELF_NAME', None)
        bin_name = None
        elf_name = None
        if o is not None:
            if bin_ is not None:
                bin_name = path.join(o, bin_)
            if elf is not None:
                elf_name = path.join(o, elf)

        load_cmd = get_env_strip_or('OPENOCD_LOAD_CMD', '"', None)
        verify_cmd = get_env_strip_or('OPENOCD_VERIFY_CMD', '"', None)
        pre_cmd = get_env_strip_or('OPENOCD_PRE_CMD', '"', None)
        post_cmd = get_env_strip_or('OPENOCD_POST_CMD', '"', None)

        gdb = os.environ.get('GDB', None)
        tui = os.environ.get('TUI', None)
        extra_init = os.environ.get('OPENOCD_EXTRA_INIT', None)
        if extra_init is not None:
            extra_init = shlex.split(extra_init)
        tcl_port = int(os.environ.get('TCL_PORT',
                                      str(DEFAULT_OPENOCD_TCL_PORT)))
        telnet_port = int(os.environ.get('TELNET_PORT',
                                         str(DEFAULT_OPENOCD_TELNET_PORT)))
        gdb_port = int(os.environ.get('GDB_PORT',
                                      str(DEFAULT_OPENOCD_GDB_PORT)))

        return OpenOcdBinaryRunner(openocd_config,
                                   openocd=openocd, default_path=default_path,
                                   bin_name=bin_name, elf_name=elf_name,
                                   load_cmd=load_cmd, verify_cmd=verify_cmd,
                                   pre_cmd=pre_cmd, post_cmd=post_cmd,
                                   extra_init=extra_init, tcl_port=tcl_port,
                                   telnet_port=telnet_port, gdb_port=gdb_port,
                                   gdb=gdb, tui=tui, debug=debug)

    def run(self, command, **kwargs):
        if command not in {'flash', 'debug', 'debugserver'}:
            raise ValueError('{} is not supported'.format(command))

        if command == 'flash':
            self.do_flash(**kwargs)
        elif command == 'debug':
            self.do_debug(**kwargs)
        else:
            self.do_debugserver(**kwargs)

    def do_flash(self, **kwargs):
        if self.bin_name is None:
            raise ValueError('Cannot flash; binary name is missing')
        if self.load_cmd is None:
            raise ValueError('Cannot flash; load command is missing')
        if self.verify_cmd is None:
            raise ValueError('Cannot flash; verify command is missing')

        pre_cmd = []
        if self.pre_cmd is not None:
            pre_cmd = ['-c', self.pre_cmd]

        post_cmd = []
        if self.post_cmd is not None:
            post_cmd = ['-c', self.post_cmd]

        cmd = (self.openocd_cmd +
               ['-f', self.openocd_config,
                '-c', 'init',
                '-c', 'targets'] +
               pre_cmd +
               ['-c', 'reset halt',
                '-c', self.load_cmd,
                '-c', 'reset halt',
                '-c', self.verify_cmd] +
               post_cmd +
               ['-c', 'reset run',
                '-c', 'shutdown'])
        self.check_call(cmd)

    def do_debug(self, **kwargs):
        if self.gdb_cmd is None:
            raise ValueError('Cannot debug; no gdb specified')
        if self.elf_name is None:
            raise ValueError('Cannot debug; no .elf specified')

        server_cmd = (self.openocd_cmd +
                      ['-f', self.openocd_config] +
                      self.extra_init +
                      ['-c', 'tcl_port {}'.format(self.tcl_port),
                       '-c', 'telnet_port {}'.format(self.telnet_port),
                       '-c', 'gdb_port {}'.format(self.gdb_port),
                       '-c', 'init',
                       '-c', 'targets',
                       '-c', 'halt'])

        gdb_cmd = (self.gdb_cmd + self.tui_arg +
                   ['-ex', 'target remote :{}'.format(self.gdb_port),
                    self.elf_name])

        self.run_server_and_client(server_cmd, gdb_cmd)

    def do_debugserver(self, **kwargs):
        cmd = (self.openocd_cmd +
               ['-f', self.openocd_config,
                '-c', 'init',
                '-c', 'targets',
                '-c', 'reset halt'])
        self.check_call(cmd)
