"""Build compact, self-hosted lookup and handwriting assets. No runtime data service."""
import json,gzip,sys,re
from pathlib import Path
root=Path(__file__).resolve().parent.parent
def save(name,obj):
 raw=json.dumps(obj,ensure_ascii=False,separators=(',',':')).encode()
 with open(root/'dist'/name,'wb') as f:
  with gzip.GzipFile(fileobj=f,mode='wb',mtime=0) as z:z.write(raw)
 print(name,len(raw),(root/'dist'/name).stat().st_size)
source=Path(sys.argv[1]) if len(sys.argv)>1 else root/'content/dictionary-source.jsonl.gz'
if source.suffix=='.gz': lines=gzip.open(source,'rt',encoding='utf8')
else: lines=source.open(encoding='utf8')
entries={}
for line in lines:
 d=json.loads(line);entries[d['character']]={'meaning':d.get('definition',''),'pinyin':d.get('pinyin',[]),'radical':d.get('radical','')}
# Keep the original dictionary as a small reproducible source asset outside dist.
if source.suffix!='.gz':
 with gzip.open(root/'content/dictionary-source.jsonl.gz','wb') as f:f.write(source.read_bytes())
examples={}
for sourcefile in ['textbooks.json','shared-textbooks.json']:
 books=json.loads((root/'content/dictation-sources'/sourcefile).read_text())
 if isinstance(books,dict):books=books.get('books',[])
 for book in books:
  for lesson in book.get('lessons',[]):
   for unit in lesson.get('units',[]):
    for text in re.split(r'[。！？\n]+',unit.get('text','')):
     text=text.strip('，、； ：0123456789.')
     if not 2<=len(text)<=48:continue
     for c in set(text):
      if c not in entries:continue
      ex=examples.setdefault(c,[])
      if len(ex)<3 and not any(x['text']==text for x in ex):ex.append({'text':text,'source':f"{book.get('title','教材')} · {lesson.get('title','')}"})
for c,examples_ in examples.items():entries[c]['examples']=examples_
save('dictionary-data.json.gz',entries)
# Eight equally spaced samples per stroke; one uniform scale preserves structure.
def sample(points,n=8):
 lengths=[0]
 for a,b in zip(points,points[1:]):lengths.append(lengths[-1]+((a[0]-b[0])**2+(a[1]-b[1])**2)**.5)
 result=[];j=1
 for i in range(n):
  target=lengths[-1]*i/(n-1)
  while j<len(lengths)-1 and lengths[j]<target:j+=1
  t=(target-lengths[j-1])/(lengths[j]-lengths[j-1] or 1)
  result.extend([points[j-1][k]+t*(points[j][k]-points[j-1][k]) for k in (0,1)])
 return result
recognition=[]
for file in sorted((root/'dist/data').glob('*.json')):
 med=json.loads(file.read_text())['medians'];points=[p for stroke in med for p in stroke]
 x0=min(p[0] for p in points);x1=max(p[0] for p in points);y0=min(p[1] for p in points);y1=max(p[1] for p in points)
 scale=230/max(x1-x0,y1-y0,1);cx=(x0+x1)/2;cy=(y0+y1)/2
 strokes=[]
 for stroke in med:
  normalized=[[(p[0]-cx)*scale+127.5,(cy-p[1])*scale+127.5] for p in stroke]
  strokes.append([round(v) for v in sample(normalized)])
 recognition.append([file.stem,strokes])
save('handwriting-index.json.gz',recognition)
