# Copyright 2017-2018, 2020-2025 NXP
# SPDX-License-Identifier: BSD-3-Clause

# -*- coding: utf-8 -*-
"""
    Base class for all flash programmer class

Copyright 2016 Freescale Semiconductor, Inc.
"""


from gdb import Command   # @UnresolvedImport  # pylint: disable=F0401
from time import time

from flash.scripts.remote import execute_remote
from flash.scripts.remote import cancel_execute_remote
from flash.scripts.utils import CwFlashProgressBar
from flash.scripts.utils import gdb_execute

from errors import Result, Error, ErrorCode
import shlex

###################################################################
######### flash programmer dump command
###################################################################
class CwFlashBase(Command):
    """
        Base class for all Flash Programmer commands
    """

    def __init__(self, cmd_name, gdb_command_class, gdb_complete_class):
        super(CwFlashBase, self).__init__(cmd_name,
            gdb_command_class, gdb_complete_class)
        self._parser = None
        self._progress = None
        self._args = None
        self._output = None
        self._t_execution = 0
        self._time = 0
        
        self.HSE_limits = None
        self.is_crc_implemented = False

    def invoke(self, arguments, from_tty):
        """
            Forward call to implementation dependent command with argument
            Implicitly call don't repeat to avoid that command be repeated
            when user enters a blank line
        """
        self.dont_repeat()

        try:
            self._args = self._parser.parse_args(shlex.split(arguments))
        except SystemExit as e:
            if e.code != 0:
                Result(Error(ErrorCode.FlashParameterError, str(e)))
            return
            
        self.can_execute(self._args)

        self.begin_command()
        self.show_progress_bar()

        try:
            self.__invoke(self._args, from_tty)
        except BaseException as e:
            cancel_execute_remote(from_tty)
            Result(Error(ErrorCode.FlashUndefinedError, str(e)))
        finally:
            self.end_progress_bar()

        self.show_result()
        self.end_command()

    def can_execute(self, args):
        """
            Allow child class to throw an exception in case execution prerequisites
            are not met.
        """
        pass

    def get_probe(self):
        """
            Call this to get the current probe
        """
        return gdb_execute("mon ctx id :ccs get prop probe", to_string = True)

    def is_rcw_area(self, offset):
        """
            Offset is in RCW area
        """
        return (offset >=0) and (offset < 0x100)

    def dont_repeat(self):
        """
            Call this in case that the command should not be repeated
            when user enter a blank line at command prompt
        """
        Command.dont_repeat(self)

    def complete(self, text, word):
        """
            Method called by GDB when user attempts to complete this command
            Right now do to gdb.COMPLETE_COMMAND flash sent in __init__ this
            method has less usefulness
        """
        Command.complete(text, word)

    def execute(self, args, from_tty):
        """
            Method called to actually execute a command with
            given parameters. A new command should overwrite this method
            to implement the expected behaviour or to format the specific
            remote command
        """
        pass

    def show_progress_bar(self):
        """
            Method used to instantiate and start a progress bar feature.
            For commands which doesn't require a progress bar simply overwrite
            this method with one with and empty body
        """
        # Create and start the progress bar
        self._progress = CwFlashProgressBar()
        self._progress.start_progress_bar()

    def end_progress_bar(self):
        """
            Method used to terminate command progress.
            This method should be overwrite by a subclass if a progress isn't
            required
        """
        # End progress bar
        self._progress.end_progress_bar()

    def show_result(self):
        """
            General method to gather command result and format it and then
            send it to a stream
            A subclass should overwrite this method accordingly.
        """
        pass

    def begin_command(self):
        """
            General method used to do all particular stuff related to
            beginning procedure of a method. Should be overwrite accordingly
            by a subclass.
        """
        pass

    def end_command(self):
        """
            General method used to do all particular stuff related to
            ending procedure of a method. Should be overwrite accordingly
            by a subclass.
        """
        pass

    def __invoke(self, args, from_tty):
        """
            Internal method
        """
        t_start = time()
        self.execute(args, from_tty)
        t_end = time()
        self._time = t_end - t_start
