/* cl-switch.jsx — the switched-branches example for the Circuit Lab.
   A SERIES-PARALLEL ladder: two sections in series, jumpered together; each
   section is a parallel block of two switched resistor branches (R1 ∥ R2).
     • a closed switch lets its resistor join its section
     • an open branch greys out (no charge)
     • if a whole section has no path, the entire circuit is still (series!)
   Switches click in both views. Charges carry the direction colour; wires stay
   neutral. Names cw*. Exports ClSchematicSwitch, ClBreadboardSwitch. */

/* clickable switch symbol, hinge (x,yA) → contact (x,yB). Closed = neutral lever
   bridging; open = lever lifted with a visible gap (grey). */
function cwSwitchSym(x, yA, yB, closed, onToggle, key, label) {
  const lever = closed
    ? <line x1={x} y1={yA} x2={x} y2={yB} stroke="var(--ink-soft)" strokeWidth="3.2" strokeLinecap="round" />
    : <line x1={x} y1={yA} x2={x + 24} y2={yA - 24} stroke={window.CL_STILL} strokeWidth="3.2" strokeLinecap="round" />;
  return (
    <g key={key} style={{ cursor: "pointer" }} onClick={onToggle}>
      <circle cx={x} cy={yA} r="4.5" fill="var(--ink)" />
      <circle cx={x} cy={yB} r="4.5" fill={closed ? "var(--ink)" : "var(--ink-faint)"} />
      {lever}
      <rect x={x - 28} y={yA - 30} width="58" height={(yB - yA) + 40} fill="transparent" />
      <text x={x + 14} y={yA - 12} fontFamily="IBM Plex Mono, monospace" fontSize="12"
            fill={closed ? "var(--current)" : "var(--ink-faint)"} fontWeight="600">{label} {closed ? "ON" : "OFF"}</text>
    </g>
  );
}

/* one switched branch (switch on top, resistor below) spanning yTop..yBot at x.
   Returns an array of svg elements. Charges ride the branch; sign + = top→bottom. */
function cwBranch(x, yTop, yBot, closed, Isig, onToggle, label, R, flowMul, labelSide, vTop, vBot, vref) {
  const hingeY = yTop + 26, contactY = hingeY + 32, resTop = contactY + 12, resBot = yBot - 4;
  const aI = Math.abs(Isig);
  const tx = labelSide === "left" ? x - 18 : x + 18, anc = labelSide === "left" ? "end" : "start";
  return [
    <window.ClWire key={label + "lt"} pts={[{ x, y: yTop }, { x, y: hingeY }]} current={0} dots={false} vStart={vTop} vEnd={vTop} vref={vref} width={2.6} />,
    <window.ClWire key={label + "lc"} pts={[{ x, y: contactY }, { x, y: resTop }]} current={0} dots={false} vStart={vTop} vEnd={vTop} vref={vref} width={2.6} />,
    <window.ClWire key={label + "lb"} pts={[{ x, y: resBot }, { x, y: yBot }]} current={0} dots={false} vStart={vBot} vEnd={vBot} vref={vref} width={2.6} />,
    <window.ClResistorV key={label + "r"} x0={x} y0={resTop} x1={x} y1={resBot} vStart={vTop} vEnd={vBot} vref={vref} width={3} />,
    <window.ClFlow key={label + "f"} path={window.clPath([{ x, y: yTop }, { x, y: yBot }])} current={Isig} speedMul={flowMul} gap={26} />,
    cwSwitchSym(x, hingeY, contactY, closed, onToggle, label + "sw", label),
    <text key={label + "rv"} x={tx} y={(resTop + resBot) / 2 - 3} textAnchor={anc} fontFamily="IBM Plex Mono, monospace" fontSize="14" fill="var(--ink)" fontWeight="600">{window.fmtOhm(R)}</text>,
    <text key={label + "iv"} x={tx} y={(resTop + resBot) / 2 + 15} textAnchor={anc} fontFamily="IBM Plex Mono, monospace" fontSize="13" fill={closed ? "var(--current)" : "var(--ink-faint)"} fontWeight="600">{closed ? window.fmtI(aI) : "0 mA"}</text>,
  ];
}

function cwCurrents(sim) {
  const g = (i) => (sim.current ? (sim.current[i] || 0) : 0);
  const IA1 = g(2), IA2 = g(4), IB1 = g(6), IB2 = g(8);
  return { IA1, IA2, IB1, IB2, Itot: IA1 + IA2 };
}

