// app.jsx — root, hierarchical routing (Timeline → Era → Composer → Work), tweaks

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "density": "regular",
  "theme": "warm-dark",
  "fontPair": "cormorant-eb"
}/*EDITMODE-END*/;

function App() {
  // Hierarchical route stack
  // levels: ['timeline'] | ['timeline','era',id] | ['timeline','era',id,'composer',cid] | ['timeline','era',id,'composer',cid,'work',widx]
  //   Era can be omitted (jump direct from timeline to composer):
  //   ['timeline','composer',cid] etc.
  const [route, setRoute] = React.useState(['timeline']);
  const [eraFilter, setEraFilter] = React.useState(null);
  const [countryFilter, setCountryFilter] = React.useState(null);
  const [rankLimit, setRankLimit] = React.useState(10);
  const [tlFocusId, setTlFocusId] = React.useState(null); // timeline highlighted composer (persists across navigation)
  const [locked, setLocked] = React.useState(false);

  const [t, _setTweak] = useTweaks(TWEAK_DEFAULTS);
  const setTweak = (k, v) => { if (!locked) _setTweak(k, v); };

  // ─── Browser history sync (back / forward buttons) ──────────
  // The route stack is JSON-serializable, so we mirror it into history.state.
  const skipPush = React.useRef(false); // set when a route change came from popstate
  const isFirstHistory = React.useRef(true);

  React.useEffect(() => {
    const onPop = (e) => {
      skipPush.current = true;
      setRoute(e.state && e.state.route ? e.state.route : ['timeline']);
    };
    window.addEventListener('popstate', onPop);
    return () => window.removeEventListener('popstate', onPop);
  }, []);

  React.useEffect(() => {
    if (skipPush.current) { skipPush.current = false; return; }
    if (isFirstHistory.current) {
      isFirstHistory.current = false;
      window.history.replaceState({ route }, '');
    } else {
      window.history.pushState({ route }, '');
    }
  }, [route]);

  // Theme + font effects
  React.useEffect(() => {
    document.body.classList.remove('theme-warm-dark', 'theme-light', 'theme-cool');
    document.body.classList.add('theme-' + t.theme);
  }, [t.theme]);

  React.useEffect(() => {
    const root = document.documentElement;
    if (t.fontPair === 'libre-caslon') {
      root.style.setProperty('--f-display', '"Libre Caslon Text", "Cormorant Garamond", Georgia, serif');
      root.style.setProperty('--f-body',    '"Libre Caslon Text", "EB Garamond", Georgia, serif');
    } else if (t.fontPair === 'playfair') {
      root.style.setProperty('--f-display', '"Playfair Display", "Cormorant Garamond", Georgia, serif');
      root.style.setProperty('--f-body',    '"EB Garamond", Georgia, serif');
    } else {
      root.style.setProperty('--f-display', '"Cormorant Garamond", Georgia, serif');
      root.style.setProperty('--f-body',    '"EB Garamond", Georgia, serif');
    }
  }, [t.fontPair]);

  // ─── Routing helpers ─────────────────────────────────────────
  const goHome = () => setRoute(['timeline']);
  const goEra = (eraId) => setRoute(['timeline', 'era', eraId]);
  const goComposer = (composerId) => {
    const c = window.COMPOSERS.find(x => x.id === composerId);
    if (!c) return;
    setTlFocusId(composerId); // keep the timeline highlight on the composer being opened
    setRoute(['timeline', 'era', c.era, 'composer', composerId]);
  };
  // workKey is a slug of the work title (see SLUGIFY in data-driven lookups).
  const goWork = (composerId, workKey) => {
    const c = window.COMPOSERS.find(x => x.id === composerId);
    if (!c) return;
    setTlFocusId(composerId);
    setRoute(['timeline', 'era', c.era, 'composer', composerId, 'work', String(workKey)]);
  };
  // Click crumb at position
  const goToCrumb = (idx) => setRoute(route.slice(0, idx + 1));

  // Parse current view
  const last = route[route.length - 1];
  const isWork = route.includes('work');
  const isComposer = route.includes('composer') && !isWork;
  const isEra = route.includes('era') && !route.includes('composer');
  const isTimeline = route.length === 1;

  const currentEraId      = route[route.indexOf('era') + 1];
  const currentComposerId = route[route.indexOf('composer') + 1];
  const currentWorkKey    = route[route.indexOf('work') + 1];

  // ─── Crumb segments ─────────────────────────────────────────
  // Build segments alongside their route-end indices so clicking pops correctly.
  const crumbs = [];
  crumbs.push({ label: 'Timeline', i: 0 }); // route[0]='timeline'

  if (currentComposerId) {
    const c = window.COMPOSERS.find(x => x.id === currentComposerId);
    if (c) {
      const surname = c.name.split(' ').slice(-1)[0];
      crumbs.push({ label: surname, i: route.indexOf('composer') + 1 });
    }
  }
  if (currentWorkKey !== undefined) {
    const w = window.workTitleFromKey(currentComposerId, currentWorkKey);
    const short = w && w.length > 36 ? w.slice(0, 34) + '…' : w;
    if (short) crumbs.push({ label: short, i: route.indexOf('work') + 1 });
  }

  return (
    <div className="app">
      <header className="hd">
        <div className="brand" onClick={goHome}>
          <div className="brand-mark">Op<em>vs</em></div>
          <div className="brand-sub">A Classical Catalogue · 50 Composers</div>
        </div>
        <div style={{ marginLeft: 'auto' }} className="hd-count">
          {isTimeline ? '1567 — 1976' : `${crumbs.length} levels`}
        </div>
      </header>

      {!isTimeline && (
        <nav className="crumb">
          {crumbs.map((cr, i) => {
            const isLast = i === crumbs.length - 1;
            return (
              <React.Fragment key={i}>
                {i > 0 && <span className="sep">›</span>}
                {isLast ? (
                  <span className={'here' + (cr.era ? ' era-tag' : '')} style={cr.era ? { '--era-accent': `var(--era-${cr.era})`, color: 'var(--era-accent)' } : null}>
                    {cr.label}
                  </span>
                ) : (
                  <button onClick={() => goToCrumb(cr.i)} className={cr.era ? 'era-tag' : ''} style={cr.era ? { '--era-accent': `var(--era-${cr.era})`, color: 'var(--era-accent)' } : null}>
                    {cr.label}
                  </button>
                )}
              </React.Fragment>
            );
          })}
        </nav>
      )}

      {isTimeline && (
        <TimelineView
          density={t.density}
          eraFilter={eraFilter}
          setEraFilter={setEraFilter}
          countryFilter={countryFilter}
          setCountryFilter={setCountryFilter}
          rankLimit={rankLimit}
          setRankLimit={setRankLimit}
          focusId={tlFocusId}
          setFocusId={setTlFocusId}
          onSelectComposer={goComposer}
          onSelectEra={goEra}
        />
      )}
      {isEra && (
        <EraView
          eraId={currentEraId}
          onSelectComposer={goComposer}
          onSelectEra={goEra}
        />
      )}
      {isComposer && (
        <DetailView
          composerId={currentComposerId}
          onBack={() => goToCrumb(route.indexOf('era') + 1 || 0)}
          onSelectComposer={goComposer}
          onSelectWork={goWork}
        />
      )}
      {isWork && (
        <WorkView
          composerId={currentComposerId}
          workKey={currentWorkKey}
          onSelectComposer={goComposer}
          onSelectWork={goWork}
        />
      )}

      <div className={'twk-panel-host' + (locked ? ' is-locked-wrap' : '')}>
        <TweaksPanel title="Tweaks">
          <div className={'twk-locked-zone' + (locked ? ' is-locked' : '')}
               style={locked ? { opacity: 0.4, pointerEvents: 'none' } : null}>
            <TweakSection label="Timeline" />
            <TweakRadio
              label="Density"
              value={t.density}
              options={['tight', 'regular', 'loose']}
              onChange={(v) => setTweak('density', v)}
            />

            <TweakSection label="Theme" />
            <TweakRadio
              label="Palette"
              value={t.theme}
              options={[
                { value: 'warm-dark', label: 'Warm Dark' },
                { value: 'cool',      label: 'Cool Dark' },
                { value: 'light',     label: 'Parchment' },
              ]}
              onChange={(v) => setTweak('theme', v)}
            />
            <TweakSelect
              label="Typeface"
              value={t.fontPair}
              options={[
                { value: 'cormorant-eb',  label: 'Cormorant + EB Garamond' },
                { value: 'libre-caslon',  label: 'Libre Caslon' },
                { value: 'playfair',      label: 'Playfair + EB Garamond' },
              ]}
              onChange={(v) => setTweak('fontPair', v)}
            />
          </div>

          <div className={'twk-lock-row' + (locked ? ' is-locked' : '')}>
            <span>{locked ? '🔒 Frozen' : '🔓 Live'}</span>
            <button onClick={() => setLocked(!locked)}>
              {locked ? 'Unfreeze' : 'Freeze tweaks'}
            </button>
          </div>
        </TweaksPanel>
      </div>
    </div>
  );
}

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