"""Rings per layer of the mesh slicer vs package vs GWN variants, for one cloud; and the descriptor's parts by span."""
import sys
from pathlib import Path
import numpy as np, trimesh
sys.path.insert(0, str(Path(__file__).parent)); sys.path.insert(0, "/home/joao/code/data/meshes/fcp_2710_tests/scripts")
import gwn, fcp
from fcp._slice import PointSlicer, MeshSlicer, centres, MIN_LOOP
from parts_report import OBJ, ROOT

name, tag, n = sys.argv[1], sys.argv[2], int(sys.argv[3])
g = trimesh.load(OBJ[name], force="mesh")
P = np.asarray(trimesh.load(ROOT / "pointclouds" / f"{name}_{tag}_{n}.ply").vertices)
c = centres(128)
def area(L):
    x, y = L[:, 0], L[:, 1]; return 0.5 * (np.dot(x, np.roll(y, -1)) - np.dot(y, np.roll(x, -1)))
ms = MeshSlicer(g, (0, 0, 1), "cuda"); Lm = ms.loops(c) if hasattr(ms, "loops") else None
def summary(L, sc, label):
    cnt = np.array([len(x) for x in L]); A = [abs(area(q * sc)) for x in L for q in x]
    print(f"{label:28s} rings {cnt.sum():5d}  layers>mesh {int((cnt > ref).sum()):3d}  max/layer {cnt.max():3d}  "
          f"median area {np.median(A) if A else 0:9.1f}  small(<10 s^2) {sum(a < 10 * s2 for a in A)}")
ps = PointSlicer(P, up=(0, 0, 1), device="cuda", slicer="surf"); s2 = ps.spacing ** 2
sc = ps.pose.scale[:2]
from fcp._slice import plane_rings
# mesh rings from encode internals: use the descriptor-free route via MeshSlicer.slices -> count per layer
S = ms.slices(128); ref = np.bincount(np.asarray(S.h), minlength=128) if hasattr(S, "h") else None
print("mesh rings", int(ref.sum()), "max/layer", ref.max())
summary(ps.loops(c), sc, "package surf")
for kv in sys.argv[4:]:
    saved = {}
    for e in kv.split(";"):
        k, v = e.split("=")
        saved[k] = old = getattr(gwn, k); setattr(gwn, k, type(old)(v) if not isinstance(old, str) else v)
    q = gwn.slicer_gwn(P, up=(0, 0, 1), c_eps=0.5)
    summary(q.loops(c), q.pose.scale[:2], f"gwn {kv}")
    for k, v in saved.items():
        setattr(gwn, k, v)
