import sys, json, subprocess, numpy as np
sys.path.insert(0,'.')
import pipeline as P, dithers as DI, os
# (the painterly pass from the checkout STARLOCK names, default this one: after the change it dithers its own write)
STAR=os.environ.get('STARLOCK', os.path.abspath('../../../public/ideas/starlock'))
OUT_DITHER='gl_FragCoord.yx' in open(os.path.join(STAR,'reveal3d.js')).read()
import tempfile; S=tempfile.mkdtemp()
from bluenoise import bluenoise; bn=bluenoise(); bytes_=np.floor(bn*256).astype(int)
W=H=192
D="uniform sampler2D uNoise; float dither() { return (texture2D(uNoise, gl_FragCoord.xy / 64.).r - .5) / 255.; }"
glowF="varying vec2 vUv; uniform vec3 uColor; uniform float uOpacity, uCore; "+D+"""
 void main() { float r2 = dot(vUv - .5, vUv - .5) * 4.;
 float a = max(0., (exp(-r2 * 4.) - .0183) / .9817) + uCore * exp(-r2 * 38.);
 vec3 c = uColor * a * uOpacity; gl_FragColor = vec4(c + dither() * step(.002, a * uOpacity), 1.); }"""
quads=[dict(x=96,y=96,w=180,h=180,col=[.55,.3,1.],op=.06,core=0.),dict(x=70,y=110,w=120,h=120,col=[.75,.45,1.],op=.04,core=.3),dict(x=120,y=80,w=100,h=140,col=[1,.94,1],op=.02,core=0.)]
x,y=P.coords(W,H); dith=((bytes_[63-(y.astype(int))%64,(x.astype(int))%64]/np.float32(255)).astype(np.float32)-np.float32(.5))/np.float32(255)
for R,st in ((0,1),(2,1),(5,1),(2,2),(5,2)):
  spec=dict(W=W,H=H,radius=R,stride=st,noise=dict(size=64,data=bytes_.ravel().tolist()),quads=[dict(frag=glowF,uniforms=dict(uColor=q['col'],uOpacity=q['op'],uCore=q['core']),x=q['x'],y=q['y'],w=q['w'],h=q['h']) for q in quads])
  json.dump(spec,open(S+'/v.json','w'))
  subprocess.run(['node','--input-type=module','-',S+'/v.json',S+'/v'],stdin=open('webgl.mjs.txt'),check=True,stderr=subprocess.DEVNULL)
  t=np.fromfile(S+'/v.target.rgba',np.uint8).reshape(H,W,4)[...,:3].astype(int)
  c=np.fromfile(S+'/v.canvas.rgba',np.uint8).reshape(H,W,4)[...,:3].astype(int)
  layers=[]
  for q in quads:
    u,v,ins=P.quad_uv(W,H,q['x'],q['y'],q['w'],q['h'])
    a=P.glow_alpha(u,v,q['core']); rgb=np.array(q['col'])[None,None]*(a*q['op'])[...,None]+(dith*(a*q['op']>=.002))[...,None]
    layers.append((rgb,ins))
  pt=P.additive(layers,W,H)
  disp=P.post(pt,R,stride=st)
  if OUT_DITHER: disp=disp+((DI.ign(y,x)-.5)/255.)[...,None]
  pc=P.to_unorm8(disp)
  et=pt-t; ec=pc-c
  print('radius',R,'stride',st,'target exact',(et==0).mean(),'max|d|',abs(et).max(),' canvas exact',(ec==0).mean(),'max|d|',abs(ec).max(), 'canvas maxcode',c.max())
