// Roulsen one-screen homepage — app
const { useState, useEffect, useRef } = React;
const { Eyebrow } = window.RoulsenDesignSystem_aea9bf;
const { RL_TRACKS: TRACKS, RL_CITIES: CITIES } = window.RL_DATA;
const RL_COLLABS = ['SHINee', 'Monsta X', "Girls' Generation", 'Red Velvet', '時代少年團 TNT', 'MIRROR', 'Timmy Trumpet', '王一博', '张靓颖', '李宇春'];
const RL_CREDS_LEAD = ['160+ songs', '“Blackout”', 'Eurovision ’19'];
const RL_CREDS_FULL = [...RL_CREDS_LEAD, ...RL_COLLABS].join('   ·   ');
const RL_CREDS_CURATED = [...RL_CREDS_LEAD, 'SHINee', 'Monsta X', "Girls' Generation"].join('   ·   ');

const RL_TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "comp": "Masthead",
  "mood": "Charcoal",
  "socials": "Right",
  "textLayout": "B",
  "logo": "Left",
  "wmScale": 1
}/*EDITMODE-END*/;

/* ---------- Spotify mini-player ----------
   Uses Spotify's IFrame API so selecting a track loads (and plays) it.
   Falls back to a plain embed iframe if the API doesn't load. */
function SpotifyPlayer({ trackId }) {
  const hostRef = useRef(null);
  const controllerRef = useRef(null);
  const [apiFailed, setApiFailed] = useState(false);
  const firstId = useRef(trackId);

  useEffect(() => {
    let cancelled = false;
    const timer = setTimeout(() => {
      if (!controllerRef.current) setApiFailed(true);
    }, 3500);

    function init(IFrameAPI) {
      if (cancelled || !hostRef.current || controllerRef.current) return;
      IFrameAPI.createController(
        hostRef.current,
        { uri: 'spotify:track:' + firstId.current, width: '100%', height: 80 },
        (controller) => { controllerRef.current = controller; }
      );
    }

    if (window.__spotifyIFrameAPI) {
      init(window.__spotifyIFrameAPI);
    } else {
      const prev = window.onSpotifyIframeApiReady;
      window.onSpotifyIframeApiReady = (IFrameAPI) => {
        window.__spotifyIFrameAPI = IFrameAPI;
        if (prev) prev(IFrameAPI);
        init(IFrameAPI);
      };
    }
    return () => { cancelled = true; clearTimeout(timer); };
  }, []);

  useEffect(() => {
    if (controllerRef.current && trackId !== firstId.current) {
      controllerRef.current.loadUri('spotify:track:' + trackId);
      controllerRef.current.play();
    }
  }, [trackId]);

  return (
    <div className="player">
      <div className="player__frame">
        <div className="player__scale">
          <div ref={hostRef} style={{ display: apiFailed ? 'none' : 'block', height: '80px' }}></div>
          {apiFailed && (
            <iframe
              key={trackId}
              title="Spotify player"
              src={'https://open.spotify.com/embed/track/' + trackId + '?utm_source=generator'}
              height="80"
              allow="autoplay; clipboard-write; encrypted-media; fullscreen; picture-in-picture"
              loading="lazy"
            ></iframe>
          )}
        </div>
      </div>
    </div>
  );
}

