"""Build fig3_realrobot.svg — two rows of real-robot results cards.

Row 1: In-Distribution (3 tasks)
Row 2: Out-of-Distribution (3 conditions, pick-and-place)

Each card = rendered frame + task/condition name + PARA vs ACT vs Motion Tracks numbers.
"""

import base64
import time

_t = time.time()

def b64(p):
    return base64.b64encode(open(p, "rb").read()).decode()

ASSETS = "/data/cameron/penpot/figures/extracted/fig3"

# Row 1 — in-distribution
row1 = [
    {
        "name": "Pick & Place",
        "img": b64(f"{ASSETS}/pickplace.png"),
        "para": "97%", "act": "9%", "mt": "5%",
    },
    {
        "name": "Wipe Table",
        "img": b64(f"{ASSETS}/wipe.png"),
        "para": "95%", "act": "0%", "mt": "61%",
    },
    {
        "name": "Fold Towel",
        "img": b64(f"{ASSETS}/fold.png"),
        "para": "97%", "act": "11%", "mt": "42%",
    },
]

# Row 2 — out-of-distribution (all pick-and-place)
row2 = [
    {
        "name": "New Viewpoint (zero-shot)",
        "img": b64(f"{ASSETS}/newview.png"),
        "para": "52%", "act": "0%", "mt": "0%",
    },
    {
        "name": "New Viewpoint + 5ep FT",
        "img": b64(f"{ASSETS}/newview_ft.png"),
        "para": "87%", "act": "4%", "mt": "0%",
    },
    {
        "name": "New Environment",
        "img": b64(f"{ASSETS}/newenv.png"),
        "para": "94%", "act": "0%", "mt": "6%",
    },
]

GREEN = "#16653a"
RED = "#a12029"
GRAY = "#6b7280"
SLATE = "#334155"
LIGHT = "#e5e7eb"
TXT = "#0f172a"


def build_card(x, y, cfg, card_id):
    """Emit SVG for one card at (x, y). Card is 440 wide × 250 tall."""
    W, H = 440, 250
    img_x = x + 12
    img_y = y + 12
    img_w = W - 24  # 416
    img_h = 160
    name_y = y + 195
    label_y = y + 217
    num_y = y + 245

    # Column centers for the three numbers
    col_para = x + 88
    col_act = x + 220
    col_mt = x + 352

    return f'''
    <g id="{card_id}">
      <rect x="{x}" y="{y}" width="{W}" height="{H}" rx="12"
            fill="#ffffff" stroke="{LIGHT}" stroke-width="1.2" filter="url(#card-shadow)"/>
      <clipPath id="clip-{card_id}">
        <rect x="{img_x}" y="{img_y}" width="{img_w}" height="{img_h}" rx="7"/>
      </clipPath>
      <image xlink:href="data:image/png;base64,{cfg['img']}"
             x="{img_x}" y="{img_y}" width="{img_w}" height="{img_h}"
             preserveAspectRatio="xMidYMid slice" clip-path="url(#clip-{card_id})"/>
      <rect x="{img_x}" y="{img_y}" width="{img_w}" height="{img_h}" rx="7"
            fill="none" stroke="{LIGHT}" stroke-width="1"/>

      <text x="{x + W/2}" y="{name_y}" text-anchor="middle" font-size="16" font-weight="800" fill="{TXT}">{cfg['name']}</text>

      <!-- small labels above each number -->
      <text x="{col_para}" y="{label_y}" text-anchor="middle" font-size="10" font-weight="700" fill="{GRAY}" letter-spacing="0.06em">PARA</text>
      <text x="{col_act}" y="{label_y}" text-anchor="middle" font-size="10" font-weight="700" fill="{GRAY}" letter-spacing="0.06em">ACT</text>
      <text x="{col_mt}" y="{label_y}" text-anchor="middle" font-size="10" font-weight="700" fill="{GRAY}" letter-spacing="0.06em">MOTION TRACKS</text>

      <!-- big numbers -->
      <text x="{col_para}" y="{num_y}" text-anchor="middle" font-size="26" font-weight="900" fill="{GREEN}" letter-spacing="-0.02em">{cfg['para']}</text>
      <text x="{col_act}" y="{num_y}" text-anchor="middle" font-size="26" font-weight="900" fill="{RED}" letter-spacing="-0.02em">{cfg['act']}</text>
      <text x="{col_mt}" y="{num_y}" text-anchor="middle" font-size="26" font-weight="900" fill="{GRAY}" letter-spacing="-0.02em">{cfg['mt']}</text>
    </g>
    '''


# Positions: 3 cards per row
X_POSITIONS = [20, 480, 940]

row1_cards = "".join(
    build_card(X_POSITIONS[i], 85, cfg, f"r1c{i}")
    for i, cfg in enumerate(row1)
)
row2_cards = "".join(
    build_card(X_POSITIONS[i], 400, cfg, f"r2c{i}")
    for i, cfg in enumerate(row2)
)

svg = f'''<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
     viewBox="0 0 1400 680" width="1400" height="680"
     font-family="Inter, Arial, sans-serif">
  <defs>
    <filter id="card-shadow" x="-10%" y="-10%" width="120%" height="130%">
      <feDropShadow dx="0" dy="1.5" stdDeviation="2.5" flood-color="#000" flood-opacity="0.08"/>
    </filter>
  </defs>

  <rect width="1400" height="680" fill="#ffffff"/>

  <!-- Row 1 header -->
  <text x="30" y="38" font-size="16" font-weight="800" fill="{TXT}">(a) In-distribution results</text>
  <text x="30" y="58" font-size="12" font-weight="500" fill="{GRAY}">
    <tspan font-weight="700" letter-spacing="0.04em">TRAINING VIEWPOINT + ENVIRONMENT</tspan> · 20 demonstrations per task
  </text>
  <line x1="30" y1="70" x2="1370" y2="70" stroke="{LIGHT}" stroke-width="1"/>

  {row1_cards}

  <!-- Row 2 header -->
  <text x="30" y="358" font-size="16" font-weight="800" fill="{TXT}">(b) Out-of-distribution robustness (pick &amp; place)</text>
  <text x="30" y="378" font-size="12" font-weight="500" fill="{GRAY}">
    <tspan font-weight="700" letter-spacing="0.04em">ROBUSTNESS EVALUATIONS</tspan> · same pick-and-place task, zero-shot unless noted
  </text>
  <line x1="30" y1="390" x2="1370" y2="390" stroke="{LIGHT}" stroke-width="1"/>

  {row2_cards}
</svg>
'''

out = "/data/cameron/para/paper/figs/svg/fig3_realrobot.svg"
with open(out, "w") as f:
    f.write(svg)
print(f"[{time.time()-_t:.2f}s] wrote {out} ({len(svg)} bytes)")
