# Copyright (c) 2023 Yonatan Schachter
#
# SPDX-License-Identifier: Apache-2.0

from textwrap import dedent
import struct

from west.commands import WestCommand
from west import log


try:
    from elftools.elf.elffile import ELFFile
    from intelhex import IntelHex
    MISSING_REQUIREMENTS = False
except ImportError:
    MISSING_REQUIREMENTS = True


# Based on scripts/build/uf2conv.py
def convert_from_uf2(buf):
    UF2_MAGIC_START0 = 0x0A324655 # First magic number ('UF2\n')
    UF2_MAGIC_START1 = 0x9E5D5157 # Second magic number
    numblocks = len(buf) // 512
    curraddr = None
    outp = []
    for blockno in range(numblocks):
        ptr = blockno * 512
        block = buf[ptr:ptr + 512]
        hd = struct.unpack(b'<IIIIIIII', block[0:32])
        if hd[0] != UF2_MAGIC_START0 or hd[1] != UF2_MAGIC_START1:
            log.inf('Skipping block at ' + ptr + '; bad magic')
            continue
        if hd[2] & 1:
            # NO-flash flag set; skip block
            continue
        datalen = hd[4]
        if datalen > 476:
            log.die(f'Invalid UF2 data size at {ptr}')
        newaddr = hd[3]
        if curraddr is None:
            curraddr = newaddr
        padding = newaddr - curraddr
        if padding < 0:
            log.die(f'Block out of order at {ptr}')
        if padding > 10*1024*1024:
            log.die(f'More than 10M of padding needed at {ptr}')
        if padding % 4 != 0:
            log.die(f'Non-word padding size at {ptr}')
        while padding > 0:
            padding -= 4
            outp += b'\x00\x00\x00\x00'
        outp.append(block[32 : 32 + datalen])
        curraddr = newaddr + datalen
    return b''.join(outp)


