"""A NON-neural cellular automaton, provided as a local-rule control.
Python builds a graph in ZIPP WASM; the selected backend runs the Life kernel.
"""
from zipp_gpu import Graph
S = {}

def configure(model):
    reset(1)
    return True

def reset(seed):
    global S
    n = 48; grid = [0.0]*(n*n)
    for y,x in [(1,2),(2,3),(3,1),(3,2),(3,3),(12,14),(12,15),(12,16),(25,25),(25,26),(26,25),(26,26)]:
        grid[y*n+x] = 1.0
    S = {'mode':'life','grid':grid,'size':n,'steps':0,'busy':False,
         'error':None,'graphs':0,'lastMs':0,'message':'Fixed B3/S23 rule. No neural weights or training.'}

def failed(error):
    S['error'] = str(error); S['busy'] = False

def act(action,args):
    if S['busy']: raise ValueError('Wait for current update')
    if action == 'reset': reset(args.get('seed',1))
    elif action == 'random':
        seed = max(1,int(args.get('seed',1))) % 2147483647
        for i in range(len(S['grid'])):
            seed = (seed*48271)%2147483647
            S['grid'][i] = 1.0 if seed%100 < 24 else 0.0
        S['steps'] = 0
    elif action == 'paint':
        x = int(args['x']); y = int(args['y'])
        if not 0 <= x < 48 or not 0 <= y < 48: raise ValueError('Invalid cell')
        S['grid'][y*48+x] = 1.0-S['grid'][y*48+x]
    elif action == 'step':
        S['busy'] = True
        g = Graph(); grid = g.tensor(S['grid'],shape=[48,48]); next_grid = grid.life()
        def done(result):
            S['grid'] = result['outputs']['grid']['data']
            S['steps'] += 1; S['graphs'] += 1
            S['lastMs'] = result['stats']['totalWallMs']; S['busy'] = False
        g.submit(done,failed,grid=next_grid)
    else: raise ValueError('Unknown Life command')
    return snapshot()

def snapshot(): return S
