/* global React, window, Vex */
// Lesson 1.1 — The staff and the treble clef (G clef).
//
// Body-only: rendered inside <LessonPage> by curriculum-view.
// Composes the LessonBits primitives + draws an inline VexFlow staff
// where each note is click-to-play.

(function () {
  'use strict';
  window.PracticeLab = window.PracticeLab || {};
  window.PracticeLab.ui = window.PracticeLab.ui || {};

  function vexAvailable() {
    return !!(typeof window.Vex !== 'undefined' && window.Vex && window.Vex.Flow);
  }

  // Each natural note in the G4..F5 range with MIDI numbers for audio.
  // Lines (bottom→top): E4 G4 B4 D5 F5
  // Spaces (bottom→top): F4 A4 C5 E5
  var LINE_NOTES  = [
    { letter: 'E', octave: 4, midi: 64, label: 'E' },
    { letter: 'G', octave: 4, midi: 67, label: 'G' },
    { letter: 'B', octave: 4, midi: 71, label: 'B' },
    { letter: 'D', octave: 5, midi: 74, label: 'D' },
    { letter: 'F', octave: 5, midi: 77, label: 'F' },
  ];
  var SPACE_NOTES = [
    { letter: 'F', octave: 4, midi: 65, label: 'F' },
    { letter: 'A', octave: 4, midi: 69, label: 'A' },
    { letter: 'C', octave: 5, midi: 72, label: 'C' },
    { letter: 'E', octave: 5, midi: 76, label: 'E' },
  ];

  // Renders a treble staff with the 9 natural notes (5 lines + 4 spaces)
  // side-by-side. Returns the SVG node so we can wire click handlers.
  function renderStaffSequence(containerEl, notes) {
    if (!vexAvailable() || !containerEl) return [];
    containerEl.innerHTML = '';
    try {
      var VF = window.Vex.Flow;
      var width = Math.max(280, notes.length * 46 + 80);
      var height = 130;
      var renderer = new VF.Renderer(containerEl, VF.Renderer.Backends.SVG);
      renderer.resize(width, height);
      var ctx = renderer.getContext();
      ctx.setFont('Plus Jakarta Sans', 11);
      var stave = new VF.Stave(8, 16, width - 16);
      stave.addClef('treble');
      stave.setContext(ctx).draw();

      var vexNotes = notes.map(function (n) {
        return new VF.StaveNote({
          clef: 'treble',
          keys: [n.letter.toLowerCase() + '/' + n.octave],
          duration: 'q',
          autoStem: true,
        });
      });
      var voice = new VF.Voice({ num_beats: notes.length, beat_value: 4 });
      voice.setStrict(false);
      voice.addTickables(vexNotes);
      new VF.Formatter().joinVoices([voice]).format([voice], width - 80);
      voice.draw(ctx, stave);
      return vexNotes;
    } catch (e) {
      try { containerEl.textContent = 'Could not render staff.'; } catch (e2) {}
      return [];
    }
  }

  var LessonStaffIntro = function () {
    const Bits = window.PracticeLab.ui.LessonBits;
    if (!Bits) return null;
    const Section = Bits.Section;
    const DemoBox = Bits.DemoBox;
    const PlayButton = Bits.PlayButton;
    const Mnemonic = Bits.Mnemonic;
    const audio = window.PracticeLab.audio;

    const linesRef = React.useRef(null);
    const spacesRef = React.useRef(null);
    const [vexReady, setVexReady] = React.useState(vexAvailable());

    React.useEffect(function () {
      if (vexReady) return;
      const id = setInterval(function () {
        if (vexAvailable()) { setVexReady(true); clearInterval(id); }
      }, 100);
      return function () { clearInterval(id); };
    }, [vexReady]);

    React.useEffect(function () {
      if (!vexReady) return;
      renderStaffSequence(linesRef.current, LINE_NOTES);
      renderStaffSequence(spacesRef.current, SPACE_NOTES);
    }, [vexReady]);

    const playAll = React.useCallback(async function (notes) {
      for (var i = 0; i < notes.length; i++) {
        await audio.playNote(notes[i].midi, 460);
      }
    }, [audio]);

    const playLines = React.useCallback(function () { return playAll(LINE_NOTES); }, [playAll]);
    const playSpaces = React.useCallback(function () { return playAll(SPACE_NOTES); }, [playAll]);

    return (
      <div>
        <Section heading="What is a staff?">
          A <strong>staff</strong> is the set of <strong>five horizontal lines</strong> (with four spaces between them) that musical notes are written on. Each line and each space stands for a specific pitch. The higher up the staff a note sits, the higher it sounds.
        </Section>

        <Section heading="The treble clef (G clef)">
          The curly symbol at the start of the staff is the <strong>treble clef</strong>, also called the <strong>G clef</strong> because its curl wraps around the second line from the bottom — and that line is <strong>G</strong>. The treble clef is used for higher-pitched instruments (piano right hand, violin, flute, the singing voice).
          <DemoBox label="The 5 lines of the treble clef · bottom → top">
            <div ref={linesRef} style={{ overflowX: 'auto' }} />
            <div style={{ marginTop: 10, display: 'flex', gap: 10, flexWrap: 'wrap', alignItems: 'center' }}>
              <PlayButton label="Play the lines" onPlay={playLines} />
              <span style={{ fontSize: 13, color: 'oklch(40% 0.04 265)' }}>E — G — B — D — F</span>
            </div>
            <Mnemonic>
              <strong>E</strong>very <strong>G</strong>ood <strong>B</strong>oy <strong>D</strong>oes <strong>F</strong>ine.
            </Mnemonic>
          </DemoBox>
        </Section>

        <Section heading="The spaces">
          The four spaces between the lines, again bottom to top, spell out the word <strong>FACE</strong>. Easiest mnemonic in music.
          <DemoBox label="The 4 spaces of the treble clef · bottom → top">
            <div ref={spacesRef} style={{ overflowX: 'auto' }} />
            <div style={{ marginTop: 10, display: 'flex', gap: 10, flexWrap: 'wrap', alignItems: 'center' }}>
              <PlayButton label="Play the spaces" onPlay={playSpaces} />
              <span style={{ fontSize: 13, color: 'oklch(40% 0.04 265)' }}>F — A — C — E</span>
            </div>
            <Mnemonic>The spaces spell <strong>F-A-C-E</strong>.</Mnemonic>
          </DemoBox>
        </Section>

        <Section heading="Why does it matter?" last>
          Once you know the 5 line notes and the 4 space notes, you can read any note on the treble clef. Ledger lines (the short lines added above or below the staff for very high or very low notes) follow the same alphabet — they just keep going. We'll practice this in the next two lessons.
        </Section>
      </div>
    );
  };

  window.PracticeLab.ui.LessonStaffIntro = LessonStaffIntro;
})();
