/* cl-led.jsx — LED example for the Circuit Lab: battery · resistor · LED, shown
   on the breadboard and as a schematic, one shared live sim. The teaching point:
   an LED is a ONE-WAY valve. Flip it (tap the LED in either view, or the Flip
   button) and the whole circuit stops — the full battery voltage just sits at
   the blocked part. Names cll*. Exports ClSchematicLed, ClBreadboardLed. */

function cllGlow(x, y, b, id) {
  if (b < 0.03) return null;
  return (
    <g key={id}>
      <defs>
        <radialGradient id={id}>
          <stop offset="0%" stopColor="#ff6a4d" stopOpacity={0.85 * b} />
          <stop offset="100%" stopColor="#ff6a4d" stopOpacity="0" />
        </radialGradient>
      </defs>
      <circle cx={x} cy={y} r={30 + 14 * b} fill={`url(#${id})`} />
    </g>
  );
}

function ClSchematicLed({ V, R, sim, kids, flowMul = 1, flipped, onFlip }) {
  const A = { x: 96, y: 72 }, B = { x: 432, y: 72 }, C = { x: 432, y: 332 }, D = { x: 96, y: 332 };
  const Isig = sim.current ? (sim.current[1] || 0) : 0;
  const I = Math.abs(Isig);
  const bright = sim.brightness ? (sim.brightness[2] || 0) : 0;
  const vN1 = sim.probe ? sim.probe("n1") : 0;
  const vref = Math.abs(V) || 9;
  const blocked = I < 0.0002 && Math.abs(V) > 2.2;

  const r1a = { x: 186, y: 72 }, r1b = { x: 322, y: 72 };
  const ledTop = 168, ledBot = 236, lx = 432, lmid = (ledTop + ledBot) / 2;
  const W = (pts, vs, ve, key) => <window.ClWire key={key} pts={pts} current={Isig} flowMul={flowMul} gap={30} width={2.8} vStart={vs} vEnd={ve} vref={vref} />;
  const ledCol = bright > 0.03 ? "#ff5a4d" : "#8a6f6b";

  return (
    <div style={{ background: "#0b0d11", "--ink": "#f2efe8", "--ink-soft": "#aab2ba", "--ink-faint": "#7c858e", border: "1px solid #2a2f37", borderRadius: 12, padding: "8px 8px 4px" }}>
      <svg viewBox="-26 0 554 404" width="100%" style={{ display: "block" }}>
        {W([A, r1a], V, V, "s_a")}
        <window.ClWire pts={[r1a, r1b]} current={Isig} flowMul={flowMul} gap={30} vStart={V} vEnd={vN1} vref={vref} stroke="none" />
        {W([r1b, B, { x: lx, y: ledTop }], vN1, vN1, "s_m")}
        {W([{ x: lx, y: ledBot }, C, D], 0, 0, "s_g")}
        {window.clSchemBattery(A.x, A.y, D.y, V, Isig, flowMul, vref)}

        {/* resistor on the top edge */}
        <window.ClResistorV x0={r1a.x} y0={r1a.y} x1={r1b.x} y1={r1b.y} vStart={V} vEnd={vN1} vref={vref} width={3} />
        <text x={(r1a.x + r1b.x) / 2} y={r1a.y - 24} textAnchor="middle" fontFamily="IBM Plex Mono, monospace" fontSize="16" fill="var(--ink)" fontWeight="600">R · {window.fmtOhm(R)}</text>

        {/* the LED on the right edge — a diode symbol with light rays. Tap to flip. */}
        {cllGlow(lx, lmid, bright, "cllglow_s")}
        <g onClick={onFlip} style={{ cursor: "pointer" }}>
          <rect x={lx - 30} y={ledTop - 6} width="60" height={ledBot - ledTop + 12} fill="transparent" />
          {flipped ? (
            <g>
              <line x1={lx - 15} y1={lmid - 15} x2={lx + 15} y2={lmid - 15} stroke={ledCol} strokeWidth="3.2" />
              <polygon points={`${lx - 15},${lmid + 17} ${lx + 15},${lmid + 17} ${lx},${lmid - 15}`} fill="none" stroke={ledCol} strokeWidth="2.8" strokeLinejoin="round" />
              <line x1={lx} y1={ledTop} x2={lx} y2={lmid - 15} stroke={ledCol} strokeWidth="2.8" />
              <line x1={lx} y1={lmid + 17} x2={lx} y2={ledBot} stroke={ledCol} strokeWidth="2.8" />
            </g>
          ) : (
            <g>
              <polygon points={`${lx - 15},${lmid - 17} ${lx + 15},${lmid - 17} ${lx},${lmid + 15}`} fill="none" stroke={ledCol} strokeWidth="2.8" strokeLinejoin="round" />
              <line x1={lx - 15} y1={lmid + 15} x2={lx + 15} y2={lmid + 15} stroke={ledCol} strokeWidth="3.2" />
              <line x1={lx} y1={ledTop} x2={lx} y2={lmid - 17} stroke={ledCol} strokeWidth="2.8" />
              <line x1={lx} y1={lmid + 15} x2={lx} y2={ledBot} stroke={ledCol} strokeWidth="2.8" />
            </g>
          )}
          {/* light rays when lit */}
          {bright > 0.03 && (
            <g stroke="#ffd21f" strokeWidth="2" strokeLinecap="round" opacity={0.4 + 0.6 * bright}>
              <line x1={lx + 20} y1={lmid - 22} x2={lx + 30} y2={lmid - 32} />
              <line x1={lx + 26} y1={lmid - 10} x2={lx + 38} y2={lmid - 16} />
            </g>
          )}
        </g>
        <text x={lx - 26} y={lmid - 4} textAnchor="end" fontFamily="IBM Plex Mono, monospace" fontSize="16" fill="var(--ink)" fontWeight="600">LED</text>
        <text x={lx - 26} y={lmid + 15} textAnchor="end" fontFamily="IBM Plex Mono, monospace" fontSize="13" fill={blocked ? "#ff0a3c" : "var(--ink-soft)"}>
          {blocked ? (kids ? "blocked!" : "reverse · blocked") : (kids ? "one-way" : "\u2192 " + (flipped ? "up" : "down") + " only")}
        </text>

        {/* node voltage at the corner between R and LED */}
        <circle cx={B.x} cy={B.y} r="4.5" fill="var(--ink)" />
        <text x={B.x - 10} y={B.y - 12} textAnchor="end" fontFamily="IBM Plex Mono, monospace" fontSize="14" fill="var(--ink-soft)" fontWeight="500">{window.fmtV(vN1)}</text>

        {window.clCurrentTag((A.x + r1a.x) / 2, A.y - 12, I, "i_before", "middle")}
        {window.clCurrentTag(C.x - 10, (ledBot + C.y) / 2, I, "i_after", "end")}
      </svg>
      <div style={{ fontSize: 12.5, color: "var(--ink-faint)", padding: "2px 10px 8px", lineHeight: 1.5 }}>
        {kids
          ? "The triangle is the LED — charge can only go the way it points. Tap the LED to turn it around and watch everything stop."
          : "The LED symbol points the way current may flow; it drops ≈2 V and glows with the current. Tap it to reverse it — note the node voltage: blocked, the full battery voltage piles up across the LED."}
      </div>
    </div>
  );
}

