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

'''Runner for NIOS II, based on quartus-flash.py and GDB.'''

from os import path
import os

from .core import ZephyrBinaryRunner, NetworkPortHelper


class Nios2BinaryRunner(ZephyrBinaryRunner):
    '''Runner front-end for NIOS II.'''

    # From the original shell script:
    #
    #     "XXX [flash] only support[s] cases where the .elf is sent
    #      over the JTAG and the CPU directly boots from __start. CONFIG_XIP
    #      and CONFIG_INCLUDE_RESET_VECTOR must be disabled."

    def __init__(self, hex_name=None, elf_name=None, cpu_sof=None,
                 zephyr_base=None, gdb=None, tui=None, debug=False):
        super(Nios2BinaryRunner, self).__init__(debug=debug)
        self.hex_name = hex_name
        self.elf_name = elf_name
        self.cpu_sof = cpu_sof
        self.zephyr_base = zephyr_base
        self.gdb_cmd = [gdb] if gdb is not None else None
        self.tui_arg = [tui] if tui is not None else []

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

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

        Required for 'flash', 'debug':

        - O: build output directory

        Required for 'flash':

        - KERNEL_HEX_NAME: name of kernel binary in HEX format
        - NIOS2_CPU_SOF: location of the CPU .sof data
        - ZEPHYR_BASE: zephyr Git repository base directory

        Required for 'debug':

        - KERNEL_ELF_NAME: name of kernel binary in ELF format
        - GDB: GDB executable

        Optional for 'debug':

        - TUI: one additional argument to GDB (e.g. -tui)
        '''
        cpu_sof = os.environ.get('NIOS2_CPU_SOF', None)
        zephyr_base = os.environ.get('ZEPHYR_BASE', None)

        o = os.environ.get('O', None)
        hex_ = os.environ.get('KERNEL_HEX_NAME', None)
        elf = os.environ.get('KERNEL_ELF_NAME', None)
        hex_name = None
        elf_name = None
        if o is not None:
            if hex_ is not None:
                hex_name = path.join(o, hex_)
            if elf is not None:
                elf_name = path.join(o, elf)

        gdb = os.environ.get('GDB', None)
        tui = os.environ.get('TUI', None)

        return Nios2BinaryRunner(hex_name=hex_name, elf_name=elf_name,
                                 cpu_sof=cpu_sof, zephyr_base=zephyr_base,
                                 gdb=gdb, tui=tui, debug=debug)

    def do_run(self, command, **kwargs):
        if command == 'flash':
            self.flash(**kwargs)
        else:
            self.debug_debugserver(command, **kwargs)

    def flash(self, **kwargs):
        sof_msg = (
            'Cannot flash; '
            'Please set NIOS2_CPU_SOF variable to location of CPU .sof data')

        if self.zephyr_base is None:
            raise ValueError('Cannot flash; ZEPHYR_BASE is missing.')
        if self.cpu_sof is None:
            raise ValueError(sof_msg)
        if self.hex_name is None:
            raise ValueError('Cannot flash; .hex binary name is missing')

        cmd = [path.join(self.zephyr_base, 'scripts', 'support',
                         'quartus-flash.py'),
               '--sof', self.cpu_sof,
               '--kernel', self.hex_name]

        self.check_call(cmd)

    def print_gdbserver_message(self, gdb_port):
        print('Nios II GDB server running on port {}'.format(gdb_port))

    def debug_debugserver(self, command, **kwargs):
        # Per comments in the shell script, the NIOSII GDB server
        # doesn't exit gracefully, so it's better to explicitly search
        # for an unused port. The script picks a random value in
        # between 1024 and 49151, but we'll start with the
        # "traditional" 3333 choice.
        gdb_start = 3333
        nh = NetworkPortHelper()
        gdb_port = nh.get_unused_ports([gdb_start])[0]

        server_cmd = (['nios2-gdb-server',
                       '--tcpport', str(gdb_port),
                       '--stop', '--reset-target'])

        if command == 'debugserver':
            self.print_gdbserver_message(gdb_port)
            self.check_call(server_cmd)
        else:
            if self.elf_name is None:
                raise ValueError('Cannot debug; elf is missing')
            if self.gdb_cmd is None:
                raise ValueError('Cannot debug; no gdb specified')

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

            self.print_gdbserver_message(gdb_port)
            self.run_server_and_client(server_cmd, gdb_cmd)
