#!/usr/bin/env python3
import json
import lzma
import os
import sys
from collections import Counter, defaultdict


def clauses(path):
    opener = lzma.open if path.endswith(".xz") else open
    with opener(path, "rt", encoding="ascii", errors="ignore") as f:
        nv = nc = None
        cur = []
        for line in f:
            if not line or line[0] in "c%":
                continue
            if line[0] == "p":
                parts = line.split()
                nv = int(parts[2])
                nc = int(parts[3])
                continue
            for tok in line.split():
                lit = int(tok)
                if lit == 0:
                    if cur:
                        yield nv, nc, cur
                        cur = []
                else:
                    cur.append(lit)


def main(argv):
    for path in argv[1:]:
        size_hist = Counter()
        unit_pos = unit_neg = 0
        nclauses = nvars = 0
        pos6 = []
        neg_bin = set()
        bin_count = 0
        tern_count = 0
        first_clauses = []
        lit_occ = Counter()
        var_occ = Counter()
        for nv, nc, cls in clauses(path):
            nvars, nclauses = nv, nc
            if len(first_clauses) < 20:
                first_clauses.append(cls[:])
            size_hist[len(cls)] += 1
            for lit in cls:
                lit_occ[lit] += 1
                var_occ[abs(lit)] += 1
            if len(cls) == 1:
                if cls[0] > 0:
                    unit_pos += 1
                else:
                    unit_neg += 1
            elif len(cls) == 2:
                bin_count += 1
                a, b = cls
                if a < 0 and b < 0:
                    x, y = sorted((-a, -b))
                    neg_bin.add((x, y))
            elif len(cls) == 3:
                tern_count += 1
            if len(cls) == 6 and all(l > 0 for l in cls):
                pos6.append(tuple(cls))

        eo6 = []
        for group in pos6:
            ok = True
            for i in range(6):
                for j in range(i + 1, 6):
                    if tuple(sorted((group[i], group[j]))) not in neg_bin:
                        ok = False
                        break
                if not ok:
                    break
            if ok:
                eo6.append(group)

        starts = [g[0] for g in eo6]
        diffs = Counter(b - a for a, b in zip(starts, starts[1:]))
        mods = Counter((g[0] - 1) % 600 for g in eo6)
        top_vars = var_occ.most_common(12)
        top_lits = lit_occ.most_common(12)
        out = {
            "file": os.path.basename(path),
            "vars": nvars,
            "clauses": nclauses,
            "sizes": dict(sorted(size_hist.items())),
            "unit_pos": unit_pos,
            "unit_neg": unit_neg,
            "pos6": len(pos6),
            "eo6": len(eo6),
            "eo6_first": eo6[:5],
            "eo6_start_minmax": [min(starts), max(starts)] if starts else None,
            "eo6_start_diffs": diffs.most_common(8),
            "eo6_start_mod600": mods.most_common(12),
            "top_vars": top_vars,
            "top_lits": top_lits,
            "first_clauses": first_clauses,
        }
        print(json.dumps(out, separators=(",", ":")))


if __name__ == "__main__":
    main(sys.argv)
