# Copyright (c) 2018 Intel Corporation.
# Copyright 2018 Open Source Foundries Limited.
#
# SPDX-License-Identifier: Apache-2.0

'''Runner for debugging and flashing Intel S1000 CRB'''
from os import path
import time
import signal
from west import log

from runners.core import ZephyrBinaryRunner

DEFAULT_XT_GDB_PORT = 20000


class IntelS1000BinaryRunner(ZephyrBinaryRunner):
    '''Runner front-end for Intel S1000.'''

    def __init__(self, cfg, xt_ocd_dir,
                 ocd_topology, ocd_jtag_instr, gdb_flash_file,
                 gdb_port=DEFAULT_XT_GDB_PORT):
        super(IntelS1000BinaryRunner, self).__init__(cfg)
        self.board_dir = cfg.board_dir
        self.elf_name = cfg.elf_file
        self.gdb_cmd = cfg.gdb
        self.xt_ocd_dir = xt_ocd_dir
        self.ocd_topology = ocd_topology
        self.ocd_jtag_instr = ocd_jtag_instr
        self.gdb_flash_file = gdb_flash_file
        self.gdb_port = gdb_port

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

    @classmethod
    def do_add_parser(cls, parser):
        # Optional
        parser.add_argument(
            '--xt-ocd-dir', default='/opt/tensilica/xocd-12.0.4/xt-ocd',
            help='ocd-dir, defaults to /opt/tensilica/xocd-12.0.4/xt-ocd')
        parser.add_argument(
            '--ocd-topology', default='topology_dsp0_flyswatter2.xml',
            help='ocd-topology, defaults to topology_dsp0_flyswatter2.xml')
        parser.add_argument(
            '--ocd-jtag-instr', default='dsp0_gdb.txt',
            help='ocd-jtag-instr, defaults to dsp0_gdb.txt')
        parser.add_argument(
            '--gdb-flash-file', default='load_elf.txt',
            help='gdb-flash-file, defaults to load_elf.txt')
        parser.add_argument(
            '--gdb-port', default=DEFAULT_XT_GDB_PORT,
            help='xt-gdb port, defaults to 20000')

    @classmethod
    def create(cls, cfg, args):
        return IntelS1000BinaryRunner(
            cfg, args.xt_ocd_dir,
            args.ocd_topology, args.ocd_jtag_instr, args.gdb_flash_file,
            gdb_port=args.gdb_port)

    def do_run(self, command, **kwargs):
        kwargs['ocd-topology'] = path.join(self.board_dir, 'support',
                                           self.ocd_topology)
        kwargs['ocd-jtag-instr'] = path.join(self.board_dir, 'support',
                                             self.ocd_jtag_instr)
        kwargs['gdb-flash-file'] = path.join(self.board_dir, 'support',
                                             self.gdb_flash_file)

        if command == 'flash':
            self.flash(**kwargs)
        elif command == 'debugserver':
            self.debugserver(**kwargs)
        else:
            self.do_debug(**kwargs)

    def flash(self, **kwargs):
        topology_file = kwargs['ocd-topology']
        jtag_instr_file = kwargs['ocd-jtag-instr']
        gdb_flash_file = kwargs['gdb-flash-file']

        self.print_gdbserver_message(self.gdb_port)
        server_cmd = [self.xt_ocd_dir,
                      '-c', topology_file,
                      '-I', jtag_instr_file]

        # Start the server
        # Note that XTOCD takes a few seconds to execute and always fails the
        # first time. It has to be relaunched the second time to work.
        server_proc = self.popen_ignore_int(server_cmd)
        time.sleep(6)
        server_proc.terminate()
        server_proc = self.popen_ignore_int(server_cmd)
        time.sleep(6)

        # Start the client
        gdb_cmd = [self.gdb_cmd, '-x', gdb_flash_file]
        client_proc = self.popen_ignore_int(gdb_cmd)

        # Wait for 3 seconds (waiting for XTGDB to finish loading the image)
        time.sleep(3)

        # At this point, the ELF image is loaded and the program is in
        # execution. Now we can quit the client (xt-gdb) and the server
        # (xt-ocd) as they are not needed anymore. The loaded program
        # (ELF) will continue to run though.
        client_proc.terminate()
        server_proc.terminate()

    def do_debug(self, **kwargs):
        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')

        topology_file = kwargs['ocd-topology']
        jtag_instr_file = kwargs['ocd-jtag-instr']

        self.print_gdbserver_message(self.gdb_port)
        server_cmd = [self.xt_ocd_dir,
                      '-c', topology_file,
                      '-I', jtag_instr_file]

        # Start the server
        # Note that XTOCD takes a few seconds to execute and always fails the
        # first time. It has to be relaunched the second time to work.
        server_proc = self.popen_ignore_int(server_cmd)
        time.sleep(6)
        server_proc.terminate()
        server_proc = self.popen_ignore_int(server_cmd)
        time.sleep(6)

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

        # Start the client
        # The below statement will consume the "^C" keypress ensuring
        # the python main application doesn't exit. This is important
        # since ^C in gdb means a "halt" operation.
        previous = signal.signal(signal.SIGINT, signal.SIG_IGN)
        try:
            self.check_call(gdb_cmd)
        finally:
            signal.signal(signal.SIGINT, previous)
            server_proc.terminate()
            server_proc.wait()

    def print_gdbserver_message(self, gdb_port):
        log.inf('Intel S1000 GDB server running on port {}'.format(gdb_port))

    def debugserver(self, **kwargs):
        topology_file = kwargs['ocd-topology']
        jtag_instr_file = kwargs['ocd-jtag-instr']

        self.print_gdbserver_message(self.gdb_port)
        server_cmd = [self.xt_ocd_dir,
                      '-c', topology_file,
                      '-I', jtag_instr_file]

        # Note that XTOCD takes a few seconds to execute and always fails the
        # first time. It has to be relaunched the second time to work.
        server_proc = self.popen_ignore_int(server_cmd)
        time.sleep(6)
        server_proc.terminate()
        self.check_call(server_cmd)