/* ---------- Icons (18px, inherit currentColor) ---------- */
function IconInstagram() {
  return (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><rect width="20" height="20" x="2" y="2" rx="5" ry="5"></rect><path d="M16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z"></path><line x1="17.5" x2="17.51" y1="6.5" y2="6.5"></line></svg>
  );
}
function IconSpotify() {
  return (
    <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M12 0C5.4 0 0 5.4 0 12s5.4 12 12 12 12-5.4 12-12S18.66 0 12 0zm5.521 17.34c-.24.359-.66.48-1.021.24-2.82-1.74-6.36-2.101-10.561-1.141-.418.122-.779-.179-.899-.539-.12-.421.18-.78.54-.9 4.56-1.021 8.52-.6 11.64 1.32.42.18.479.659.301 1.02zm1.44-3.3c-.301.42-.841.6-1.262.3-3.239-1.98-8.159-2.58-11.939-1.38-.479.12-1.02-.12-1.14-.6-.12-.48.12-1.021.6-1.141C9.6 9.9 15 10.561 18.72 12.84c.361.181.54.78.241 1.2zm.12-3.36C15.24 8.4 8.82 8.16 5.16 9.301c-.6.179-1.2-.181-1.38-.721-.18-.601.18-1.2.72-1.381 4.26-1.26 11.28-1.02 15.721 1.621.539.3.719 1.02.42 1.56-.299.421-1.02.599-1.56.3z"></path></svg>
  );
}
function IconYouTube() {
  return (
    <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M23.5 6.2a3 3 0 0 0-2.11-2.12C19.5 3.55 12 3.55 12 3.55s-7.5 0-9.39.53A3 3 0 0 0 .5 6.2 31.3 31.3 0 0 0 0 12a31.3 31.3 0 0 0 .5 5.8 3 3 0 0 0 2.11 2.12c1.89.53 9.39.53 9.39.53s7.5 0 9.39-.53A3 3 0 0 0 23.5 17.8 31.3 31.3 0 0 0 24 12a31.3 31.3 0 0 0-.5-5.8zM9.6 15.6V8.4l6.2 3.6z"></path></svg>
  );
}
function IconFacebook() {
  return (
    <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M24 12a12 12 0 1 0-13.88 11.85v-8.38H7.08V12h3.04V9.36c0-3 1.79-4.66 4.53-4.66 1.31 0 2.68.24 2.68.24v2.95h-1.51c-1.49 0-1.95.92-1.95 1.87V12h3.32l-.53 3.47h-2.79v8.38A12 12 0 0 0 24 12z"></path></svg>
  );
}
function IconX() {
  return (
    <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24h-6.66l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"></path></svg>
  );
}
function IconMuso() {
  return (
    <svg className="icon-muso" viewBox="0 0 48.223 36.965" fill="currentColor" aria-hidden="true"><path d="M38.2318 1.70291L25.0476 14.7151C24.527 15.2267 23.6921 15.2267 23.1746 14.7151L9.99366 1.70291C6.28254 -1.95767 0 0.673372 0 5.88779V24.0413V31.0606V34.9405C0 36.059 0.904762 36.9646 2.02222 36.9646C3.13968 36.9646 4.04445 36.059 4.04445 34.9405L4.04762 5.63994C4.04762 4.67077 4.84762 3.88591 5.82223 3.91769C6.76508 3.94629 7.49207 4.76928 7.49207 5.71302L7.48254 27.8703C7.48254 28.8141 8.20953 29.6371 9.15239 29.6657C10.127 29.6943 10.927 28.9126 10.927 27.9434V12.0618C11.054 11.2357 11.7651 10.6002 12.6286 10.6002C13.581 10.6002 14.3524 11.3723 14.3524 12.3256L14.3587 21.2292C14.3587 22.1697 15.1206 22.9324 16.0603 22.9324C17 22.9324 17.7619 22.1697 17.7619 21.2292V16.9871C17.7619 16.2753 18.6191 15.9163 19.1238 16.4151L38.2318 35.2423C41.9429 38.9029 48.2254 36.275 48.2254 31.0575V5.88779C48.2222 0.673372 41.9397 -1.95767 38.2318 1.70291ZM30.4603 19.9581C30.4603 20.6699 29.6032 21.029 29.0984 20.5301L27.5937 19.0462C27.2762 18.7316 27.2762 18.22 27.5937 17.9054L29.0984 16.4215C29.6032 15.9226 30.4603 16.2817 30.4603 16.9935V19.9581ZM37.3524 24.5911C37.3524 25.5602 36.5524 26.3451 35.5778 26.3133C34.6349 26.2847 33.908 25.4617 33.908 24.518V12.4273C33.908 11.4835 34.6349 10.6605 35.5778 10.6319C36.5524 10.6033 37.3524 11.385 37.3524 12.3542V24.5911ZM44.2413 31.3752C44.2413 32.3285 43.4699 33.1006 42.5175 33.1006C41.5651 33.1006 40.7937 32.3285 40.7937 31.3752V5.57003C40.7937 4.61676 41.5651 3.8446 42.5175 3.8446C43.4699 3.8446 44.2413 4.61676 44.2413 5.57003V31.3752Z"></path></svg>
  );
}
function IconClass101() {
  return (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><path d="M22 10 12 5 2 10l10 5 10-5Z"></path><path d="M6 12v5c0 1 2.5 2.5 6 2.5s6-1.5 6-2.5v-5"></path></svg>
  );
}

