# 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):
        self.require(self.xt_ocd_dir)
        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):
        if self.gdb_cmd is None:
            raise ValueError('Cannot debug; no gdb specified')
        self.require(self.gdb_cmd)
        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')
        self.require(self.gdb_cmd)

        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)
