# Copyright 2023 NXP
# SPDX-License-Identifier: Apache-2.0
"""
Runner for NXP S32 Debug Probe.
"""

import argparse
import os
import platform
import re
import shlex
import subprocess
import sys
import tempfile
from dataclasses import dataclass
from pathlib import Path
from typing import Dict, List, Optional, Union

from runners.core import (BuildConfiguration, RunnerCaps, RunnerConfig,
                          ZephyrBinaryRunner)

NXP_S32DBG_USB_CLASS = 'NXP Probes'
NXP_S32DBG_USB_VID = 0x15a2
NXP_S32DBG_USB_PID = 0x0067


@dataclass
class NXPS32DebugProbeConfig:
    """NXP S32 Debug Probe configuration parameters."""
    conn_str: str = 's32dbg'
    server_port: int = 45000
    speed: int = 16000
    remote_timeout: int = 30
    reset_type: Optional[str] = 'default'
    reset_delay: int = 0


class NXPS32DebugProbeRunner(ZephyrBinaryRunner):
    """Runner front-end for NXP S32 Debug Probe."""

    def __init__(self,
                 runner_cfg: RunnerConfig,
                 probe_cfg: NXPS32DebugProbeConfig,
                 core_name: str,
                 soc_name: str,
                 soc_family_name: str,
                 start_all_cores: bool,
                 s32ds_path: Optional[str] = None,
                 tool_opt: Optional[List[str]] = None) -> None:
        super(NXPS32DebugProbeRunner, self).__init__(runner_cfg)
        self.elf_file: str = runner_cfg.elf_file or ''
        self.probe_cfg: NXPS32DebugProbeConfig = probe_cfg
        self.core_name: str = core_name
        self.soc_name: str = soc_name
        self.soc_family_name: str = soc_family_name
        self.start_all_cores: bool = start_all_cores
        self.s32ds_path_override: Optional[str] = s32ds_path

        self.tool_opt: List[str] = []
        if tool_opt:
            for opt in tool_opt:
                self.tool_opt.extend(shlex.split(opt))

        build_cfg = BuildConfiguration(runner_cfg.build_dir)
        self.arch = build_cfg.get('CONFIG_ARCH').replace('"', '')

    @classmethod
    def name(cls) -> str:
        return 'nxp_s32dbg'

    @classmethod
    def capabilities(cls) -> RunnerCaps:
        return RunnerCaps(commands={'debug', 'debugserver', 'attach'},
                          dev_id=True, tool_opt=True)

    @classmethod
    def dev_id_help(cls) -> str:
        return '''Debug probe connection string as in "s32dbg[:<address>]"
                  where <address> can be the IP address if TAP is available via Ethernet,
                  the serial ID of the probe or empty if TAP is available via USB.'''

    @classmethod
    def tool_opt_help(cls) -> str:
        return '''Additional options for GDB client when used with "debug" or "attach" commands
                  or for GTA server when used with "debugserver" command.'''

    @classmethod
    def do_add_parser(cls, parser: argparse.ArgumentParser) -> None:
        parser.add_argument('--core-name',
                            required=True,
                            help='Core name as supported by the debug probe (e.g. "R52_0_0")')
        parser.add_argument('--soc-name',
                            required=True,
                            help='SoC name as supported by the debug probe (e.g. "S32Z270")')
        parser.add_argument('--soc-family-name',
                            required=True,
                            help='SoC family name as supported by the debug probe (e.g. "s32z2e2")')
        parser.add_argument('--start-all-cores',
                            action='store_true',
                            help='Start all SoC cores and not just the one being debugged. '
                                 'Use together with "debug" command.')
        parser.add_argument('--s32ds-path',
                            help='Override the path to NXP S32 Design Studio installation. '
                                 'By default, this runner will try to obtain it from the system '
                                 'path, if available.')
        parser.add_argument('--server-port',
                            default=NXPS32DebugProbeConfig.server_port,
                            type=int,
                            help='GTA server port')
        parser.add_argument('--speed',
                            default=NXPS32DebugProbeConfig.speed,
                            type=int,
                            help='JTAG interface speed')
        parser.add_argument('--remote-timeout',
                            default=NXPS32DebugProbeConfig.remote_timeout,
                            type=int,
                            help='Number of seconds to wait for the remote target responses')

    @classmethod
    def do_create(cls, cfg: RunnerConfig, args: argparse.Namespace) -> 'NXPS32DebugProbeRunner':
        probe_cfg = NXPS32DebugProbeConfig(args.dev_id,
                                           server_port=args.server_port,
                                           speed=args.speed,
                                           remote_timeout=args.remote_timeout)

        return NXPS32DebugProbeRunner(cfg, probe_cfg, args.core_name, args.soc_name,
                                      args.soc_family_name, args.start_all_cores,
                                      s32ds_path=args.s32ds_path, tool_opt=args.tool_opt)

    @staticmethod
    def find_usb_probes() -> List[str]:
        """Return a list of debug probe serial numbers connected via USB to this host."""
        # use system's native commands to enumerate and retrieve the USB serial ID
        # to avoid bloating this runner with third-party dependencies that often
        # require priviledged permissions to access the device info
        macaddr_pattern = r'(?:[0-9a-f]{2}[:]){5}[0-9a-f]{2}'
        if platform.system() == 'Windows':
            cmd = f'pnputil /enum-devices /connected /class "{NXP_S32DBG_USB_CLASS}"'
            serialid_pattern = f'instance id: +usb\\\\.*\\\\({macaddr_pattern})'
        else:
            cmd = f'lsusb -v -d {NXP_S32DBG_USB_VID:x}:{NXP_S32DBG_USB_PID:x}'
            serialid_pattern = f'iserial +.*({macaddr_pattern})'

        try:
            outb = subprocess.check_output(shlex.split(cmd), stderr=subprocess.DEVNULL)
            out = outb.decode('utf-8').strip().lower()
        except subprocess.CalledProcessError:
            raise RuntimeError('error while looking for debug probes connected')

        devices: List[str] = []
        if out and 'no devices were found' not in out:
            devices = re.findall(serialid_pattern, out)

        return sorted(devices)

    @classmethod
    def select_probe(cls) -> str:
        """
        Find debugger probes connected and return the serial number of the one selected.

        If there are multiple debugger probes connected and this runner is being executed
        in a interactive prompt, ask the user to select one of the probes.
        """
        probes_snr = cls.find_usb_probes()
        if not probes_snr:
            raise RuntimeError('there are no debug probes connected')
        elif len(probes_snr) == 1:
            return probes_snr[0]
        else:
            if not sys.stdin.isatty():
                raise RuntimeError(
                    f'refusing to guess which of {len(probes_snr)} connected probes to use '
                    '(Interactive prompts disabled since standard input is not a terminal). '
                    'Please specify a device ID on the command line.')

            print('There are multiple debug probes connected')
            for i, probe in enumerate(probes_snr, 1):
                print(f'{i}. {probe}')

            prompt = f'Please select one with desired serial number (1-{len(probes_snr)}): '
            while True:
                try:
                    value: int = int(input(prompt))
                except EOFError:
                    sys.exit(0)
                except ValueError:
                    continue
                if 1 <= value <= len(probes_snr):
                    break
            return probes_snr[value - 1]

    @property
    def runtime_environment(self) -> Optional[Dict[str, str]]:
        """Execution environment used for the client process."""
        if platform.system() == 'Windows':
            python_lib = (self.s32ds_path / 'S32DS' / 'build_tools' / 'msys32'
                        / 'mingw32' / 'lib' / 'python2.7')
            return {
                **os.environ,
                'PYTHONPATH': f'{python_lib}{os.pathsep}{python_lib / "site-packages"}'
            }

        return None

    @property
    def script_globals(self) -> Dict[str, Optional[Union[str, int]]]:
        """Global variables required by the debugger scripts."""
        return {
            '_PROBE_IP': self.probe_cfg.conn_str,
            '_JTAG_SPEED': self.probe_cfg.speed,
            '_GDB_SERVER_PORT': self.probe_cfg.server_port,
            '_RESET_TYPE': self.probe_cfg.reset_type,
            '_RESET_DELAY': self.probe_cfg.reset_delay,
            '_REMOTE_TIMEOUT': self.probe_cfg.remote_timeout,
            '_CORE_NAME': f'{self.soc_name}_{self.core_name}',
            '_SOC_NAME': self.soc_name,
            '_IS_LOGGING_ENABLED': False,
            '_FLASH_NAME': None,    # not supported
            '_SECURE_TYPE': None,   # not supported
            '_SECURE_KEY': None,    # not supported
        }

    def server_commands(self) -> List[str]:
        """Get launch commands to start the GTA server."""
        server_exec = str(self.s32ds_path / 'S32DS' / 'tools' / 'S32Debugger'
                          / 'Debugger' / 'Server' / 'gta' / 'gta')
        cmd = [server_exec, '-p', str(self.probe_cfg.server_port)]
        return cmd

    def client_commands(self) -> List[str]:
        """Get launch commands to start the GDB client."""
        if self.arch == 'arm':
            client_exec_name = 'arm-none-eabi-gdb-py'
        elif self.arch == 'arm64':
            client_exec_name = 'aarch64-none-elf-gdb-py'
        else:
            raise RuntimeError(f'architecture {self.arch} not supported')

        client_exec = str(self.s32ds_path / 'S32DS' / 'tools' / 'gdb-arm'
                          / 'arm32-eabi' / 'bin' / client_exec_name)
        cmd = [client_exec]
        return cmd

    def get_script(self, name: str) -> Path:
        """
        Get the file path of a debugger script with the given name.

        :param name: name of the script, without the SoC family name prefix
        :returns: path to the script
        :raises RuntimeError: if file does not exist
        """
        script = (self.s32ds_path / 'S32DS' / 'tools' / 'S32Debugger' / 'Debugger' / 'scripts'
                  / self.soc_family_name / f'{self.soc_family_name}_{name}.py')
        if not script.exists():
            raise RuntimeError(f'script not found: {script}')
        return script

    def do_run(self, command: str, **kwargs) -> None:
        """
        Execute the given command.

        :param command: command name to execute
        :raises RuntimeError: if target architecture or host OS is not supported
        :raises MissingProgram: if required tools are not found in the host
        """
        if platform.system() not in ('Windows', 'Linux'):
            raise RuntimeError(f'runner not supported on {platform.system()} systems')

        if self.arch not in ('arm', 'arm64'):
            raise RuntimeError(f'architecture {self.arch} not supported')

        app_name = 's32ds' if platform.system() == 'Windows' else 's32ds.sh'
        self.s32ds_path = Path(self.require(app_name, path=self.s32ds_path_override)).parent

        if not self.probe_cfg.conn_str:
            self.probe_cfg.conn_str = f's32dbg:{self.select_probe()}'
            self.logger.info(f'using debug probe {self.probe_cfg.conn_str}')

        if command in ('attach', 'debug'):
            self.ensure_output('elf')
            self.do_attach_debug(command, **kwargs)
        else:
            self.do_debugserver(**kwargs)

    def do_attach_debug(self, command: str, **kwargs) -> None:
        """
        Launch the GTA server and GDB client to start a debugging session.

        :param command: command name to execute
        """
        gdb_script: List[str] = []

        # setup global variables required for the scripts before sourcing them
        for name, val in self.script_globals.items():
            gdb_script.append(f'py {name} = {repr(val)}')

        # load platform-specific debugger script
        if command == 'debug':
            if self.start_all_cores:
                startup_script = self.get_script('generic_bareboard_all_cores')
            else:
                startup_script = self.get_script('generic_bareboard')
        else:
            startup_script = self.get_script('attach')
        gdb_script.append(f'source {startup_script}')

        # executes the SoC and board initialization sequence
        if command == 'debug':
            gdb_script.append('py board_init()')

        # initializes the debugger connection to the core specified
        gdb_script.append('py core_init()')

        gdb_script.append(f'file {Path(self.elf_file).as_posix()}')
        if command == 'debug':
            gdb_script.append('load')

        with tempfile.TemporaryDirectory(suffix='nxp_s32dbg') as tmpdir:
            gdb_cmds = Path(tmpdir) / 'runner.nxp_s32dbg'
            gdb_cmds.write_text('\n'.join(gdb_script), encoding='utf-8')
            self.logger.debug(gdb_cmds.read_text(encoding='utf-8'))

            server_cmd = self.server_commands()
            client_cmd = self.client_commands()
            client_cmd.extend(['-x', gdb_cmds.as_posix()])
            client_cmd.extend(self.tool_opt)

            self.run_server_and_client(server_cmd, client_cmd, env=self.runtime_environment)

    def do_debugserver(self, **kwargs) -> None:
        """Start the GTA server on a given port with the given extra parameters from cli."""
        server_cmd = self.server_commands()
        server_cmd.extend(self.tool_opt)
        self.check_call(server_cmd)
