"""CANONICAL ArUco board registry for the whole system (single source of truth — import this, never
redefine constants inline). All boards: cv2.aruco.DICT_6X6_250. ID ALLOCATIONS (must never overlap):
  100-108  smith300 arm base board (this file)
  190-198  UMI gripper cube TOP    (this file)
  200-208  UMI gripper cube BACK   (this file)
  217-225  fiducial exoskeleton arm 1   (exo_redo/ExoConfigs/panda_exo.py — NOT ours to move)
  226-234  fiducial exoskeleton arm 2   (exo_redo)
  240,241  DEPRECATED UMI singles (2026-07-07) — do not reuse until physical sheets confirmed destroyed
"""
import numpy as np
import cv2

DICT = cv2.aruco.getPredefinedDictionary(cv2.aruco.DICT_6X6_250)

ARM_BASE = dict(name="arm_base", shape=(3, 3), marker_m=0.020, sep_m=0.005,
                margin_m=0.005, sheet_mm=80.0, ids=np.arange(100, 109))
# ^ 2026-07-11: shrunk to the 80mm UMI-grid layout (fused base, board 80x80). SUPERSEDES the
#   160mm/42.29mm layout — destroy old 160 prints; detection code must use these constants.
UMI_TOP = dict(name="umi_top", shape=(3, 3), marker_m=0.020, sep_m=0.005,
               margin_m=0.005, sheet_mm=80.0, ids=np.arange(190, 199))
UMI_BACK = dict(name="umi_back", shape=(3, 3), marker_m=0.020, sep_m=0.005,
                margin_m=0.005, sheet_mm=80.0, ids=np.arange(200, 209))
EXO_ARM1_IDS = np.arange(217, 226)   # owned by exo_redo, listed for overlap checks only
EXO_ARM2_IDS = np.arange(226, 235)

UMI_V2 = dict(name="umi_v2", shape=(4, 3), marker_m=0.020, sep_m=0.005,
              margin_m=0.005, sheet_mm=(120.0, 80.0), ids=np.arange(150, 162))
# ^ v2 wand single-slab board (2026-07-09): 4x3 on the 120x80 face. v1 cube boards (190-208) stay
#   reserved while the printed v1 wand exists.

ALL_BOARDS = [ARM_BASE, UMI_TOP, UMI_BACK, UMI_V2]


def board(spec):
    """cv2.aruco.GridBoard for a spec dict from this registry."""
    return cv2.aruco.GridBoard(spec["shape"], spec["marker_m"], spec["sep_m"], DICT, spec["ids"])


def check_no_overlaps():
    groups = {s["name"]: set(s["ids"].tolist()) for s in ALL_BOARDS}
    groups["exo_arm1"] = set(EXO_ARM1_IDS.tolist())
    groups["exo_arm2"] = set(EXO_ARM2_IDS.tolist())
    names = list(groups)
    ok = True
    for i in range(len(names)):
        for j in range(i + 1, len(names)):
            inter = groups[names[i]] & groups[names[j]]
            if inter:
                ok = False
                print(f"OVERLAP {names[i]} vs {names[j]}: {sorted(inter)}")
    return ok


if __name__ == "__main__":
    print("overlap check:", "PASS - all ID ranges disjoint" if check_no_overlaps() else "FAIL")
