# -*- coding: utf-8 -*-
"""原创离线合成样例；不连接模型、不读取账户。输出位于脚本旁。
已有输入保留，修改输入后可以重跑。失败边界由 --negative 单独演示。
"""
from pathlib import Path
import sys, json, csv, math, io, hashlib, html, base64, re
sys.stdout.reconfigure(encoding='utf-8')
sys.stderr.reconfigure(encoding='utf-8')
BASE = Path(__file__).resolve().parent
NEG = '--negative' in sys.argv
def write(name, value):
    p=BASE/name; p.parent.mkdir(parents=True,exist_ok=True)
    if isinstance(value,bytes): p.write_bytes(value)
    else: p.write_text(value,encoding='utf-8',newline='')
def seed(name,value):
    if not (BASE/name).exists(): write(name,value)
def jwrite(name,value): write(name,json.dumps(value,ensure_ascii=False,indent=2))
def jseed(name,value):
    if not (BASE/name).exists(): jwrite(name,value)
def load(name): return json.loads((BASE/name).read_text(encoding='utf-8'))
def table(name,heads,rows):
    f=io.StringIO(newline='');w=csv.writer(f);w.writerow(heads);w.writerows(rows);write(name,f.getvalue())
def page(name,title,body):
    write(name,'<!doctype html><html lang="zh-CN"><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>'+html.escape(title)+'</title><style>body{max-width:1000px;margin:2rem auto;padding:0 1rem;font:17px/1.7 system-ui}table{border-collapse:collapse}td,th{border:1px solid #aaa;padding:.5rem}pre{white-space:pre-wrap;overflow-wrap:anywhere}img,svg{max-width:100%;height:auto}a{color:#125caa}</style><h1>'+html.escape(title)+'</h1>'+body+'</html>')
def emit(data): print(json.dumps(data,ensure_ascii=False))

from PIL import Image,ImageChops,ImageDraw
for name,bad in [('good-tile.png',False),('bad-tile.png',True)]:
    if not (BASE/name).exists():
        im=Image.new('RGB',(32,32),'#dddddd');d=ImageDraw.Draw(im);d.ellipse((7,7,24,24),fill='#5e839e')
        if bad:d.rectangle((30,0,31,31),fill='black')
        im.save(BASE/name)
rows=[];preview=Image.new('RGB',(192,128),'white')
for i,name in enumerate(['good-tile.png','bad-tile.png']):
    im=Image.open(BASE/name).convert('RGB');w,h=im.size;lr=sum(abs(im.getpixel((0,y))[c]-im.getpixel((w-1,y))[c]) for y in range(h) for c in range(3))/(h*3);tb=sum(abs(im.getpixel((x,0))[c]-im.getpixel((x,h-1))[c]) for x in range(w) for c in range(3))/(w*3);rows.append([name,lr,tb])
    for y in range(3):
        for x in range(3):preview.paste(im,(i*96+x*32,y*32))
    preview.paste(ImageChops.offset(im,w//2,h//2),(i*96+32,96))
preview.save(BASE/'tiled-previews.png');table('edge-differences.csv',['tile','mean_left_right','mean_top_bottom'],rows)
boundary=None
if NEG:
    misleading=Image.new('RGB',(32,32),'#dddddd');d=ImageDraw.Draw(misleading);d.line((8,8,24,24),fill='black',width=3);d.line((24,8,8,24),fill='black',width=3);misleading.save(BASE/'zero-edge-repeating-mark.png');repeat=Image.new('RGB',(96,96))
    for yy in range(3):
        for xx in range(3):repeat.paste(misleading,(xx*32,yy*32))
    repeat.save(BASE/'boundary-preview.png');lr=sum(abs(misleading.getpixel((0,y))[c]-misleading.getpixel((31,y))[c]) for y in range(32) for c in range(3))/96;tb=sum(abs(misleading.getpixel((x,0))[c]-misleading.getpixel((x,31))[c]) for x in range(32) for c in range(3))/96;boundary={'edge_lr':lr,'edge_tb':tb,'repeated_marks':9,'preview':'boundary-preview.png'}
emit({'edges':rows,'boundary':'边缘相同不能排除内部重复图案与人眼接缝' if NEG else '原尺寸3x3与半幅平移预览','boundary_fixture':boundary})
