import re
import sys
from pathlib import Path

def parse_values(knownfolders_h: Path) -> dict[str,str]:
    if not knownfolders_h.is_file():
        print(f'ERROR: {knownfolders_h} is not a file')
        sys.exit(2)

    values: dict[str,str] = dict()
    lines = knownfolders_h.read_text().splitlines()
    for line in lines:
        # Typical NTSTATUS definition lines look like this:
        # DEFINE_KNOWN_FOLDER(FOLDERID_NetworkFolder, 0xD20BEEC4, 0x5CA8, 0x4905, 0xAE, 0x3B, 0xBF, 0x25, 0x1E, 0xA0, 0x9B, 0x53);
        # Which should be interpreted as this GUID: {D20BEEC4-5CA8-4905-AE3B-BF251EA09B53}
        m = re.fullmatch(r'DEFINE_KNOWN_FOLDER\(FOLDERID_(\w+),\s*(.*)\);', line)
        if not m:
            continue

        name = m.group(1)
        fields = [int(v.strip(), 16) for v in m.group(2).split(',')]

        assert fields[0] < 2**32
        assert fields[1] < 2**16
        assert fields[2] < 2**16
        for i in range(3, 11):
            assert fields[i] < 2**8

        values[name] = f'{fields[0]:08x}-{fields[1]:04x}-{fields[2]:04x}-{fields[3]:02x}{fields[4]:02x}-{fields[5]:02x}{fields[6]:02x}{fields[7]:02x}{fields[8]:02x}{fields[9]:02x}{fields[10]:02x}'

    return values

def read_script(folderids_py: Path) -> tuple[list[str],str]:
    if not folderids_py.is_file():
        print(f'ERROR: {folderids_py} is not a file')
        sys.exit(2)

    autogen_line = '# AUTOGENERATED FROM HERE, DO NOT TOUCH'
    lines = folderids_py.read_text().splitlines()
    for index, line in enumerate(lines):
        if m := re.fullmatch(r'^(\s+)' + autogen_line, line):
            return lines[0:index+1] + [''], m.group(1)

    print(f'ERROR: {folderids_py} does not contain the line "{autogen_line}" (with indentation)')
    sys.exit(2)

def main() -> None:
    if len(sys.argv) != 2:
        print(f'Usage: {Path(__file__).name} path/to/KnownFolders.h')
        sys.exit(1)

    knownfolders_h = Path(sys.argv[1])
    values = parse_values(knownfolders_h)
    print(f'Extracted {len(values)} FOLDERIDs')

    folderids_py = Path(__file__).parent.parent / 'win_shortcut' / '_known_folder_id.py'

    lines, indent = read_script(folderids_py)
    for name, value in sorted(values.items()):
        lines.append(f'{indent}{name} = \'{{{value}}}\'')

    folderids_py.write_text('\n'.join(lines) + '\n')

if __name__ == '__main__':
    main()