/* Reusable social cluster — leads with the brand R-roundel, then the platforms */
function SocialCluster({ className = '' }) {
  return (
    <nav className={'social-row ' + className} aria-label="Social links">
      <span className="nav-brand" role="img" aria-label="Roulsen">
        <img className="nav-brand__img nav-brand__img--paper" src="assets/icon-nav-paper.png" alt="" />
        <img className="nav-brand__img nav-brand__img--ink" src="assets/icon-nav-ink.png" alt="" />
      </span>
      <a href="https://instagram.com/roulsenmusic" target="_blank" rel="noreferrer" aria-label="Instagram"><IconInstagram></IconInstagram></a>
      <a href="https://www.youtube.com/channel/UCRqLi4LLvSH2Vta4LT-KbjQ" target="_blank" rel="noreferrer" aria-label="YouTube"><IconYouTube></IconYouTube></a>
      <a href="https://facebook.com/roulsenmusic" target="_blank" rel="noreferrer" aria-label="Facebook"><IconFacebook></IconFacebook></a>
      <a href="https://twitter.com/roulsenmusic" target="_blank" rel="noreferrer" aria-label="X"><IconX></IconX></a>
      <a href="https://open.spotify.com/playlist/1ZkX7et8bEme2zSL0J1fDY?si=7775630150994945" target="_blank" rel="noreferrer" aria-label="Spotify"><IconSpotify></IconSpotify></a>
      <a href="https://class101.net/en/products/6279f8e078540f001511d1cf" target="_blank" rel="noreferrer" aria-label="Class 101 — K-pop masterclass" title="K-pop masterclass on Class 101"><IconClass101></IconClass101></a>
      <a href="https://credits.muso.ai/artist/84a10c88-4221-49c8-a62e-cb03efca4e46" target="_blank" rel="noreferrer" aria-label="Muso.AI credits" title="Muso.AI credits"><IconMuso></IconMuso></a>
    </nav>
  );
}

/* ---------- Zones ---------- */
function BrandZone({ variant }) {
  return (
    <header className="zone zone--brand">
      <div className="brand__row">
        <h1 className="brand__name" aria-label="Roulsen">
          <img className="brand__wordmark brand__wordmark--ink" src="assets/logo-wordmark-black.png" alt="Roulsen" />
          <img className="brand__wordmark brand__wordmark--paper" src="assets/logo-wordmark-white.png" alt="" aria-hidden="true" />
        </h1>
        {variant === 'c' && (
          <div className="brand__intro">
            <p className="brand__creds">{RL_CREDS_CURATED}</p>
          </div>
        )}
      </div>
    </header>
  );
}