function ClSchematicSwitch({ V, Ra1, Ra2, Rb1, Rb2, sim, kids, sw, onToggle, flowMul = 1 }) {
  const { IA1, IA2, IB1, IB2, Itot } = cwCurrents(sim);
  const vMid = sim.probe ? sim.probe("midA") : 0;
  const vref = Math.abs(V) || 9;
  const batX = 110, yTop = 86, yMid = 250, yBot = 410;
  const xA1 = 250, xA2 = 338, xB1 = 442, xB2 = 530;
  const W = (pts, cur, vs, ve, key, stroke) => <window.ClWire key={key} pts={pts} current={cur} flowMul={flowMul} gap={28} width={stroke ? 2.8 : 2.6} vStart={vs} vEnd={ve} vref={vref} stroke={stroke || "var(--ink-soft)"} />;

  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 604 452" width="100%" style={{ display: "block" }}>
        {/* battery (schematic symbol) on the left, leads carry the trunk */}
        {(() => { const my = (yTop + yBot) / 2; return (
          <g>
            {W([{ x: batX, y: my - 18 }, { x: batX, y: yTop }], Itot, V, V, "bl1")}
            {W([{ x: batX, y: yBot }, { x: batX, y: my + 18 }], Itot, 0, 0, "bl2")}
            <line x1={batX - 17} y1={my - 18} x2={batX + 17} y2={my - 18} stroke="var(--ink)" strokeWidth="3.4" />
            <line x1={batX - 9} y1={my - 7} x2={batX + 9} y2={my - 7} stroke="var(--ink)" strokeWidth="2.2" />
            <line x1={batX - 17} y1={my + 4} x2={batX + 17} y2={my + 4} stroke="var(--ink)" strokeWidth="3.4" />
            <line x1={batX - 9} y1={my + 15} x2={batX + 9} y2={my + 15} stroke="var(--ink)" strokeWidth="2.2" />
            <text x={batX - 26} y={my - 12} textAnchor="end" fontFamily="IBM Plex Mono, monospace" fontSize="15" fill="var(--current)">+</text>
            <text x={batX - 26} y={my + 24} textAnchor="end" fontFamily="IBM Plex Mono, monospace" fontSize="15" fill="var(--ink-soft)">−</text>
            <text x={batX - 40} y={my + 6} textAnchor="end" fontFamily="IBM Plex Mono, monospace" fontSize="16" fill="var(--ink)" fontWeight="600">{window.fmtV(V)}</text>
          </g>
        ); })()}

        {/* top rail: bat→A1 (trunk), A1→A2 (after A1 taps) — node = V */}
        {W([{ x: batX, y: yTop }, { x: xA1, y: yTop }], Itot, V, V, "tr0")}
        {W([{ x: xA1, y: yTop }, { x: xA2, y: yTop }], IA2, V, V, "tr1")}
        {/* mid rail: A1→A2 (IA1), JUMPER A2→B1 (trunk, black), B1→B2 (IB2) — node = vMid */}
        {W([{ x: xA1, y: yMid }, { x: xA2, y: yMid }], IA1, vMid, vMid, "mr0")}
        {W([{ x: xA2, y: yMid }, { x: xB1, y: yMid }], Itot, vMid, vMid, "mr1", "var(--ink)")}
        {W([{ x: xB1, y: yMid }, { x: xB2, y: yMid }], IB2, vMid, vMid, "mr2")}
        {/* bottom rail: B2→B1 (IB2), B1→bat (trunk) — node = 0 */}
        {W([{ x: xB2, y: yBot }, { x: xB1, y: yBot }], IB2, 0, 0, "br0")}
        {W([{ x: xB1, y: yBot }, { x: batX, y: yBot }], Itot, 0, 0, "br1")}

        {/* section A branches (yTop→yMid): V → vMid */}
        {cwBranch(xA1, yTop, yMid, sw[0], IA1, () => onToggle(0), "SW1", Ra1, flowMul, "left", V, vMid, vref)}
        {cwBranch(xA2, yTop, yMid, sw[1], IA2, () => onToggle(1), "SW2", Ra2, flowMul, "right", V, vMid, vref)}
        {/* section B branches (yMid→yBot): vMid → 0 */}
        {cwBranch(xB1, yMid, yBot, sw[2], IB1, () => onToggle(2), "SW3", Rb1, flowMul, "left", vMid, 0, vref)}
        {cwBranch(xB2, yMid, yBot, sw[3], IB2, () => onToggle(3), "SW4", Rb2, flowMul, "right", vMid, 0, vref)}

        {/* node dots */}
        {[[xA1, yTop], [xA2, yTop], [xA1, yMid], [xA2, yMid], [xB1, yMid], [xB2, yMid], [xB1, yBot], [xB2, yBot]].map((p, i) => <circle key={i} cx={p[0]} cy={p[1]} r="4" fill="var(--ink)" />)}

        {/* labels */}
        <text x={(batX + xA1) / 2} y={yTop - 12} textAnchor="middle" fontFamily="IBM Plex Mono, monospace" fontSize="14" fill="var(--ink)" fontWeight="600">trunk {window.fmtI(Math.abs(Itot))}</text>
        <text x={(xA2 + xB1) / 2} y={yMid - 12} textAnchor="middle" fontFamily="IBM Plex Mono, monospace" fontSize="13" fill="var(--ink-soft)" fontWeight="600">jumper</text>
        <text x={xA1 - 4} y={yTop - 30} textAnchor="middle" fontFamily="IBM Plex Mono, monospace" fontSize="12" fill="var(--ink-faint)">section A · R1∥R2</text>
        <text x={xB1 - 4} y={yMid + 4} textAnchor="start" fontFamily="IBM Plex Mono, monospace" fontSize="12" fill="var(--ink-faint)"> </text>
      </svg>
      <div style={{ fontSize: 12.5, color: "var(--ink-faint)", padding: "2px 10px 8px", lineHeight: 1.5 }}>
        {kids
          ? "Two groups of switches, joined by a jumper. Inside a group the paths share; the two groups are in a line, so if one whole group is switched off, everything stops."
          : "Two parallel sections in series, joined by the jumper. Within a section the branch currents split (R1∥R2); the sections carry the same trunk current. Open every branch in a section and the whole loop goes still."}
      </div>
    </div>
  );
}

