#!/usr/bin/python3
"""Compile the dictionary into the directory given as the argument.

These are the steps and arguments of upstream's scripts/build_release_data.py,
using the tools from 0c-ime-tools.  Stop if the result does not match
data/dictionary.lock.json.
"""
import hashlib
import json
import shutil
import subprocess
import sys
from pathlib import Path

TOOLS = Path("/usr/libexec/0c-ime-tools")
DATA = Path("data").resolve()

COMPILE_ARGS = [
    "-public=true", "-relative-readings=true", "-inherit=true",
    "-yibu=true", "-neutral=true", "-polyphone=true", "-max-variants=4",
    "-unigram=mcbopomofo=2,0c_collect=1", "-unigram-fallback=chewing-v4,zhwiki",
    "-fallback-scale=0.25", "-alpha=0.5", "-prune-mu=0.7",
    "-prune-by=entropy",
    "-demote=", "-rare=cns11643,mcbopomofo-rare",
    "-bigram=chewing-v4=3,zhwiki=1,0c_collect-ns=3,0c_collect-ss=2", "-bigram-max=12000000",
    "-boost=",
]
RUNTIME = {"version": 1, "document_context_weight": 0.075}


def run(tool, *args):
    subprocess.run([TOOLS / tool, *args], stdin=subprocess.DEVNULL, check=True)


def check(directory, lock):
    """Stop if the files in directory differ from the sizes and checksums in lock."""
    entries = json.loads((DATA / lock).read_text(encoding="utf-8"))["files"]
    for name, entry in entries.items():
        path = directory / name
        digest = hashlib.sha256(path.read_bytes()).hexdigest()
        if path.stat().st_size != entry["size"] or digest != entry["sha256"]:
            sys.exit(f"{path} does not match {lock}")
    return entries


def main():
    out = Path(sys.argv[1]).resolve()
    if out.exists():
        shutil.rmtree(out)
    check(DATA / "lm/bigram", "sources/bigram.lock.json")

    run("0c-compile", "-data", DATA, "-out", out, *COMPILE_ARGS)
    run("0c-english", "-source", DATA / "english", "-out", out / "english")
    manifest_path = out / "manifest.json"
    manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
    manifest["format"] = 2
    manifest["runtime"] = RUNTIME
    manifest_path.write_bytes((json.dumps(manifest, ensure_ascii=False, indent=2) + "\n").encode("utf-8"))
    run("0c-cli", "-data", out)
    run("0c-single-gate", "-data", out, "-source", DATA, "-approved", DATA / "curation/single-gate.tsv")

    entries = check(out, "dictionary.lock.json")
    built = {str(f.relative_to(out)) for f in out.rglob("*") if f.is_file()}
    if built != set(entries):
        sys.exit(f"files differ from dictionary.lock.json: {sorted(built ^ set(entries))}")


if __name__ == "__main__":
    main()
