# -*- coding: utf-8 -*-
"""
    Implementation of Flash Programmer erase command

Copyright 2015 Freescale Semiconductor, Inc.
Copyright 2017-2020, 2022, 2024-2025 NXP.

SPDX-License-Identifier: BSD-3-Clause

"""

import gdb   # @UnresolvedImport  # pylint: disable=F0401
import argparse

from flash.gdbcommands.base_command import CwFlashBase
from flash.gdbcommands.cmd_name import CMD_CW_FLASH_ERASE

from flash.scripts.utils import string_to_offset
from flash.scripts.utils import string_to_size
from flash.scripts.utils import size_to_human_readable
from flash.scripts.remote import execute_remote

from errors import Result, Error, ErrorCode

###################################################################
######### flash programmer erase command
###################################################################
class CwFlashErase(CwFlashBase):
    """
usage: [-h] offset size

S32DS Flash Programming erase command.

positional arguments:
  offset      offset in device address range
  size        size of memory section to be erased

optional arguments:
  -h, --help  show this help message and exit
    """

    def __init__(self, hse_limits):
        """
            Register new command with GDB
            Add a parameter parser to easily specify positional offset and size
            parameters
        """
        super(CwFlashErase, self).__init__(CMD_CW_FLASH_ERASE,
        gdb.COMMAND_USER, gdb.COMPLETE_COMMAND)
        parser = argparse.ArgumentParser(description='S32DS \
                                         Flash Programming erase command.')
        parser.add_argument('offset',
                            type = string_to_offset,
                            help = 'offset in device address range')
        parser.add_argument('size',
                            type = string_to_size,
                            help = 'size of memory section to be erased')
        parser.add_argument('--force',
                            action="store_true",
                            help = 'allows erasing of RCW area')
        self._parser = parser
        CwFlashErase.print_result = None

        self.HSE_limits = hse_limits

        # Don't print on the screen while progress bar is in place. Save the output and
        # print after closing the progress bar.
        self.output = ""

    def can_execute(self, args):
        """
            Internal method
        """
        if (args.force is False) and self.is_rcw_area(args.offset) and self.get_probe().startswith('cmsisdap'):  # pylint: disable=no-member
            raise gdb.GdbError("F-ERROR: CodeWarrior detected an attempt to modify the Reset Configuration Word (RCW) " \
                  "while using the CMSIS-DAP probe; it is recommended to verify operation " \
                  "parameters and RCW correctness before continuing. Failure to program a " \
                  "compatible RCW may result in board being unable to boot. Recovery is not " \
                  "possible using CSMSIS-DAP and will require use of the external CodeWarrior " \
                  "TAP unit. For details please refer to \"ARM v8 Targeting Manual / " \
                  "Use Cases / Board Recovery\".\n\nPlease re-run command with --force if you "\
                  "understand and accept the above.")

    def execute(self, args, from_tty):
        """
            Execute command called with args parameters
            Build command string in the form of a monitor command
            and call internal gdb execution.
        """

        cmd_string = 'mon flash erase offset %d size %d' % (args.offset, args.size)

        if(self.HSE_limits != None):
            try:
                self.HSE_limits.check_address(args.offset, args.size)
            except:
                Result(Error(ErrorCode.FlashWriteError, "F-ERROR: Restricted area detected. Aborting Command"))
                return
        #execute command
        try:
            execute_remote(cmd_string, from_tty, no_wait = True)
        except:
            Result(Error(ErrorCode.FlashEraseError, "F-ERROR: Can not erase"))

    def begin_command(self):
        gdb.write('Erasing....\n')

    def show_result(self):
        summary = 'Erase %s in %.2fs\n' % \
            (size_to_human_readable(self._args.size), self._time)
        gdb.write(summary)

def create_command(hse_limits):
    """
        Instantiate flash programmer erase command
    """
    CwFlashErase(hse_limits)