function ClBreadboardSwitch({ V, Ra1, Ra2, Rb1, Rb2, sim, kids, sw, onToggle, flowMul = 1 }) {
  const { IA1, IA2, IB1, IB2, Itot } = cwCurrents(sim);
  const vMid = sim.probe ? sim.probe("midA") : 0;
  const vref = Math.abs(V) || 9;
  const railTopY = 84, railBotY = 388, batX = 60;
  const xA1 = 188, xA2 = 250, xB1 = 360, xB2 = 422, midY = 236;
  const secTopY = 116, secBotY = 356;   // branch spans
  const boardFill = "#e8e0cf";
  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.5" />); return o; };

  return (
    <div style={{ background: "var(--bg-card)", border: "1px solid var(--rule)", borderRadius: 12, padding: "8px 8px 4px" }}>
      <svg viewBox="-26 0 524 452" width="100%" style={{ display: "block" }}>
        <rect x="36" y="62" width="452" height="348" rx="12" fill={boardFill} stroke="#c9bda3" strokeWidth="1.5" />
        {/* + / − rails */}
        <line x1="70" y1={railTopY} x2="470" y2={railTopY} stroke="#c0392b" strokeWidth="2.5" opacity="0.8" />
        <line x1="70" y1={railBotY} x2="470" y2={railBotY} stroke="#2f6db0" strokeWidth="2.5" opacity="0.8" />
        {holeRow(railTopY, 82, 458, 13, "rt")}
        {holeRow(railBotY, 82, 458, 13, "rb")}
        <text x="56" y={railTopY + 5} textAnchor="end" fontFamily="IBM Plex Mono, monospace" fontSize="15" fill="#c0392b">+</text>
        <text x="56" y={railBotY + 5} textAnchor="end" fontFamily="IBM Plex Mono, monospace" fontSize="15" fill="#2f6db0">−</text>

        {/* mid terminal strip (node between sections) + the jumper to it */}
        <line x1={xA1 - 6} y1={midY} x2={xA2 + 6} y2={midY} stroke="var(--ink-faint)" strokeWidth="2" opacity="0.6" />
        <line x1={xB1 - 6} y1={midY} x2={xB2 + 6} y2={midY} stroke="var(--ink-faint)" strokeWidth="2" opacity="0.6" />

        {/* battery cell on the left */}
        {window.clBatteryCell(batX, railTopY, railBotY, V, "batcell")}

        {/* section A: rail(top) → switch → resistor → mid strip */}
        {window.clResBody(xA1, secTopY + 70, secBotY - (secBotY - midY), "ra1")}
        {window.clResBody(xA2, secTopY + 70, midY, "ra2")}
        {/* section B: mid strip → switch → resistor → rail(bottom) */}
        {window.clResBody(xB1, midY + 70, secBotY, "rb1")}
        {window.clResBody(xB2, midY + 70, secBotY, "rb2")}

        {/* switches at the tops of each branch */}
        {cwSwitchSym(xA1, railTopY + 14, railTopY + 46, sw[0], () => onToggle(0), "swA1", "SW1")}
        {cwSwitchSym(xA2, railTopY + 14, railTopY + 46, sw[1], () => onToggle(1), "swA2", "SW2")}
        {cwSwitchSym(xB1, midY + 14, midY + 46, sw[2], () => onToggle(2), "swB1", "SW3")}
        {cwSwitchSym(xB2, midY + 14, midY + 46, sw[3], () => onToggle(3), "swB2", "SW4")}

        {/* jumper wire between section A out and section B in — black, with charges */}
        <window.ClWire pts={window.clArc({ x: xA2 + 6, y: midY }, { x: (xA2 + xB1) / 2, y: midY - 30 }, { x: xB1 - 6, y: midY }, 14)}
                       current={Itot} flowMul={flowMul} gap={26} width={3} stroke="var(--ink)" vStart={vMid} vEnd={vMid} vref={vref} />
        <text x={(xA2 + xB1) / 2} y={midY - 34} textAnchor="middle" fontFamily="IBM Plex Mono, monospace" fontSize="12.5" fill="var(--ink-soft)" fontWeight="600">jumper</text>

        {/* value labels */}
        <text x={xA1} y={secTopY + 64} textAnchor="middle" fontFamily="IBM Plex Mono, monospace" fontSize="12.5" fill="var(--ink)" fontWeight="600">{window.fmtOhm(Ra1)}</text>
        <text x={xA2} y={secTopY + 64} textAnchor="middle" fontFamily="IBM Plex Mono, monospace" fontSize="12.5" fill="var(--ink)" fontWeight="600">{window.fmtOhm(Ra2)}</text>
        <text x={xB1} y={midY + 64} textAnchor="middle" fontFamily="IBM Plex Mono, monospace" fontSize="12.5" fill="var(--ink)" fontWeight="600">{window.fmtOhm(Rb1)}</text>
        <text x={xB2} y={midY + 64} textAnchor="middle" fontFamily="IBM Plex Mono, monospace" fontSize="12.5" fill="var(--ink)" fontWeight="600">{window.fmtOhm(Rb2)}</text>

        {/* charges on every conducting segment (rails keep red/blue), voltage-coloured */}
        {[
          [[{ x: batX, y: railBotY }, { x: batX, y: railTopY }], Itot, 0, V, "bat"],
          [[{ x: batX, y: railTopY }, { x: xA1, y: railTopY }], Itot, V, V, "t0"],
          [[{ x: xA1, y: railTopY }, { x: xA2, y: railTopY }], IA2, V, V, "t1"],
          [[{ x: xA1, y: railTopY + 46 }, { x: xA1, y: midY }], IA1, V, vMid, "a1"],
          [[{ x: xA2, y: railTopY + 46 }, { x: xA2, y: midY }], IA2, V, vMid, "a2"],
          [[{ x: xA1, y: midY }, { x: xA2, y: midY }], IA1, vMid, vMid, "m0"],
          [[{ x: xB1, y: midY }, { x: xB2, y: midY }], IB2, vMid, vMid, "m1"],
          [[{ x: xB1, y: midY + 46 }, { x: xB1, y: railBotY }], IB1, vMid, 0, "b1"],
          [[{ x: xB2, y: midY + 46 }, { x: xB2, y: railBotY }], IB2, vMid, 0, "b2"],
          [[{ x: xB2, y: railBotY }, { x: xB1, y: railBotY }], IB2, 0, 0, "t2"],
          [[{ x: xB1, y: railBotY }, { x: batX, y: railBotY }], Itot, 0, 0, "t3"],
        ].map(([pts, I, vs, ve, k]) => (
          <window.ClFlow key={k} path={window.clPath(pts)} current={I} speedMul={flowMul} gap={26} vStart={vs} vEnd={ve} vref={vref} />
        ))}
      </svg>
      <div style={{ fontSize: 12.5, color: "var(--ink-faint)", padding: "2px 10px 8px", lineHeight: 1.5 }}>
        {kids
          ? "Two groups of resistors on the board, linked by a jumper wire. Flip switches to add or remove paths in each group."
          : "Two parallel sections built on the board and linked by the jumper. Each resistor joins its section through its own switch; the rails and jumper carry the shared trunk current."}
      </div>
    </div>
  );
}

Object.assign(window, { ClSchematicSwitch, ClBreadboardSwitch });
