# Copyright 2015 Freescale Semiconductor, Inc.
# Copyright 2019-2025 NXP
# SPDX-License-Identifier: BSD-3-Clause

#Implementation of Flash Programmer utility methods

import gdb, sys
import string
import os
import os.path

# Enable or disable warning messages
__show_warning = False

def string_to_offset(str):
    if str.startswith('0x'):
        return int(str, 16)
    return int(str)

def string_to_size(str):
    value = 0
    if str.startswith('0x'):
        if sys.version_info.major == 2:
            value = long(str , 16)
        else:
            value = int(str , 16)
    elif str.endswith('k') or str.endswith('K'):
        value = 1024 * int(str[:len(str) - 1])
    elif str.endswith('m') or str.endswith('M'):
        value = 1024 * 1024 * int(str[:len(str) - 1])
    elif str.endswith('g') or str.endswith('G'):
        value = 1024 * 1024 * 1024 * int(str[:len(str) - 1])
    else:
        # pylint: disable=all
        if sys.version_info.major == 2:
            value = long(str , 10)
        else:
            value = int(str , 10)

    if value <= 0:
        raise ValueError('size can\'t be zero')

    return value

def string_to_abs_path(str):
    abs_file_path = os.path.abspath(str)
    abs_file_path = abs_file_path.replace("\\", "/")
    path_list = abs_file_path.rsplit('/', 1)
    if os.path.isdir(path_list[0]):
        return abs_file_path

    raise ValueError('F-ERROR: invalid path %s' % path_list[0])

def is_hex_sequence(seq):
    if seq.startswith('0x'):
        hex_digits = set(string.hexdigits)
        return all(c in hex_digits for c in seq[2:])
    return False

def size_to_human_readable(size):
    suffix = 'B'
    for unit in ['','K','M','G','T']:
        if abs(size) < 1024.0:
            if unit is '':
                return '%d%s%s' % (size, unit, suffix)
            else:
                return '%.2f%s%s' % (size, unit, suffix)
        size /= 1024.0
    return '%.2f%s%s' % (size, 'P', suffix)

def get_soc_ctx_from_current(ctx):
    """
        Get SoC context for current context
        For flash programmer current context it is usually a core context
    """
    # check if current context is a SoC context
    cmd_string = 'mon ctx id %s get prop type' % ctx
    result = gdb.execute(cmd_string, False, True)
    if result:
        if 'soc' not in result:
            ctxs = ctx.split(':')
            return ''.join([':', ctxs[1], ':', ctxs[2]])
    return ctx

def gdb_execute(command, from_tty = False, to_string = False):
    """
        Execute a GDB command, remove the echo if it appears,
        handle the exception
    """ 
    result = None
    try:
        print("\nORG GDB: " + command)
        result = gdb.execute(command, from_tty, True)
        if result:
            result = result.rstrip("\n")
        echo_command = "+" + command + "\n"
        if result is not None and result.startswith(echo_command):
            return result[len(echo_command):]
        else:
            return result
    except gdb.error as exc:        
        command = 'mon errorinfo'
        error_msg = gdb.execute(command, from_tty, True)
        raise gdb.GdbError(error_msg)

def gdb_warning(warning_msg):
    global __show_warning

    if __show_warning is True:
        gdb.write(warning_msg)

def int_to_bytes(data):
        h = hex(data).upper()[2:]
        return h if len(h) % 2 == 0 else "0"+h

def bytestring_to_bytes( data):
    return "".join([int_to_bytes(ord(byte)) for byte in data])

def bytes_to_bytestring( data):
    x = 2
    res = [data[y - x:y] for y in range(x, len(data) + x, x)]
    bytes = "".join([chr(int(y, 16)) for y in res])
    return  bytes
