import collections
import struct


def fnt2Dict(fnt):
    """
    Convert a NDS fnt.bin file to an OrderedDict.
    """
    def loadFolder(folderId):
        """
        Load the folder with ID `folderId` and return it as a dict.
        """
        folderDict = collections.OrderedDict()

        # Get the entries table offset and file ID from the top of the
        # fnt file
        off = 8 * (folderId & 0xFFF)
        entriesTableOff, fileID = struct.unpack_from('<IH', fnt, off)
        folderDict['first_id'] = fileID

        files = []
        folders = collections.OrderedDict()
        off = entriesTableOff

        # Read file and folder entries from the entries table
        while True:
            control, = struct.unpack_from('B', fnt, off); off += 1
            if control == 0:
                break

            # That first byte is a control byte that includes the length
            # of the upcoming string and if this entry is a folder
            len_, isFolder = control & 0x7F, control & 0x80

            name = fnt[off : off+len_].decode('latin-1'); off += len_

            if isFolder:
                # There's an additional 2-byte value with the subfolder
                # ID. Get that and load the folder
                subFolderID, = struct.unpack_from('<H', fnt, off); off += 2
                folders[name] = loadFolder(subFolderID)
            else:
                files.append(name)

        # Only add these to the folder dict if they're nonempty
        if files:
            folderDict['files'] = files
        if folders:
            folderDict['folders'] = folders

        return folderDict

    # Root folder is always 0xF000
    return loadFolder(0xF000)