#!/usr/bin/env python3
import lzma, sys
# imports detect by path? just quick parse blocks from saved module
import importlib.util
spec=importlib.util.spec_from_file_location('dmb','/workspace/solver/tools/detect_min_blocks.py')
dmb=importlib.util.module_from_spec(spec); spec.loader.exec_module(dmb)

def read_clauses(path):
    with lzma.open(path,'rt') as fh:
        head=fh.readline().split(); V=int(head[2]); C=int(head[3])
        first=fh.readline().split(); P=abs(int(first[2]))-1
        clauses=[tuple(int(x) for x in first if x!='0')]
        for line in fh: clauses.append(tuple(int(x) for x in line.split() if x!='0'))
    return V,C,P,clauses

def detect_blocks(clauses,P):
    blocks=[]; pos=0
    while pos+92<=len(clauses):
        cl=clauses[pos]; matched=False
        if len(cl)==3 and cl[0]>0 and cl[1]>0 and cl[2]>P:
            x0,y0,aux0=cl
            if y0==x0+6:
                row=0; p=pos; sels=[]
                while p+92<=len(clauses):
                    if row==0: bits=list(range(x0,x0+6)); sel=x0+16
                    else:
                        s=x0+17+7*(row-1); bits=list(range(s,s+6)); sel=s+6
                    g=dmb.gen_row(bits,y0,sel,aux0+18*row)
                    if clauses[p:p+92]!=g: break
                    sels.append(sel); row+=1; p+=92
                if row>0 and p<len(clauses) and clauses[p]==tuple(reversed(sels)):
                    blocks.append((x0,y0,row,sels)); pos=p+1; matched=True
        if not matched: pos+=1
    return blocks
path=sys.argv[1]
V,C,P,clauses=read_clauses(path)
blocks=detect_blocks(clauses,P)
assign=[False]*(P+1)
for x0,y0,k,sels in blocks:
    assign[sels[0]]=True
# test primary-only
bad=[]
for idx,cl in enumerate(clauses,1):
    if all(abs(l)<=P for l in cl):
        if not any((l>0 and assign[abs(l)]) or (l<0 and not assign[abs(l)]) for l in cl):
            bad.append((idx,cl))
            if len(bad)>=30: break
print('blocks',len(blocks),'true selectors',[b[3][0] for b in blocks[:5]],'bad first',len(bad))
for b in bad: print(b)
# count all bad if wanted
cnt=0; sizes={}
for idx,cl in enumerate(clauses,1):
    if all(abs(l)<=P for l in cl):
        if not any((l>0 and assign[abs(l)]) or (l<0 and not assign[abs(l)]) for l in cl):
            cnt+=1; sizes[len(cl)]=sizes.get(len(cl),0)+1
print('bad total',cnt,'sizes',sizes)
