#!/usr/bin/env python3
"""make_images.py — LOG479 (フィジカルAI研究室 Log#26) の記事の画像を作る. 元の記録は読むだけ.
書き出し先: 第1引数のフォルダ (既定は iCloud の フィジカルAI研究室を作る/LOG479_images/)
  LOG479_01_pos3_old_vs_new.jpg  位置3 の閉じて 1.0 秒後の上カメラ. 左: 元の記録 (120818・42.5px), 右: 教え直し (124117・2.7px)
  LOG479_03_pos3_align.jpg       位置3 の最初のコマにブロックの枠を重ねた図 (緑: 深かった本, 赤: 浅かった本)
  LOG479_04_pos4_descent.jpg     位置4 の下ろす区間の上カメラ 5 コマ × 3 段 (125825 差し替え版・193825 10/19・130542 教え直し)
  LOG479_02_measure_cable.jpg    measure の確認画像 (measure_20261109_123559.jpg) を 1280 幅に縮めたもの
"""
import bisect, csv, json, sys
from pathlib import Path
import cv2
import numpy as np

DATA = Path("/Volumes/KIOXIA/r2r2r-data")
OUT = Path(sys.argv[1]) if len(sys.argv) > 1 else Path.home() / "Library/Mobile Documents/com~apple~CloudDocs/デスクトップ/ADAPT DESIGN/じぶんの/PixelstoMotors/デジタルツイン学習R2R2R/フィジカルAI研究室を作る/LOG479_images"
if len(sys.argv) > 2:
    DATA = Path(sys.argv[2])
RUNS = DATA / "runs/run_pick_place"
OUT.mkdir(parents=True, exist_ok=True)


def frame_at(run, t):
    ts = [float(r["capture_ts"]) for r in csv.DictReader(open(RUNS / run / "recording/top_frame_log.csv"))]
    cap = cv2.VideoCapture(str(RUNS / run / "recording/top.mp4"))
    cap.set(cv2.CAP_PROP_POS_FRAMES, min(bisect.bisect_left(ts, t), len(ts) - 1))
    ok, f = cap.read()
    cap.release()
    return f


def stage_t(run, name):
    st = list(csv.DictReader(open(RUNS / run / "recording/states.csv")))
    return [float(r["ts"]) for r in st if r["event_type"] == "stage" and r["stage"] == name][0]


def label(img, text):
    cv2.rectangle(img, (0, 0), (img.shape[1], 34), (20, 20, 20), -1)
    cv2.putText(img, text, (10, 24), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (240, 240, 240), 2, cv2.LINE_AA)
    return img


# 1. 位置3: 元の記録と教え直しの, 閉じて 1.0 秒後 (grasp_depth.py が測るコマ)
sys.path.insert(0, str(Path.home() / "r2r2r-scripts/pi05"))
import grasp_depth as gd  # noqa: E402
tiles = []
for run, txt in [("run_0001_20261109_120818", "old teach  42.5px"), ("run_0001_20261109_124117", "re-taught  2.7px")]:
    m = gd.measure_run(RUNS / run)
    cap = cv2.VideoCapture(str(RUNS / run / "recording/top.mp4"))
    cap.set(cv2.CAP_PROP_POS_FRAMES, m["frame_after"])
    ok, f = cap.read()
    cap.release()
    cx, cy = m["center_px"]
    c = f[max(0, cy - 260):cy + 260, max(0, cx - 330):cx + 330].copy()
    tiles.append(label(cv2.resize(c, (660, 520)), txt))
cv2.imwrite(str(OUT / "LOG479_01_pos3_old_vs_new.jpg"), np.hstack(tiles), [cv2.IMWRITE_JPEG_QUALITY, 90])

# 2. measure の確認画像 (ケーブルを拾った回)
f = cv2.imread(str(DATA / "mecharm_calibration/teach_poses_20261109/measure_20261109_123559.jpg"))
cv2.imwrite(str(OUT / "LOG479_02_measure_cable.jpg"), cv2.resize(f, (1280, 720)), [cv2.IMWRITE_JPEG_QUALITY, 90])

# 3. 位置3 の置き場所 (最初のコマのブロックの枠)
runs = {"124117": ("deep 2.7", (0, 200, 0)), "124256": ("deep 4.5", (0, 200, 0)), "123848": ("deep 9.5", (0, 200, 0)),
        "123655": ("shallow 25.9", (0, 0, 255)), "123940": ("shallow 25.6", (0, 0, 255))}
base = None
for k, (r, (txt, col)) in enumerate(runs.items()):
    cap = cv2.VideoCapture(str(RUNS / f"run_0001_20261109_{r}/recording/top.mp4"))
    ok, f = cap.read()
    cap.release()
    if base is None:
        base = f.copy()
    hsv = cv2.cvtColor(f, cv2.COLOR_BGR2HSV)
    m = cv2.inRange(hsv, (0, 40, 80), (12, 255, 255)) | cv2.inRange(hsv, (158, 40, 80), (180, 255, 255))
    m[:500, :] = 0   # 根元とケーブルを除く
    m = cv2.morphologyEx(m, cv2.MORPH_OPEN, np.ones((5, 5), np.uint8))
    cs, _ = cv2.findContours(m, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    rect = cv2.minAreaRect(max(cs, key=cv2.contourArea))
    cv2.drawContours(base, [cv2.boxPoints(rect).astype(int)], 0, col, 2)
    cx, cy = map(int, rect[0])
    cv2.putText(base, f"{r} {txt}", (cx + 60, cy - 40 + 20 * k), cv2.FONT_HERSHEY_SIMPLEX, 0.6, col, 2)
crop = cv2.resize(base[480:900, 420:1000], None, fx=1.6, fy=1.6)
cv2.imwrite(str(OUT / "LOG479_03_pos3_align.jpg"), crop, [cv2.IMWRITE_JPEG_QUALITY, 90])

# 4. 位置4 の下ろす区間 (PICK の段階の 0.5 秒前から, 段階の終わりの 2 秒前まで)
rows = []
for run, txt in [("run_0001_20261109_125825", "125825 (13:00) "), ("run_0001_20261019_193825", "193825 (10/19) "),
                 ("run_0001_20261109_130542", "130542 (13:03) ")]:
    tp, tl = stage_t(run, "PICK"), stage_t(run, "APPROACH_PICK_LIFT")
    row = []
    for t in [tp - 0.5] + list(np.linspace(tp + 0.5, max(tp + 0.6, tl - 2.0), 4)):
        f = frame_at(run, t)
        c = cv2.resize(f[100:700, 300:1000], None, fx=0.5, fy=0.5)
        cv2.putText(c, f"{txt}{t - tp:+.1f}s", (5, 20), 0, 0.6, (0, 255, 255), 2)
        row.append(c)
    rows.append(np.hstack(row))
cv2.imwrite(str(OUT / "LOG479_04_pos4_descent.jpg"), np.vstack(rows), [cv2.IMWRITE_JPEG_QUALITY, 90])
print("ok", sorted(p.name for p in OUT.glob("LOG479_*")))
