/* StrudelPlayer — bindet die externe Live-Coding-Umgebung Strudel (@strudel/embed)
   per Web-Component <strudel-repl> ein. Wird ausschliesslich in Andreas' Bio
   (Über-uns-Sektion) verwendet.

   Wichtig zur Lizenz: @strudel/embed wird NICHT selbst gehostet, sondern von
   unpkg geladen (feste Version, siehe unten). Die Strudel-Runtime läuft im
   eingebetteten iframe extern — die AGPL berührt diese Codebasis dadurch nicht.

   Performance: Das Script wird erst per Klick geladen (nicht beim Seitenaufruf).
   Web Audio: Ton startet erst nach Nutzer-Interaktion (unser Klick lädt, danach
   der Play-Knopf innerhalb von Strudel). */

/* ── Gepinnte Version (NICHT @latest) ── */
const STRUDEL_VERSION = '1.1.2';
const STRUDEL_SRC = `https://unpkg.com/@strudel/embed@${STRUDEL_VERSION}`;

/* ===========================================================================
   STRUDEL-PATTERN — hier austauschen.
   Das Pattern landet 1:1 in einem HTML-Kommentar in <strudel-repl>.
   Regeln: gültiger Strudel/TidalCycles-Code, KEIN "-->" im Text verwenden.
   =========================================================================== */
const STRUDEL_PATTERN = `// High-Tech Minimal | Fis-Moll | 126 BPM
setcps(0.525)

stack(
  // Kick - Four-on-the-Floor
  s("bd*4").bank("RolandTR909"),

  // Hi-Hats mit Swing
  s("hh*16").bank("RolandTR909").gain("[.14 .3 .18 .4]*4").swingBy(1/3, 16),
  // Open Hats auf den Offbeats
  s("[~ oh]*4").bank("RolandTR909").gain(.32),
  // Rimshots als Ghostnotes
  s("~ rim ~ [rim ~] ~ ~ rim ~").bank("RolandTR909").gain(.4).swingBy(1/3, 8),
  // Clap auf der 3, mit Hall
  s("~ ~ cp ~").bank("RolandTR909").gain(.5).room(.3),

  // Offbeat-Bass
  note("[~ fs1]*4").add("<0 0 0 [0 -2]>")
    .s("sawtooth").lpf(650).decay(.16).sustain(0).gain(.85),

  // Pluck-Melodie mit Delay
  note("<[fs4 ~ ~ cs5 ~ ~ a4 ~] [e4 ~ ~ b4 ~ ~ gs4 ~]>")
    .s("square").lpf(2400).decay(.11).sustain(0)
    .delay(.7).delaytime(.25).delayfeedback(.6)
    .room(.4).gain(.5).swingBy(1/3, 8),

  // Pad-Flaeche im Hintergrund
  note("<[fs3,a3,cs4] [e3,gs3,b3]>/2")
    .s("sawtooth").lpf(sine.range(400, 1500).slow(16))
    .attack(.03).release(.5).gain(.28).room(.6).delay(.35)
)`;
/* ===========================  Ende Pattern  =============================== */

/* Lädt das Embed-Script genau einmal (geteilt über alle Instanzen). */
let strudelLoader = null;
function loadStrudel() {
  if (window.customElements && customElements.get('strudel-repl')) {
    return Promise.resolve();
  }
  if (strudelLoader) return strudelLoader;
  strudelLoader = new Promise((resolve, reject) => {
    const existing = document.querySelector('script[data-strudel-embed]');
    if (existing) {
      existing.addEventListener('load', () => resolve());
      existing.addEventListener('error', () => reject(new Error('load-failed')));
      return;
    }
    const s = document.createElement('script');
    s.src = STRUDEL_SRC;
    s.async = true;
    s.setAttribute('data-strudel-embed', '');
    s.onload = () => resolve();
    s.onerror = () => reject(new Error('load-failed'));
    document.head.appendChild(s);
  });
  return strudelLoader;
}