function ClBreadboardLed({ V, R, sim, kids, flowMul = 1, flipped, onFlip }) {
  const Isig = sim.current ? (sim.current[1] || 0) : 0;
  const I = Math.abs(Isig);
  const bright = sim.brightness ? (sim.brightness[2] || 0) : 0;
  const vN1 = sim.probe ? sim.probe("n1") : 0;
  const vref = Math.abs(V) || 9;

  const railTopY = 96, railBotY = 314, batX = 64, r1x = 196, ledx = 332;
  const jumper = window.clArc({ x: r1x, y: 206 }, { x: (r1x + ledx) / 2, y: 188 }, { x: ledx, y: 206 }, 12);
  const F = (pts, vs, ve, key) => <window.ClFlow key={key} path={window.clPath(pts)} current={Isig} speedMul={flowMul} gap={30} />;
  const holeRow = (y, x0, x1, n, pre) => { const o = []; for (let i = 0; i < n; i++) o.push(<circle key={pre + i} cx={x0 + (x1 - x0) * i / (n - 1)} cy={y} r="3" fill="#3a3327" opacity="0.55" />); return o; };

  // LED body: dome between the jumper row (206) and the − rail
  const domeY = 246, domeR = 17;

  return (
    <div style={{ background: "var(--bg-card)", border: "1px solid var(--rule)", borderRadius: 12, padding: "8px 8px 4px" }}>
      <svg viewBox="-26 0 554 404" width="100%" style={{ display: "block" }}>
        <rect x="40" y="60" width="448" height="290" rx="12" fill="#e8e0cf" stroke="#c9bda3" strokeWidth="1.5" />
        <line x1="72" y1={railTopY} x2="456" y2={railTopY} stroke="#c0392b" strokeWidth="2.5" opacity="0.8" />
        <line x1="72" y1={railBotY} x2="456" y2={railBotY} stroke="#2f6db0" strokeWidth="2.5" opacity="0.8" />
        {holeRow(railTopY, 84, 444, 13, "rt")}
        {holeRow(railBotY, 84, 444, 13, "rb")}
        <text x="60" y={railTopY + 5} textAnchor="end" fontFamily="IBM Plex Mono, monospace" fontSize="15" fill="#c0392b">+</text>
        <text x="60" y={railBotY + 5} textAnchor="end" fontFamily="IBM Plex Mono, monospace" fontSize="15" fill="#2f6db0">−</text>
        {[150, 168, 186, 224, 242, 260].map((y, r) => holeRow(y, 84, 444, 13, "t" + r))}

        {window.clBatteryCell(batX, railTopY, railBotY, V, "batcell")}

        {/* resistor from + rail down to the jumper row — value LEFT of the body */}
        {window.clResBody(r1x, railTopY, 206, "r1")}
        <text x={r1x - 18} y="150" textAnchor="end" fontFamily="IBM Plex Mono, monospace" fontSize="15" fill="var(--ink)" fontWeight="600">R · {window.fmtOhm(R)}</text>

        {/* jumper */}
        <path d={`M ${r1x} 206 Q ${(r1x + ledx) / 2} 188 ${ledx} 206`} fill="none" stroke="var(--ink)" strokeWidth="3.6" strokeLinecap="round" />
        <circle cx={r1x} cy="206" r="3.4" fill="var(--ink)" />
        <circle cx={ledx} cy="206" r="3.4" fill="var(--ink)" />

        {/* the LED — tap to flip. Long leg (anode) faces the jumper normally;
            flipped, the flat side faces the jumper and it blocks. */}
        {cllGlow(ledx, domeY, bright, "cllglow_b")}
        <g onClick={onFlip} style={{ cursor: "pointer" }}>
          <rect x={ledx - 30} y={206} width="60" height={railBotY - 206} fill="transparent" />
          <line x1={ledx} y1="206" x2={ledx} y2={domeY - domeR} stroke="var(--ink-soft)" strokeWidth="2.4" />
          <line x1={ledx} y1={domeY + domeR - 3} x2={ledx} y2={railBotY} stroke="var(--ink-soft)" strokeWidth="2.4" />
          <circle cx={ledx} cy={domeY} r={domeR} fill={bright > 0.03 ? `rgba(255,90,77,${0.55 + 0.45 * bright})` : "rgba(190,90,80,0.35)"} stroke="#a04437" strokeWidth="1.6" />
          <circle cx={ledx} cy={domeY} r={domeR - 6} fill={bright > 0.03 ? `rgba(255,190,120,${0.5 + 0.5 * bright})` : "rgba(190,90,80,0.18)"} />
          {/* flat-side (cathode) marker — bottom normally, top when flipped */}
          <line x1={ledx - domeR + 3} y1={flipped ? domeY - domeR + 3 : domeY + domeR - 3} x2={ledx + domeR - 3} y2={flipped ? domeY - domeR + 3 : domeY + domeR - 3} stroke="#7c3328" strokeWidth="3" strokeLinecap="round" />
        </g>
        <text x={ledx + 32} y={domeY - 2} fontFamily="IBM Plex Mono, monospace" fontSize="15" fill="var(--ink)" fontWeight="600">LED</text>
        <text x={ledx + 32} y={domeY + 16} fontFamily="IBM Plex Mono, monospace" fontSize="12.5" fill={I < 0.0002 && Math.abs(V) > 2.2 ? "#c0392b" : "var(--ink-faint)"}>
          {I < 0.0002 && Math.abs(V) > 2.2 ? (kids ? "in backwards!" : "reversed · blocked") : (flipped ? "flat side up" : "flat side down")}
        </text>

        {/* jumper node voltage + current tags */}
        <text x={(r1x + ledx) / 2} y="176" textAnchor="middle" fontFamily="IBM Plex Mono, monospace" fontSize="14" fill="var(--ink-soft)" fontWeight="500">{window.fmtV(vN1)}</text>
        {window.clCurrentTag((batX + r1x) / 2, railTopY - 8, I, "i_pre", "middle")}
        {window.clCurrentTag(ledx + 4, railBotY + 16, I, "i_post", "middle")}

        {/* charges */}
        {F([{ x: batX, y: railTopY }, { x: r1x, y: railTopY }], V, V, "f_pre")}
        {F([{ x: r1x, y: railTopY }, { x: r1x, y: 206 }], V, vN1, "f_r1")}
        {F(jumper, vN1, vN1, "f_jmp")}
        {F([{ x: ledx, y: 206 }, { x: ledx, y: railBotY }], vN1, 0, "f_led")}
        {F([{ x: ledx, y: railBotY }, { x: batX, y: railBotY }], 0, 0, "f_post")}
        {F([{ x: batX, y: railBotY }, { x: batX, y: railTopY }], 0, V, "f_bat")}
      </svg>
      <div style={{ fontSize: 12.5, color: "var(--ink-faint)", padding: "2px 10px 8px", lineHeight: 1.5 }}>
        {kids
          ? "A real LED has a flat side and a short leg — that side must face −. Tap the LED to put it in backwards and see the charges stop."
          : "On the board the schematic's triangle becomes a plastic dome: the flat side / short leg is the cathode and must face −. Tap the LED to reverse it — same blockage as the diagram."}
      </div>
    </div>
  );
}

Object.assign(window, { ClSchematicLed, ClBreadboardLed });
