/* global React, window */
// Piano Lab — SVG keyboard renderer.
//
// Renders a clickable piano keyboard between two MIDI numbers (loMidi /
// hiMidi). Both ends must land on a white key (the rendering math
// indexes by white-key position). White keys render as a row; black
// keys overlay on the boundary between the white keys.
//
// Props:
//   loMidi, hiMidi      — inclusive MIDI range, both white keys
//   onKey(midi)         — optional click handler. If omitted, keyboard
//                         is non-interactive.
//   highlight           — single MIDI to outline in yellow
//   highlightMidis      — array of MIDIs to outline (alternative to
//                         single `highlight`)
//   correctMidi         — green outline (post-answer feedback)
//   wrongMidi           — red outline (post-answer feedback)
//   labels              — optional map { midi: 'C', ... } drawn at the
//                         bottom of the white keys
//   showAllLabels       — if true, label every white key with its letter
//   width               — px width of the SVG; defaults responsive to
//                         the white-key count
//   disabled            — disable all clicks
//
// Exposed at window.PianoLab.ui.Keyboard.

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

  const Keyboard = function (props) {
    const loMidi = props.loMidi != null ? props.loMidi : 60; // C4
    const hiMidi = props.hiMidi != null ? props.hiMidi : 71; // B4
    const onKey = props.onKey || null;
    const disabled = !!props.disabled;
    const labels = props.labels || {};
    const showAllLabels = !!props.showAllLabels;
    const correctMidi = props.correctMidi;
    const wrongMidi   = props.wrongMidi;
    const highlightArr = props.highlightMidis || (props.highlight != null ? [props.highlight] : []);

    // Build the list of white and black keys in the range.
    const whiteKeys = [];
    const blackKeys = [];
    for (let m = loMidi; m <= hiMidi; m++) {
      const info = window.PianoLab.theory.midiToName(m);
      if (info.isBlack) blackKeys.push({ midi: m, info: info });
      else              whiteKeys.push({ midi: m, info: info });
    }

    // Layout — white keys are equal-width across the SVG, black keys
    // straddle the boundary between two whites at 60% width.
    const whiteW = 38;
    const whiteH = 150;
    const blackW = Math.round(whiteW * 0.62);
    const blackH = Math.round(whiteH * 0.62);
    const svgW = whiteKeys.length * whiteW;
    const svgH = whiteH + 20;

    function whiteIndex(midi) {
      for (let i = 0; i < whiteKeys.length; i++) {
        if (whiteKeys[i].midi === midi) return i;
      }
      return -1;
    }

    // For a black key at MIDI m, return its x. Black keys are positioned
    // so they sit between the two adjacent whites. The black key's
    // associated "lower" white key is m-1 (since black keys always
    // follow C, D, F, G, A in semitone terms).
    function blackX(midi) {
      const i = whiteIndex(midi - 1);
      if (i === -1) return null;
      return (i + 1) * whiteW - blackW / 2;
    }

    function keyOutlineColor(midi, isBlack) {
      if (correctMidi != null && midi === correctMidi) return 'oklch(55% 0.18 145)'; // green
      if (wrongMidi   != null && midi === wrongMidi)   return 'oklch(55% 0.18 25)';  // red
      if (highlightArr.indexOf(midi) !== -1) return 'oklch(60% 0.18 80)';            // amber
      return isBlack ? 'oklch(15% 0.02 265)' : 'oklch(75% 0.012 265)';
    }

    function keyFill(midi, isBlack) {
      if (correctMidi != null && midi === correctMidi) return 'oklch(94% 0.07 145)';
      if (wrongMidi   != null && midi === wrongMidi)   return 'oklch(95% 0.07 25)';
      if (highlightArr.indexOf(midi) !== -1)           return isBlack ? 'oklch(60% 0.16 80)' : 'oklch(96% 0.08 80)';
      return isBlack ? 'oklch(15% 0.02 265)' : '#fff';
    }

    function handleClick(midi) {
      if (disabled || !onKey) return;
      onKey(midi);
    }

    // We give every key a tooltip so screen readers and curious mouse
    // users can read the note name.
    function tooltip(midi) {
      return window.PianoLab.theory.midiToLabel(midi);
    }

    return (
      <div style={{ display: 'inline-block', maxWidth: '100%' }}>
        <svg
          viewBox={'0 0 ' + svgW + ' ' + svgH}
          width="100%"
          style={{ maxWidth: Math.min(640, svgW), display: 'block', touchAction: 'manipulation' }}
          role="img"
          aria-label="Piano keyboard"
        >
          {/* White keys first so black keys overlay them */}
          {whiteKeys.map(function (k, i) {
            const x = i * whiteW;
            const stroke = keyOutlineColor(k.midi, false);
            const fill = keyFill(k.midi, false);
            const isHighlight = highlightArr.indexOf(k.midi) !== -1
              || correctMidi === k.midi
              || wrongMidi === k.midi;
            return (
              <g key={'w' + k.midi}>
                <rect
                  x={x + 1}
                  y={1}
                  width={whiteW - 2}
                  height={whiteH - 2}
                  fill={fill}
                  stroke={stroke}
                  strokeWidth={isHighlight ? 3 : 1}
                  rx={4}
                  style={{
                    cursor: (onKey && !disabled) ? 'pointer' : 'default',
                  }}
                  onClick={function () { handleClick(k.midi); }}
                  aria-label={tooltip(k.midi)}
                />
                {(labels[k.midi] || (showAllLabels && k.info.letter)) && (
                  <text
                    x={x + whiteW / 2}
                    y={whiteH - 10}
                    textAnchor="middle"
                    fontSize="13"
                    fontWeight="700"
                    fontFamily="'Plus Jakarta Sans', sans-serif"
                    fill={isHighlight ? 'oklch(25% 0.10 265)' : 'oklch(40% 0.04 265)'}
                    pointerEvents="none"
                  >{labels[k.midi] || k.info.letter}</text>
                )}
                {/* Middle-C marker — a tiny "C4" tag below the key */}
                {k.midi === 60 && !labels[60] && !showAllLabels && (
                  <text
                    x={x + whiteW / 2}
                    y={svgH - 5}
                    textAnchor="middle"
                    fontSize="9"
                    fontWeight="700"
                    fontFamily="'Plus Jakarta Sans', sans-serif"
                    fill="oklch(45% 0.13 80)"
                  >C4</text>
                )}
              </g>
            );
          })}

          {/* Black keys overlay */}
          {blackKeys.map(function (k) {
            const x = blackX(k.midi);
            if (x == null) return null;
            const stroke = keyOutlineColor(k.midi, true);
            const fill = keyFill(k.midi, true);
            const isHighlight = highlightArr.indexOf(k.midi) !== -1
              || correctMidi === k.midi
              || wrongMidi === k.midi;
            return (
              <g key={'b' + k.midi}>
                <rect
                  x={x}
                  y={1}
                  width={blackW}
                  height={blackH}
                  fill={fill}
                  stroke={stroke}
                  strokeWidth={isHighlight ? 3 : 1}
                  rx={3}
                  style={{
                    cursor: (onKey && !disabled) ? 'pointer' : 'default',
                  }}
                  onClick={function () { handleClick(k.midi); }}
                  aria-label={tooltip(k.midi)}
                />
                {labels[k.midi] && (
                  <text
                    x={x + blackW / 2}
                    y={blackH - 8}
                    textAnchor="middle"
                    fontSize="11"
                    fontWeight="700"
                    fontFamily="'Plus Jakarta Sans', sans-serif"
                    fill={isHighlight ? '#000' : '#fff'}
                    pointerEvents="none"
                  >{labels[k.midi]}</text>
                )}
              </g>
            );
          })}
        </svg>
      </div>
    );
  };

  window.PianoLab.ui.Keyboard = Keyboard;
})();
