/* global React, window */
// Guitar Lab — SVG fretboard renderer.
//
// Renders a 6-string fretboard with N visible frets. Strings are
// horizontal lines, frets are vertical lines. The headstock end is on
// the LEFT, body end on the right — matches the way most guitar tabs
// are laid out.
//
// Props:
//   - frets:        number of frets to show (default 12)
//   - highlight:    optional { stringIndex, fret, label?, color? } to
//                   draw a colored marker. stringIndex 0 = low E
//                   (top of fretboard), 5 = high E (bottom).
//                   fret 0 = open (drawn on the nut).
//   - markers:      optional array of { stringIndex, fret, label?, color? }
//                   for multiple markers (eg. scale shapes).
//   - showNoteNames: if true, draw the note name inside each marker.
//   - onFretClick:  optional click handler, called with ({ stringIndex,
//                   fret, midi }) when the user taps a fret cell.
//   - width:        pixel width (default 560)
//
// Exposed as window.GuitarLab.ui.Fretboard.

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

  const STRING_NAMES = ['E', 'A', 'D', 'G', 'B', 'E']; // low to high
  const STRING_LABELS = ['6', '5', '4', '3', '2', '1'];
  // Inlay dots on a real guitar: 3, 5, 7, 9, 12 (double), 15, 17, 19, 21, 24 (double)
  const SINGLE_DOTS = [3, 5, 7, 9, 15, 17, 19, 21];
  const DOUBLE_DOTS = [12, 24];

  const Fretboard = function (props) {
    const frets = props.frets || 12;
    const width = props.width || 560;
    const showNames = !!props.showNoteNames;
    const padX = 36;
    const padTop = 18;
    const padBottom = 28;
    const stringSpacing = 22;
    const height = padTop + padBottom + stringSpacing * 5;
    const innerLeft = padX;
    const innerRight = width - 12;
    const fretSpacing = (innerRight - innerLeft) / (frets + 0.4); // a little extra space for the "open" cell

    function fretX(fret) {
      // fret 0 sits on the nut (innerLeft); fret N sits at innerLeft + N*fretSpacing
      return innerLeft + fret * fretSpacing;
    }

    function fretCellCenterX(fret) {
      // For dots inside a fret, place the dot in the MIDDLE of the cell
      // (between the fret line N-1 and N). Open notes (fret 0) live on
      // the nut itself.
      if (fret === 0) return innerLeft - 14;
      return innerLeft + (fret - 0.5) * fretSpacing;
    }

    function stringY(stringIndex) {
      return padTop + stringIndex * stringSpacing;
    }

    function midiFor(stringIndex, fret) {
      if (window.GuitarLab && window.GuitarLab.theory && window.GuitarLab.theory.fretToMidi) {
        return window.GuitarLab.theory.fretToMidi(stringIndex, fret);
      }
      return null;
    }

    function noteLetterFor(stringIndex, fret) {
      var m = midiFor(stringIndex, fret);
      if (m == null) return '';
      if (window.GuitarLab && window.GuitarLab.theory && window.GuitarLab.theory.midiToNoteLetter) {
        return window.GuitarLab.theory.midiToNoteLetter(m);
      }
      return '';
    }

    const allMarkers = [];
    if (props.highlight) allMarkers.push(props.highlight);
    if (props.markers && props.markers.length) {
      for (var m = 0; m < props.markers.length; m++) allMarkers.push(props.markers[m]);
    }

    return (
      <div style={{ display: 'inline-block', maxWidth: '100%', overflowX: 'auto' }}>
        <svg
          width={width}
          height={height}
          viewBox={'0 0 ' + width + ' ' + height}
          style={{ display: 'block', maxWidth: '100%', height: 'auto' }}
          aria-label="Guitar fretboard"
        >
          {/* Wood background */}
          <rect x={innerLeft} y={padTop - 4} width={innerRight - innerLeft} height={stringSpacing * 5 + 8} fill="oklch(76% 0.08 60)" />

          {/* Nut */}
          <rect x={innerLeft - 4} y={padTop - 6} width={6} height={stringSpacing * 5 + 12} fill="oklch(20% 0.02 80)" />

          {/* Fret wires */}
          {(function () {
            var out = [];
            for (var f = 1; f <= frets; f++) {
              out.push(<line key={'fret-' + f} x1={fretX(f)} y1={padTop - 2} x2={fretX(f)} y2={padTop + stringSpacing * 5 + 2} stroke="oklch(70% 0.02 80)" strokeWidth={2} />);
            }
            return out;
          })()}

          {/* Single inlay dots */}
          {SINGLE_DOTS.filter(function (d) { return d <= frets; }).map(function (d) {
            return (
              <circle key={'inlay-' + d} cx={fretCellCenterX(d)} cy={padTop + stringSpacing * 2.5} r={5} fill="oklch(94% 0.01 80)" opacity={0.7} />
            );
          })}

          {/* Double inlay dots (12th, 24th) */}
          {DOUBLE_DOTS.filter(function (d) { return d <= frets; }).map(function (d) {
            return (
              <g key={'dblinlay-' + d}>
                <circle cx={fretCellCenterX(d)} cy={padTop + stringSpacing * 1.5} r={5} fill="oklch(94% 0.01 80)" opacity={0.7} />
                <circle cx={fretCellCenterX(d)} cy={padTop + stringSpacing * 3.5} r={5} fill="oklch(94% 0.01 80)" opacity={0.7} />
              </g>
            );
          })}

          {/* Strings (low E on top per fretboard convention when laid flat */}
          {STRING_NAMES.map(function (name, i) {
            return (
              <line
                key={'string-' + i}
                x1={innerLeft - 6}
                y1={stringY(i)}
                x2={innerRight}
                y2={stringY(i)}
                stroke={i < 3 ? 'oklch(60% 0.03 80)' : 'oklch(82% 0.03 80)'}
                strokeWidth={i < 3 ? 2.2 : 1.4}
              />
            );
          })}

          {/* Fret-number labels under the fretboard (every 3rd + 12th) */}
          {(function () {
            var out = [];
            for (var f = 1; f <= frets; f++) {
              if (f === 3 || f === 5 || f === 7 || f === 9 || f === 12 || f === 15 || f === 17 || f === 19 || f === 21 || f === 24) {
                out.push(
                  <text key={'fl-' + f} x={fretCellCenterX(f)} y={padTop + stringSpacing * 5 + 18} textAnchor="middle" fontSize="10" fill="oklch(45% 0.04 265)" fontFamily="'Plus Jakarta Sans', sans-serif">{f}</text>
                );
              }
            }
            return out;
          })()}

          {/* String-number labels on the far left, just outside the nut */}
          {STRING_LABELS.map(function (lbl, i) {
            return (
              <text key={'sl-' + i} x={innerLeft - 18} y={stringY(i) + 4} textAnchor="middle" fontSize="10" fill="oklch(45% 0.04 265)" fontFamily="'Plus Jakarta Sans', sans-serif">{lbl}</text>
            );
          })}

          {/* Markers */}
          {allMarkers.map(function (mk, idx) {
            if (!mk || mk.stringIndex == null || mk.fret == null) return null;
            var cx = fretCellCenterX(mk.fret);
            var cy = stringY(mk.stringIndex);
            var color = mk.color || 'oklch(35% 0.16 265)';
            var label = mk.label != null ? mk.label : (showNames ? noteLetterFor(mk.stringIndex, mk.fret) : '');
            return (
              <g key={'mk-' + idx}>
                <circle cx={cx} cy={cy} r={11} fill={color} stroke="#fff" strokeWidth={2} />
                {label !== '' && (
                  <text x={cx} y={cy + 3.5} textAnchor="middle" fontSize="10" fontWeight="700" fill="#fff" fontFamily="'Plus Jakarta Sans', sans-serif">{label}</text>
                )}
              </g>
            );
          })}

          {/* Optional click overlay — invisible rects per fret cell, only
              rendered when an onFretClick handler is supplied. */}
          {props.onFretClick && (function () {
            var out = [];
            for (var s = 0; s < 6; s++) {
              for (var f = 0; f <= frets; f++) {
                (function (s, f) {
                  var cx, w;
                  if (f === 0) { cx = innerLeft - 14; w = 18; }
                  else { cx = innerLeft + (f - 1) * fretSpacing; w = fretSpacing; }
                  out.push(
                    <rect
                      key={'clk-' + s + '-' + f}
                      x={cx}
                      y={stringY(s) - stringSpacing / 2}
                      width={w}
                      height={stringSpacing}
                      fill="transparent"
                      style={{ cursor: 'pointer' }}
                      onClick={function () {
                        props.onFretClick({ stringIndex: s, fret: f, midi: midiFor(s, f) });
                      }}
                    />
                  );
                })(s, f);
              }
            }
            return out;
          })()}
        </svg>
      </div>
    );
  };

  window.GuitarLab.ui.Fretboard = Fretboard;
})();
