import {
  fundstelleText,
  fundstelleVorlesetext,
  type Fundstelle,
} from '../../../../shared/erklaerungen';
import type { Glossareintrag } from '../../../../shared/glossar';
import type { Sprachausgabe } from '../../hooks/useVorlesen';
import { Normstelle } from './Normstelle';
import { Vorlesetaste } from './Vorlesetaste';

export interface BegriffserklaerungProps {
  readonly eintrag: Glossareintrag;
  /**
   * Überschriftenebene.
   *
   * Beide Male 2: Im Glossar steht darüber die Überschrift der Ansicht, unter
   * einer Frage die Frage selbst. Die Angabe bleibt trotzdem eine Prop – wer
   * die Einträge später tiefer verschachtelt, soll sie mitziehen müssen und
   * nicht einen Sprung erben.
   */
  readonly ebene: 2 | 3;
  /**
   * Sprungziel der A-bis-Z-Leiste im Glossar.
   *
   * Mit Ref bekommt die Überschrift zusätzlich tabIndex -1: Der Sprung soll
   * den Fokus mitnehmen, nicht nur den Bildausschnitt – reines Rollen wäre
   * für Tastatur und Bildschirmleser wirkungslos.
   */
  readonly ueberschriftRef?: React.Ref<HTMLHeadingElement> | undefined;
  /**
   * Sprung zu einem verwandten Begriff.
   *
   * Ohne Angabe bleiben die „Siehe auch“-Verweise reiner Text — und das ist
   * unter einer Frage richtig so: Dort steht das Ziel gar nicht auf dem
   * Bildschirm, ein Knopf führte ins Leere. Im Glossar dagegen liegen alle
   * Einträge in derselben Ansicht, und wer per Tastatur oder Bildschirmleser
   * von „Erwerben“ zu „Überlassen“ wollte, musste bis 0.22.0 zurück zum
   * Filterfeld, den Begriff abtippen und die Liste neu durchgehen.
   */
  readonly onSprungZu?: (begriff: string) => void;
  /**
   * Sprachausgabe für „Begriff vorlesen“.
   *
   * Ohne Angabe entfällt die Taste. Wie bei der Erklärungstafel führt der
   * Eintrag bewusst keine eigene Instanz: Zwei Sprachausgaben auf demselben
   * Bildschirm brächen einander ab.
   */
  readonly stimme?: Sprachausgabe;
}

/** Der Eintrag als vorlesbarer Text – Fundstellen ausgeschrieben. */
function vorlesetext(eintrag: Glossareintrag): string {
  const teile: string[] = [eintrag.begriff, eintrag.kurz];
  if (eintrag.text !== undefined) {
    teile.push(eintrag.text);
  }
  if (eintrag.fundstellen.length > 0) {
    teile.push(
      `Fundstelle: ${eintrag.fundstellen.map((f) => fundstelleVorlesetext(f)).join('; ')}.`,
    );
  }
  if (eintrag.ohneFundstelleGrund !== undefined) {
    teile.push(eintrag.ohneFundstelleGrund);
  }
  return teile.join('\n');
}

/**
 * Fundstellen einer Bestimmung – seit 0.22.0 zum Aufklappen.
 *
 * Vorher eine Zeile mit Zitaten, durch Kommas getrennt. Als Liste, weil jedes
 * Zitat jetzt ein eigenes Bedienelement ist: Ein Aufklapper mitten im
 * Fließtext wäre für Tastatur und Bildschirmleser eine Reihe namenloser
 * Sprungmarken. Gerade hier zählt es – wer einen Begriff nachschlägt, sucht
 * meist genau die Legaldefinition.
 */
function Fundstellen({ fundstellen }: { readonly fundstellen: readonly Fundstelle[] }) {
  return (
    <ul className="begriff__fundstellen">
      {fundstellen.map((fundstelle) => (
        <li key={fundstelleText(fundstelle)}>
          <Normstelle fundstelle={fundstelle} />
        </li>
      ))}
    </ul>
  );
}

/**
 * Ein Glossareintrag.
 *
 * Dieselbe Darstellung im Glossar und unter einer Frage – nur die
 * Überschriftenebene unterscheidet sich, damit die Hierarchie an beiden
 * Stellen sprungfrei bleibt.
 *
 * Die Kurzfassung steht immer da und trägt für sich allein. Wer nur sie
 * liest, muss die Frage verstehen können; alles Weitere ist Zugabe.
 */
export function Begriffserklaerung({
  eintrag,
  ebene,
  ueberschriftRef,
  onSprungZu,
  stimme,
}: BegriffserklaerungProps): React.JSX.Element {
  const titel = (
    <>
      {eintrag.begriff}
      {eintrag.art === 'abkuerzung' ? <span className="begriff__art"> (Abkürzung)</span> : null}
    </>
  );
  const tabIndex = ueberschriftRef === undefined ? undefined : -1;

  return (
    <div className="begriff">
      {ebene === 2 ? (
        <h2 className="begriff__wort" ref={ueberschriftRef} tabIndex={tabIndex}>
          {titel}
        </h2>
      ) : (
        <h3 className="begriff__wort" ref={ueberschriftRef} tabIndex={tabIndex}>
          {titel}
        </h3>
      )}

      <p className="begriff__kurz">{eintrag.kurz}</p>

      {eintrag.text === undefined ? null : <p className="begriff__text">{eintrag.text}</p>}

      {eintrag.fundstellen.length > 0 ? <Fundstellen fundstellen={eintrag.fundstellen} /> : null}

      {eintrag.ohneFundstelleGrund === undefined ? null : (
        <p className="begriff__ohnefundstelle">{eintrag.ohneFundstelleGrund}</p>
      )}

      {eintrag.siehe !== undefined && eintrag.siehe.length > 0 ? (
        <p className="begriff__siehe">
          Siehe auch:{' '}
          {eintrag.siehe.map((verwandt, i) => (
            <span key={verwandt}>
              {i > 0 ? ', ' : ''}
              {onSprungZu === undefined ? (
                verwandt
              ) : (
                <button
                  type="button"
                  className="begriff__sprung"
                  onClick={() => {
                    onSprungZu(verwandt);
                  }}
                >
                  {verwandt}
                </button>
              )}
            </span>
          ))}
        </p>
      ) : null}

      {stimme?.moeglich === true ? (
        <div className="begriff__stimme">
          <Vorlesetaste
            laeuft={stimme.laeuft}
            angehalten={stimme.angehalten}
            gegenstand="Begriff"
            onSprich={() => {
              stimme.sprich(vorlesetext(eintrag));
            }}
            onAbbrechen={stimme.abbrechen}
            onAnhalten={stimme.anhalten}
            onFortsetzen={stimme.fortsetzen}
          />
        </div>
      ) : null}
    </div>
  );
}