function WorksZone({ selected, onSelect, variant }) {
  return (
    <section className="zone zone--works works" aria-label="Selected credits">
      {variant === 'b' && (
        <p className="works__creds">{RL_CREDS_FULL}</p>
      )}
      <Eyebrow>Selected credits</Eyebrow>
      <div className="tracklist">
        {TRACKS.map((tr, i) => (
          <button
            key={tr.id}
            type="button"
            className={'track' + (tr.id === selected ? ' is-active' : '')}
            onClick={() => onSelect(tr.id)}
          >
            <span className="track__idx">{tr.id === selected ? '●' : String(i + 1).padStart(2, '0')}</span>
            <span className="track__main">
              <span className="track__title">{tr.title}</span>
              <span className="track__artist"> — {tr.artist}</span>
            </span>
            <span className="track__genre">{tr.genre}</span>
          </button>
        ))}
      </div>
      <SpotifyPlayer trackId={selected} />
    </section>
  );
}

function PhotoZone() {
  return (
    <figure className="zone zone--photo photo" style={{ margin: 0 }}>
      <div className="photo__img">
        <img src="uploads/photo-1781099683416.jpg" alt="Roulsen, portrait against a brick wall" />
      </div>
    </figure>
  );
}

function FootZone({ side }) {
  return (
    <footer className={'zone zone--foot foot foot--socials-' + side}>
      <div className="foot__brand">
        <span className="foot__motto">Follow your sound.</span>
        <span className="foot__meta"><span>© 2026 Roulsen</span></span>
      </div>
      <SocialCluster className="foot__social"></SocialCluster>
    </footer>
  );
}

/* ---------- App ---------- */
const RL_PARAMS = new URLSearchParams(location.search);
const RL_CAP = (s) => s ? s.charAt(0).toUpperCase() + s.slice(1).toLowerCase() : s;

function App() {
  const [t, setTweak] = useTweaks(RL_TWEAK_DEFAULTS);
  const [selected, setSelected] = useState(TRACKS[0].id);
  const hideChrome = RL_PARAMS.get('chrome') === 'off';

  // URL overrides let the comparison view render fixed variants (?mood=&comp=&chrome=off)
  const comp = RL_CAP(RL_PARAMS.get('comp')) || t.comp;
  const mood = RL_CAP(RL_PARAMS.get('mood')) || t.mood;
  const socials = (RL_PARAMS.get('socials') || t.socials || 'Right').toLowerCase();
  const textVariant = (RL_PARAMS.get('text') || t.textLayout || 'B').toLowerCase();
  const logoSide = (RL_PARAMS.get('logo') || t.logo || 'Left').toLowerCase();

  return (
    <main
      className={'page' + (hideChrome ? ' no-anim' : '')}
      data-screen-label="Roulsen homepage"
      data-comp={comp.toLowerCase()}
      data-mood={mood.toLowerCase()}
      data-logo={logoSide}
      style={{ '--wm-scale': t.wmScale }}
    >
      <BrandZone variant={textVariant}></BrandZone>
      <WorksZone selected={selected} onSelect={setSelected} variant={textVariant}></WorksZone>
      <PhotoZone></PhotoZone>
      <FootZone side={socials}></FootZone>
      {!hideChrome && (
        <TweaksPanel>
          <TweakSection label="Composition" />
          <TweakRadio label="Grid" value={t.comp} options={['Masthead', 'Split', 'Poster']} onChange={(v) => setTweak('comp', v)} />
          <TweakSelect label="Mood" value={t.mood} options={['Paper', 'Ink', 'Charcoal', 'Cobalt', 'Mixed']} onChange={(v) => setTweak('mood', v)} />
          <TweakRadio label="Socials" value={t.socials} options={['Left', 'Right']} onChange={(v) => setTweak('socials', v)} />
          <TweakRadio label="Top text" value={t.textLayout} options={['B', 'C']} onChange={(v) => setTweak('textLayout', v)} />
          <TweakRadio label="Logo side" value={t.logo} options={['Left', 'Right']} onChange={(v) => setTweak('logo', v)} />
          <TweakSlider label="Wordmark size" value={t.wmScale} min={0.8} max={1.4} step={0.05} onChange={(v) => setTweak('wmScale', v)} />
        </TweaksPanel>
      )}
    </main>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<App></App>);
