#!/usr/bin/env python3
"""Write hanja.dict from a Hanja-per-row UTF-8 source."""

import sys
from pathlib import Path


SOURCE = Path(__file__).with_name("hanja.src")
MAXCANDIDATES = 128


def ishangul(s):
    return s != "" and all(0xAC00 <= ord(c) <= 0xD7A3 for c in s)


def ishanja(s):
    return s != "" and all(0x3400 <= ord(c) <= 0x4DBF
                           or 0x4E00 <= ord(c) <= 0x9FFF
                           or 0xF900 <= ord(c) <= 0xFAFF for c in s)


def read(path):
    comments = []
    table = {}
    seen = set()
    leading = True
    with path.open(encoding="utf-8") as src:
        for lineno, raw in enumerate(src, 1):
            line = raw.rstrip("\r\n")
            if not line:
                continue
            if line.startswith("#"):
                if leading:
                    comments.append(";;" + line[1:])
                continue
            leading = False
            fields = line.split("\t")
            if len(fields) != 2:
                raise ValueError(f"{path}:{lineno}: need Hanja<TAB>reading")
            hanja, reading = fields
            if not ishanja(hanja):
                raise ValueError(f"{path}:{lineno}: need BMP Hanja")
            if not ishangul(reading):
                raise ValueError(f"{path}:{lineno}: need Hangul syllables")
            pair = (hanja, reading)
            if pair in seen:
                raise ValueError(f"{path}:{lineno}: duplicate Hanja reading")
            seen.add(pair)
            table.setdefault(reading, []).append(hanja)
    if not seen:
        raise ValueError(f"{path}: no Hanja readings")
    return comments, table


def main():
    sys.stdout.reconfigure(encoding="utf-8")
    sys.stderr.reconfigure(encoding="utf-8")
    if len(sys.argv) > 2:
        print(f"usage: {sys.argv[0]} [hanja.src]", file=sys.stderr)
        return 2
    path = Path(sys.argv[1]) if len(sys.argv) == 2 else SOURCE
    try:
        comments, table = read(path)
        for line in comments:
            print(line)
        if comments:
            print()
        for reading, candidates in table.items():
            print(f"{reading}\t{' '.join(candidates[:MAXCANDIDATES])}")
    except (OSError, UnicodeError, ValueError) as error:
        print(error, file=sys.stderr)
        return 1
    return 0


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