function StrudelPlayer() {
  const [state, setState] = React.useState('idle'); // idle | loading | ready | error
  const hostRef = React.useRef(null);

  const activate = () => {
    if (state === 'loading' || state === 'ready') return;
    setState('loading');
    loadStrudel()
      .then(() => {
        if (hostRef.current) {
          // <strudel-repl> mit dem Pattern im HTML-Kommentar aufbauen.
          hostRef.current.innerHTML =
            '<strudel-repl title="Strudel Live-Coding von Andreas Züst" ' +
            'aria-label="Interaktive Live-Coding-Musikumgebung">' +
            '<!--\n' + STRUDEL_PATTERN + '\n-->' +
            '</strudel-repl>';
        }
        setState('ready');
      })
      .catch(() => setState('error'));
  };

  return (
    <section className="strudel-block" aria-label="Live Coding — Andreas' Musik-Hobby">
      <p className="strudel-label">// Live Coding · mein Hobby</p>

      <div className="strudel-frame">
        {state !== 'ready' && (
          <button
            type="button"
            className="strudel-poster"
            onClick={activate}
            disabled={state === 'loading'}
            aria-label="Live-Coding-Musikumgebung laden — startet danach auf Klick"
          >
            <span className="strudel-play" aria-hidden="true">
              <Icon name="play" size={22} />
            </span>
            <span className="strudel-poster-title">
              {state === 'loading' ? 'Lädt…' : 'Live-Coding starten'}
            </span>
            <span className="strudel-poster-sub">
              Ich mache elektronische Musik per Code. Klick lädt die Umgebung,
              den Ton startest du danach selbst.
            </span>
          </button>
        )}

        {/* Ziel-Container: <strudel-repl> wird hier per innerHTML eingesetzt. */}
        <div
          ref={hostRef}
          className={'strudel-host' + (state === 'ready' ? ' is-ready' : '')}
          aria-live="polite"
        />

        {state === 'error' && (
          <p className="strudel-error" role="alert">
            Die Live-Coding-Umgebung konnte nicht geladen werden. Bitte Seite neu laden.
          </p>
        )}
      </div>

      <p className="strudel-hint">
        Läuft extern über Strudel (@strudel/embed {STRUDEL_VERSION}) · Ton erst nach deinem Play-Klick
      </p>
    </section>
  );
}

/* Styles — nur bestehende CI-Tokens/Variablen, angelehnt an .aboutus-card
   (dunkles Glas, mono Eyebrow, Akzentfarbe für Play) aus TeamSection.jsx. */
const strudelStyles = `
.strudel-block {
  margin-top: 26px; padding-top: 22px;
  border-top: 1px solid rgba(255,255,255,0.12);
}
.strudel-label {
  font-family: var(--font-mono); font-size: 12px; font-weight: 500;
  color: var(--brand-accent); letter-spacing: 0.04em; margin: 0 0 14px;
}
.strudel-frame {
  position: relative; width: 100%;
  border-radius: var(--radius-md); overflow: hidden;
  border: 1px solid rgba(255,255,255,0.10);
  background: rgba(255,255,255,0.045);
}
.strudel-poster {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 12px; width: 100%; min-height: 240px; padding: 32px;
  background: transparent; border: none; cursor: pointer;
  font-family: inherit; color: rgba(255,255,255,0.72); text-align: center;
  transition: background var(--dur-base) var(--ease-out);
}
.strudel-poster:hover { background: rgba(255,255,255,0.03); }
.strudel-poster:focus-visible { outline: none; box-shadow: var(--shadow-focus); }
.strudel-poster:disabled { cursor: progress; opacity: 0.7; }
.strudel-play {
  width: 56px; height: 56px; border-radius: var(--radius-pill);
  background: var(--brand-accent); color: #fff;
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 8px 24px rgba(255,107,53,0.35);
}
.strudel-poster-title {
  font-family: var(--font-mono); font-size: 14px; color: #fff; letter-spacing: 0.01em;
}
.strudel-poster-sub {
  font-size: 12.5px; line-height: 1.55; color: rgba(255,255,255,0.5); max-width: 340px;
}
.strudel-host { display: none; }
.strudel-host.is-ready { display: block; }
.strudel-host strudel-repl { display: block; width: 100%; min-height: 360px; }
.strudel-hint {
  font-family: var(--font-mono); font-size: 11.5px;
  color: rgba(255,255,255,0.4); margin: 10px 0 0;
}
.strudel-error { color: var(--brand-accent-300); font-size: 13px; padding: 16px; margin: 0; }
@media (max-width: 520px) {
  .strudel-poster { min-height: 200px; padding: 24px; }
  .strudel-host strudel-repl { min-height: 300px; }
}
`;
const strudelStyleEl = document.createElement('style');
strudelStyleEl.textContent = strudelStyles;
document.head.appendChild(strudelStyleEl);

window.StrudelPlayer = StrudelPlayer;
