#!/usr/bin/env python3
"""Usage: python3 sys/unicode-width.py UCD > libr/util/str_utf8_width.inc.c.

UCD must contain Unicode 17.0.0 UnicodeData.txt, EastAsianWidth.txt and emoji/.
"""

import pathlib
import sys


def codepoints(field):
    ends = field.strip().split("..")
    return range(int(ends[0], 16), int(ends[-1], 16) + 1)


def properties(path):
    for line in path.read_text().splitlines():
        fields = line.split("#")[0].split(";")
        if len(fields) > 1:
            yield fields[0].strip(), fields[1].strip()


def emit(name, data):
    print("static const ut8 " + name + "[] =")
    for offset in range(0, len(data), 64):
        print('\t"' + ''.join(f"\\x{byte:02x}" for byte in data[offset:offset + 64]) + '"')
    print(";\n")


ucd = pathlib.Path(sys.argv[1])
zero = set(range(0x1160, 0x1200))
zero.update(range(0xd7b0, 0xd7c7))
zero.update(range(0xd7cb, 0xd7fc))
for line in (ucd / "UnicodeData.txt").read_text().splitlines():
    fields = line.split(";")
    point = int(fields[0], 16)
    if fields[2] in ("Mn", "Me", "Cf") and point != 0xad:
        zero.add(point)
wide = set()
for field, prop in properties(ucd / "EastAsianWidth.txt"):
    if prop in ("W", "F"):
        wide.update(codepoints(field))
variation = {int(field.split()[0], 16)
             for field, prop in properties(ucd / "emoji/emoji-variation-sequences.txt")}
pictographic, modifier = set(), set()
for field, prop in properties(ucd / "emoji/emoji-data.txt"):
    if prop == "Extended_Pictographic":
        pictographic.update(codepoints(field))
    elif prop == "Emoji_Modifier_Base":
        modifier.update(codepoints(field))

data = bytearray([1]) * 0x110000
for point in wide:
    data[point] = 2
for point in zero:
    data[point] = 0
for points, flag in ((variation, 4), (pictographic, 8), (modifier, 16),
                     (range(0x1f1e6, 0x1f200), 32), (map(ord, "#*0123456789"), 64)):
    for point in points:
        data[point] |= flag

pages, page_ids, index = bytearray(), {}, bytearray()
for offset in range(0, len(data), 128):
    page = bytes(data[offset:offset + 128])
    if page not in page_ids:
        page_ids[page] = len(page_ids)
        pages.extend(page)
    index.append(page_ids[page])
assert len(page_ids) <= 256

print("// Generated by sys/unicode-width.py from Unicode 17.0.0 UCD data.")
print("// https://www.unicode.org/Public/17.0.0/ucd/")
print("// Unicode data copyright Unicode, Inc.; see doc/licenses/Unicode-3.0.txt.")
print("// Deduplicated 128-codepoint pages: width in bits 0-1, emoji properties in bits 2-6.\n")
emit("utf8_width_index", index)
emit("utf8_width_pages", pages)
