# 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, no 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())

        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):
            kwargs['stderr'] = subprocess.DEVNULL
        self.check_call(linkserver_cmd, **kwargs)
