#!/usr/bin/env python3
"""Write emoji.dict to stdout from a result-first UTF-8 TSV file."""

import sys
import unicodedata
from pathlib import Path


SOURCE = Path(__file__).with_name("emoji.src")
MAXRUNES = 64


def fold(s):
    s = "".join(chr(ord(c) + 32) if "A" <= c <= "Z" else c for c in s)
    return unicodedata.normalize("NFC", s)


def hascontrol(s):
    return any(unicodedata.category(c) == "Cc" for c in s)


def read(path):
    entries = []
    with path.open(encoding="utf-8") as src:
        for lineno, raw in enumerate(src, 1):
            line = raw.rstrip("\r\n")
            if not line.strip():
                continue
            if "\t" not in line and line.lstrip().startswith("#"):
                continue
            fields = line.split("\t")
            if len(fields) < 2:
                raise ValueError(f"{path}:{lineno}: need a result and an alias")
            result = unicodedata.normalize("NFC", fields[0])
            if (not result or len(result) > MAXRUNES or hascontrol(result)
                    or any(c.isspace() for c in result)):
                raise ValueError(f"{path}:{lineno}: bad result")
            for field in fields[1:]:
                alias = fold(field)
                if (not alias or len(alias) > MAXRUNES or hascontrol(alias)
                        or alias != alias.strip() or alias.startswith(";")):
                    raise ValueError(f"{path}:{lineno}: bad alias")
                entries.append((result, alias))
    return entries


def add(table, key, result):
    values = table.setdefault(key, [])
    if result not in values:
        values.append(result)


def build(entries):
    exact = {}
    prefix = {}
    for result, alias in entries:
        for n in range(1, len(alias) + 1):
            add(exact if n == len(alias) else prefix, alias[:n], result)
    for key in sorted(exact.keys() | prefix.keys()):
        values = exact.get(key, []) + prefix.get(key, [])
        values = list(dict.fromkeys(values))
        yield f"{key}\t{' '.join(values)}"


def main():
    if len(sys.argv) > 2:
        print(f"usage: {sys.argv[0]} [emoji.src]", file=sys.stderr)
        return 2
    path = Path(sys.argv[1]) if len(sys.argv) == 2 else SOURCE
    try:
        for line in build(read(path)):
            print(line)
    except (OSError, UnicodeError, ValueError) as error:
        print(error, file=sys.stderr)
        return 1
    return 0


if __name__ == "__main__":
    sys.exit(main())
