# Copyright 2023 NXP
# Copyright (c) 2017 Linaro Limited.
#
# SPDX-License-Identifier: Apache-2.0
#
# Based on jlink.py

'''Runner for debugging with NXP's LinkServer.'''

import logging
import os
import shlex
import subprocess
import sys

from runners.core import ZephyrBinaryRunner, RunnerCaps


DEFAULT_LINKSERVER_EXE = 'Linkserver.exe' if sys.platform == 'win32' else 'LinkServer'
DEFAULT_LINKSERVER_GDB_PORT =  3333
DEFAULT_LINKSERVER_SEMIHOST_PORT = 3334

class LinkServerBinaryRunner(ZephyrBinaryRunner):
    '''Runner front-end for NXP Linkserver'''
    def __init__(self, cfg, device, core,
                 linkserver=DEFAULT_LINKSERVER_EXE,
                 dt_flash=True, erase=True,
                 probe='#1',
                 gdb_host='',
                 gdb_port=DEFAULT_LINKSERVER_GDB_PORT,
                 semihost_port=DEFAULT_LINKSERVER_SEMIHOST_PORT,
                 override=[],
                 tui=False, tool_opt=[]):
        super().__init__(cfg)
        self.file = cfg.file
        self.file_type = cfg.file_type
        self.hex_name = cfg.hex_file
        self.bin_name = cfg.bin_file
        self.elf_name = cfg.elf_file
        self.gdb_cmd = cfg.gdb if cfg.gdb else None
        self.device = device
        self.core = core
        self.linkserver = linkserver
        self.dt_flash = dt_flash
        self.erase = erase
        self.probe = probe
        self.gdb_host = gdb_host
        self.gdb_port = gdb_port
        self.semihost_port = semihost_port
        self.tui_arg = ['-tui'] if tui else []
        self.override = override
        self.override_cli = self._build_override_cli()

        self.tool_opt = []
        for opts in [shlex.split(opt) for opt in tool_opt]:
            self.tool_opt += opts

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

    @classmethod
    def capabilities(cls):
        return RunnerCaps(commands={'flash', 'debug', 'debugserver', 'attach'},
                          dev_id=True, flash_addr=True, erase=True,
                          tool_opt=True, file=True)

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

        parser.add_argument('--core', required=False, help='core of the device')

        parser.add_argument('--probe', default='#1',
                            help='interface to use (index, or serial number, default is #1')

        parser.add_argument('--tui', default=False, action='store_true',
                            help='if given, GDB uses -tui')

        parser.add_argument('--gdb-port', default=DEFAULT_LINKSERVER_GDB_PORT,
                            help='gdb port to open, defaults to {}'.format(
                               DEFAULT_LINKSERVER_GDB_PORT))

        parser.add_argument('--semihost-port', default=DEFAULT_LINKSERVER_SEMIHOST_PORT,
                            help='semihost port to open, defaults to the empty string '
                            'and runs a gdb server')
        # keep this, we have to assume that the default 'commander' is on PATH
        parser.add_argument('--linkserver', default=DEFAULT_LINKSERVER_EXE,
                            help=f'''LinkServer executable, default is
                            {DEFAULT_LINKSERVER_EXE}''')
        # user may need to override settings.
        parser.add_argument('--override', required=False, action='append',
                            help=f'''configuration overrides as defined bylinkserver. Example: /device/memory/0/location=0xcafecafe''')

    @classmethod
    def do_create(cls, cfg, args):

        return LinkServerBinaryRunner(cfg, args.device, args.core,
                                 linkserver=args.linkserver,
                                 dt_flash=args.dt_flash,
                                 erase=args.erase,
                                 probe=args.probe,
                                 semihost_port=args.semihost_port,
                                 gdb_port=args.gdb_port,
                                 override=args.override,
                                 tui=args.tui, tool_opt=args.tool_opt)

    @property
    def linkserver_version_str(self):

        if not hasattr(self, '_linkserver_version'):
            linkserver_version_cmd=[self.linkserver, "-v"]
            ls_output=self.check_output(linkserver_version_cmd)
            self.linkserver_version = str(ls_output.split()[1].decode()).lower()

        return self.linkserver_version

    def do_run(self, command, **kwargs):

        self.linkserver = self.require(self.linkserver)
        self.logger.info(f'LinkServer: {self.linkserver}, version {self.linkserver_version_str}')

        if command == 'flash':
            self.flash(**kwargs)
        else:
            if self.core is not None:
                _cmd_core = [ "-c",  self.core ]
            else:
                _cmd_core = []

            linkserver_cmd = ([self.linkserver] +
                              ["gdbserver"]    +
                              ["--probe", str(self.probe) ] +
                              ["--gdb-port", str(self.gdb_port )] +
                              ["--semihost-port", str(self.semihost_port) ] +
                              _cmd_core +
                              self.override_cli +
                              [self.device])

            self.logger.debug(f'LinkServer cmd:  + {linkserver_cmd}')

            if command in ('debug', 'attach'):
                if self.elf_name is  None or not os.path.isfile(self.elf_name):
                    raise ValueError('Cannot debug; elf file required')

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

                if command == 'debug':
                    gdb_cmd += [ '-ex', 'load', '-ex', 'monitor reset']

                if command == 'attach':
                    linkserver_cmd += ['--attach']

                self.run_server_and_client(linkserver_cmd, gdb_cmd)

            elif command == 'debugserver':
                if self.gdb_host:
                    raise ValueError('Cannot run debugserver with --gdb-host')

                self.check_call(linkserver_cmd)

    def do_erase(self, **kwargs):

        if self.core is not None:
            _cmd_core = ":"+self.core
        else:
            _cmd_core = ""

        linkserver_cmd = ([self.linkserver, "flash"] + ["--probe", str(self.probe)] +
                          [self.device+_cmd_core] + ["erase"])
        self.logger.debug("flash erase command = " + str(linkserver_cmd))
        self.check_call(linkserver_cmd)

    def _build_override_cli(self):

        override_cli = []

        if self.override is not None:
            for ov in self.override:
                override_cli = (override_cli + ["-o", str(ov)])

        return override_cli

    def flash(self, **kwargs):

        if self.core is not None:
            _cmd_core = ":"+self.core
        else:
            _cmd_core = ""

        linkserver_cmd = ([self.linkserver, "flash"] + ["--probe", str(self.probe)] + self.override_cli + [self.device+_cmd_core])
        self.logger.debug(f'LinkServer cmd:  + {linkserver_cmd}')

        if self.erase:
            self.do_erase()

        if self.bin_name is not None and os.path.isfile(self.bin_name):
            if self.dt_flash:
                load_addr = self.flash_address_from_build_conf(self.build_conf)
            else:
                self.logger.critical("no load flash address could be found...")
                raise RuntimeError("no load flash address could be found...")

            flash_cmd = (["load", "--addr", str(load_addr), self.bin_name])
        else:
            err = 'Cannot flash; no bin ({}) file found.'
            raise ValueError(err.format(self.bin_name))

        # Flash the selected elf file
        linkserver_cmd = linkserver_cmd + flash_cmd
        self.logger.debug("flash command = " + str(linkserver_cmd))
        kwargs = {}
        if not self.logger.isEnabledFor(logging.DEBUG):
            if self.linkserver_version_str < "v1.3.15":
                kwargs['stderr'] = subprocess.DEVNULL
            else:
                kwargs['stdout'] = subprocess.DEVNULL

        self.check_call(linkserver_cmd, **kwargs)
