# Copyright (c) 2022-2024 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0

'''Runner for flashing with the Intel ADSP boards.'''

import argparse
import os
import sys
import re
import hashlib
import random
import shutil
from runners.core import ZephyrBinaryRunner, RunnerCaps
from zephyr_ext_common import ZEPHYR_BASE

DEFAULT_CAVSTOOL='soc/intel/intel_adsp/tools/cavstool_client.py'

class SignParamError(argparse.Action):
    'User-friendly feedback when trying to sign with west flash'
    def __call__(self, parser, namespace, values, option_string=None):
        parser.error(f'Cannot use "west flash {option_string} ..." any more. ' +
                     '"west sign" is now called from CMake, see "west sign -h"')

class IntelAdspBinaryRunner(ZephyrBinaryRunner):
    '''Runner front-end for the intel ADSP boards.'''

    def __init__(self,
                 cfg,
                 remote_host,
                 pty,
                 tool_opt,
                 ):
        super().__init__(cfg)

        self.remote_host = remote_host
        self.bin_fw = os.path.join(cfg.build_dir, 'zephyr', 'zephyr.ri')

        self.cavstool = os.path.join(ZEPHYR_BASE, DEFAULT_CAVSTOOL)
        self.platform = os.path.basename(cfg.board_dir)
        self.pty = pty

        self.tool_opt_args = tool_opt

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

    @classmethod
    def capabilities(cls):
        return RunnerCaps(commands={'flash'}, tool_opt=True)

    @classmethod
    def do_add_parser(cls, parser):
        parser.add_argument('--remote-host',
                            help='hostname of the remote targeting ADSP board')
        parser.add_argument('--pty', nargs='?', const="remote-host", type=str,
                            help=''''Capture the output of cavstool.py running on --remote-host \
                            and stream it remotely to west's standard output.''')

        for old_sign_param in [ '--rimage-tool', '--config-dir', '--default-key', '--key']:
            parser.add_argument(old_sign_param, action=SignParamError,
                            help='do not use, "west sign" is now called from CMake, see "west sign -h"')

    @classmethod
    def tool_opt_help(cls) -> str:
        return """Additional options for run/request service tool,
        e.g. '--lock' """

    @classmethod
    def do_create(cls, cfg, args):
        return IntelAdspBinaryRunner(cfg,
                                    remote_host=args.remote_host,
                                    pty=args.pty,
                                    tool_opt=args.tool_opt,
                                    )

    def do_run(self, command, **kwargs):
        self.logger.info('Starting Intel ADSP runner')

        if re.search("adsp", self.platform):
            self.require(self.cavstool)
            self.flash(**kwargs)
        else:
            self.logger.error("No suitable platform for running")
            sys.exit(1)

    def flash(self, **kwargs):
        'Generate a hash string for appending to the sending ri file'
        hash_object = hashlib.md5(self.bin_fw.encode())
        random_str = f"{random.getrandbits(64)}".encode()
        hash_object.update(random_str)
        send_bin_fw = str(self.bin_fw + "." + hash_object.hexdigest())
        shutil.copy(self.bin_fw, send_bin_fw)

        # Copy the zephyr to target remote ADSP host and run
        self.run_cmd = ([f'{self.cavstool}','-s', f'{self.remote_host}', f'{send_bin_fw}'])

        # Add the extra tool options to run/request service tool
        if self.tool_opt_args:
            self.run_cmd = self.run_cmd + self.tool_opt_args

        self.logger.debug(f"rcmd: {self.run_cmd}")

        self.check_call(self.run_cmd)

        # If the self.pty is assigned, the log will output to stdout
        # directly. That means you don't have to execute the command:
        #
        #   cavstool_client.py -s {host}:{port} -l
        #
        # to get the result later separately.
        if self.pty is not None:
            if self.pty == 'remote-host':
                self.log_cmd = ([f'{self.cavstool}','-s', f'{self.remote_host}', '-l'])
            else:
                self.log_cmd = ([f'{self.cavstool}','-s', f'{self.pty}', '-l'])

            self.logger.debug(f"rcmd: {self.log_cmd}")

            self.check_call(self.log_cmd)