class Bindesc(WestCommand):
    EXTENSIONS = ['bin', 'hex', 'elf', 'uf2']

    # Corresponds to the definitions in include/zephyr/bindesc.h.
    # Do not change without syncing the definitions in both files!
    TYPE_UINT = 0
    TYPE_STR = 1
    TYPE_BYTES = 2
    MAGIC = 0xb9863e5a7ea46046
    DESCRIPTORS_END = 0xffff

    def __init__(self):
        self.TAG_TO_NAME = {
            # Corresponds to the definitions in include/zephyr/bindesc.h.
            # Do not change without syncing the definitions in both files!
            self.bindesc_gen_tag(self.TYPE_STR, 0x800): 'APP_VERSION_STRING',
            self.bindesc_gen_tag(self.TYPE_UINT, 0x801): 'APP_VERSION_MAJOR',
            self.bindesc_gen_tag(self.TYPE_UINT, 0x802): 'APP_VERSION_MINOR',
            self.bindesc_gen_tag(self.TYPE_UINT, 0x803): 'APP_VERSION_PATCHLEVEL',
            self.bindesc_gen_tag(self.TYPE_UINT, 0x804): 'APP_VERSION_NUMBER',
            self.bindesc_gen_tag(self.TYPE_STR, 0x805): 'APP_BUILD_VERSION',
            self.bindesc_gen_tag(self.TYPE_STR, 0x900): 'KERNEL_VERSION_STRING',
            self.bindesc_gen_tag(self.TYPE_UINT, 0x901): 'KERNEL_VERSION_MAJOR',
            self.bindesc_gen_tag(self.TYPE_UINT, 0x902): 'KERNEL_VERSION_MINOR',
            self.bindesc_gen_tag(self.TYPE_UINT, 0x903): 'KERNEL_VERSION_PATCHLEVEL',
            self.bindesc_gen_tag(self.TYPE_UINT, 0x904): 'KERNEL_VERSION_NUMBER',
            self.bindesc_gen_tag(self.TYPE_STR, 0x905): 'KERNEL_BUILD_VERSION',
            self.bindesc_gen_tag(self.TYPE_UINT, 0xa00): 'BUILD_TIME_YEAR',
            self.bindesc_gen_tag(self.TYPE_UINT, 0xa01): 'BUILD_TIME_MONTH',
            self.bindesc_gen_tag(self.TYPE_UINT, 0xa02): 'BUILD_TIME_DAY',
            self.bindesc_gen_tag(self.TYPE_UINT, 0xa03): 'BUILD_TIME_HOUR',
            self.bindesc_gen_tag(self.TYPE_UINT, 0xa04): 'BUILD_TIME_MINUTE',
            self.bindesc_gen_tag(self.TYPE_UINT, 0xa05): 'BUILD_TIME_SECOND',
            self.bindesc_gen_tag(self.TYPE_UINT, 0xa06): 'BUILD_TIME_UNIX',
            self.bindesc_gen_tag(self.TYPE_STR, 0xa07): 'BUILD_DATE_TIME_STRING',
            self.bindesc_gen_tag(self.TYPE_STR, 0xa08): 'BUILD_DATE_STRING',
            self.bindesc_gen_tag(self.TYPE_STR, 0xa09): 'BUILD_TIME_STRING',
            self.bindesc_gen_tag(self.TYPE_STR, 0xb00): 'HOST_NAME',
            self.bindesc_gen_tag(self.TYPE_STR, 0xb01): 'C_COMPILER_NAME',
            self.bindesc_gen_tag(self.TYPE_STR, 0xb02): 'C_COMPILER_VERSION',
            self.bindesc_gen_tag(self.TYPE_STR, 0xb03): 'CXX_COMPILER_NAME',
            self.bindesc_gen_tag(self.TYPE_STR, 0xb04): 'CXX_COMPILER_VERSION',
        }
        self.NAME_TO_TAG = {v: k for k, v in self.TAG_TO_NAME.items()}

        super().__init__(
            'bindesc',
            'work with Binary Descriptors',
            dedent('''
            Work with Binary Descriptors - constant data objects
            describing a binary image
            '''))

    def do_add_parser(self, parser_adder):
        parser = parser_adder.add_parser(self.name,
                                         help=self.help,
                                         description=self.description)

        subparsers = parser.add_subparsers(help='sub-command to run', required=True)

        dump_parser = subparsers.add_parser('dump', help='Dump all binary descriptors in the image')
        dump_parser.add_argument('file', type=str, help='Executable file')
        dump_parser.add_argument('--file-type', type=str, choices=self.EXTENSIONS, help='File type')
        dump_parser.add_argument('-b', '--big-endian', action='store_true',
                                 help='Target CPU is big endian')
        dump_parser.set_defaults(subcmd='dump', big_endian=False)

        search_parser = subparsers.add_parser('search', help='Search for a specific descriptor')
        search_parser.add_argument('descriptor', type=str, help='Descriptor name')
        search_parser.add_argument('file', type=str, help='Executable file')
        search_parser.add_argument('--file-type', type=str, choices=self.EXTENSIONS, help='File type')
        search_parser.add_argument('-b', '--big-endian', action='store_true',
                                   help='Target CPU is big endian')
        search_parser.set_defaults(subcmd='search', big_endian=False)

        custom_search_parser = subparsers.add_parser('custom_search',
                                                     help='Search for a custom descriptor')
        custom_search_parser.add_argument('type', type=str, choices=['UINT', 'STR', 'BYTES'],
                                          help='Descriptor type')
        custom_search_parser.add_argument('id', type=str, help='Descriptor ID in hex')
        custom_search_parser.add_argument('file', type=str, help='Executable file')
        custom_search_parser.add_argument('--file-type', type=str, choices=self.EXTENSIONS,
                                          help='File type')
        custom_search_parser.add_argument('-b', '--big-endian', action='store_true',
                                   help='Target CPU is big endian')
        custom_search_parser.set_defaults(subcmd='custom_search', big_endian=False)

        list_parser = subparsers.add_parser('list', help='List all known descriptors')
        list_parser.set_defaults(subcmd='list', big_endian=False)

        return parser

    def dump(self, args):
        image = self.get_image_data(args.file)

        descriptors = self.parse_descriptors(image)
        for tag, value in descriptors.items():
            if tag in self.TAG_TO_NAME:
                tag = self.TAG_TO_NAME[tag]
            log.inf(f'{tag}', self.bindesc_repr(value))

    def list(self, args):
        for tag in self.TAG_TO_NAME.values():
            log.inf(f'{tag}')

    def common_search(self, args, search_term):
        image = self.get_image_data(args.file)

        descriptors = self.parse_descriptors(image)

        if search_term in descriptors:
            value = descriptors[search_term]
            log.inf(self.bindesc_repr(value))
        else:
            log.die('Descriptor not found')

    def search(self, args):
        try:
            search_term = self.NAME_TO_TAG[args.descriptor]
        except KeyError:
            log.die(f'Descriptor {args.descriptor} is invalid')

        self.common_search(args, search_term)

    def custom_search(self, args):
        custom_type = {
            'STR': self.TYPE_STR,
            'UINT': self.TYPE_UINT,
            'BYTES': self.TYPE_BYTES
        }[args.type]
        custom_tag = self.bindesc_gen_tag(custom_type, int(args.id, 16))
        self.common_search(args, custom_tag)

    def do_run(self, args, _):
        if MISSING_REQUIREMENTS:
            raise RuntimeError('one or more Python dependencies were missing; '
                               'see the getting started guide for details on '
                               'how to fix')
        self.is_big_endian = args.big_endian
        self.file_type = self.guess_file_type(args)
        subcmd = getattr(self, args.subcmd)
        subcmd(args)

    def get_image_data(self, file_name):
        if self.file_type == 'bin':
            with open(file_name, 'rb') as bin_file:
                return bin_file.read()

        if self.file_type == 'hex':
            return IntelHex(file_name).tobinstr()

        if self.file_type == 'uf2':
            with open(file_name, 'rb') as uf2_file:
                return convert_from_uf2(uf2_file.read())

        if self.file_type == 'elf':
            with open(file_name, 'rb') as f:
                elffile = ELFFile(f)

                section = elffile.get_section_by_name('rom_start')
                if section:
                    return section.data()

                section = elffile.get_section_by_name('text')
                if section:
                    return section.data()

            log.die('No "rom_start" or "text" section found')

        log.die('Unknown file type')

    def parse_descriptors(self, image):
        magic = struct.pack('>Q' if self.is_big_endian else 'Q', self.MAGIC)
        index = image.find(magic)
        if index == -1:
            log.die('Could not find binary descriptor magic')

        descriptors = {}

        index += len(magic) # index points to first descriptor
        current_tag = self.bytes_to_short(image[index:index+2])
        while current_tag != self.DESCRIPTORS_END:
            index += 2 # index points to length
            length = self.bytes_to_short(image[index:index+2])
            index += 2 # index points to data
            data = image[index:index+length]

            tag_type = self.bindesc_get_type(current_tag)
            if tag_type == self.TYPE_STR:
                decoded_data = data[:-1].decode('ascii')
            elif tag_type == self.TYPE_UINT:
                decoded_data = self.bytes_to_uint(data)
            elif tag_type == self.TYPE_BYTES:
                decoded_data = data
            else:
                log.die(f'Unknown type for tag 0x{current_tag:04x}')

            key = f'0x{current_tag:04x}'
            descriptors[key] = decoded_data
            index += length
            index = self.align(index, 4)
            current_tag = self.bytes_to_short(image[index:index+2])

        return descriptors

    def guess_file_type(self, args):
        if "file" not in args:
            return None

        # If file type is explicitly given, use it
        if args.file_type is not None:
            return args.file_type

        # If the file has a known extension, use it
        for extension in self.EXTENSIONS:
            if args.file.endswith(f'.{extension}'):
                return extension

        with open(args.file, 'rb') as f:
            header = f.read(1024)

        # Try the elf magic
        if header.startswith(b'\x7fELF'):
            return 'elf'

        # Try the uf2 magic
        if header.startswith(b'UF2\n'):
            return 'uf2'

        try:
            # if the file is textual it's probably hex
            header.decode('ascii')
            return 'hex'
        except UnicodeDecodeError:
            # Default to bin
            return 'bin'

    def bytes_to_uint(self, b):
        return struct.unpack('>I' if self.is_big_endian else 'I', b)[0]

    def bytes_to_short(self, b):
        return struct.unpack('>H' if self.is_big_endian else 'H', b)[0]

    @staticmethod
    def bindesc_gen_tag(_type, _id):
        return f'0x{(_type << 12 | _id):04x}'

    @staticmethod
    def bindesc_get_type(tag):
        return tag >> 12

    @staticmethod
    def align(x, alignment):
        return (x + alignment - 1) & (~(alignment - 1))

    @staticmethod
    def bindesc_repr(value):
        if isinstance(value, str):
            return f'"{value}"'
        if isinstance(value, (int, bytes)):
            return f'{value}'
