"""The v6 lobe parts (fcp/_lobes.py, FCP_API pointing at the v6 worktree) against the same package with them off, on meshes
(or a cloud kind: FCP_INPUT=clean_10000 ...). Parts, Chamfer and normals over 30° at 256 / 1024 / 6144; renders at 1024 and
6144 for the objects given in FCP_RENDER. Prints, and writes ../report/lobes_check_<input>.csv.

    FCP_API=/home/joao/code/fcp_devel_v6/api env -u PYTHONPATH PYTHONWARNINGS=ignore .venv/bin/python \\
        ~/code/data/meshes/fcp_2910_v6/scripts/lobes_check.py [objects...]
"""
import csv
import os
import sys
import time
from pathlib import Path

import numpy as np
import trimesh

sys.path.insert(0, "/home/joao/code/data/meshes/fcp_2810_partition/scripts")  # the shared helpers: objects, measures, renders
from degree_sweep import DEVICE, OBJ, UP, Ref  # noqa: E402  (puts the package on the path)
import fcp  # noqa: E402

REPORT = Path(__file__).resolve().parent.parent / "report"  # fcp_2910_v6/report
IMG = REPORT / "img"
from fcp import _lobes  # noqa: E402
from renders import render  # noqa: E402

INPUT = os.environ.get("FCP_INPUT", "mesh")
RENDER = set(os.environ.get("FCP_RENDER", "mug").split(","))
CLOUDS = Path("/home/joao/code/data/meshes/fcp_2710_tests/pointclouds")
BUDGETS = [256, 1024, 6144]


def main():
    names = sys.argv[1:] or list(OBJ)
    out = REPORT / f"lobes_check_{INPUT}.csv"
    old = [r for r in csv.DictReader(out.open())] if out.exists() else []
    keep = [r for r in old if r["object"] not in names]
    fields = ["object", "config", "atoms", "parts", "chamfer", "p95", "n_over30", "seconds"]
    with out.open("w", newline="") as f:
        w = csv.DictWriter(f, fields)
        w.writeheader()
        w.writerows(keep)
        for name in names:
            g = trimesh.load(OBJ[name], force="mesh")
            ref = Ref(g)
            if INPUT == "mesh":
                geom, kw = g, {}
            else:
                geom = np.asarray(trimesh.load(CLOUDS / f"{name}_{INPUT}.ply").vertices)
                kw = {"noise": 0.006 * float(np.linalg.norm(g.extents))} if INPUT.startswith("pn") else {}
            line = [f"{name:16s}"]
            for cfg, on in (("off", False), ("lobes", True)):
                _lobes.LOBES = on
                t = time.perf_counter()
                d = fcp.encode(geom, atoms=6144, up=UP, device=DEVICE, **kw)
                sec = time.perf_counter() - t
                res = []
                for T in BUDGETS:
                    m = fcp.decode(d.prefix(T), device=DEVICE)
                    v = ref.measure(m)
                    res.append(v)
                    w.writerow(dict(object=name, config=cfg, atoms=T, parts=len(d.parts), chamfer=round(float(v[0]), 5),
                                    p95=round(float(v[1]), 5), n_over30=round(float(v[3]), 3), seconds=round(sec, 2)))
                    if name in RENDER and T in (1024, 6144):
                        render(d.prefix(T), m, IMG / f"lobes_{INPUT}_{name}_{cfg}_a{T}.png",
                               f"{name} ({INPUT}): v6 lobes {cfg}, {T} atoms, {len(d.parts)} parts")
                line.append(f"{cfg}: {len(d.parts):3d}p ch " + "/".join(f"{v[0]:.3f}" for v in res)
                            + " n30 " + "/".join(f"{v[3]:.1f}" for v in res) + f" {sec:.1f}s")
            _lobes.LOBES = True
            f.flush()
            print("  ".join(line), flush=True)


if __name__ == "__main__":
    main()
