/**
 * Das Unterstützungsangebot – eine Bitte, kein Handel.
 *
 * ## Eine Adresse, und leer heißt lautlos
 *
 * {@link UNTERSTUETZUNG_URL} ist die **einzige** Stelle, an der die Adresse
 * steht. Ist sie leer, lässt die Anwendung das Angebot vollständig weg: keine
 * Überschrift, kein Knopf, keine leere Zeile. Ein Knopf, der ins Nichts führt,
 * wäre schlimmer als kein Knopf – er sagt zu, dass es dort weitergeht. Wer den
 * Dienst wechselt oder das Angebot zurücknehmen will, ändert diese eine
 * Zeile.
 *
 * Gewählt ist Ko-fi. Die Form bleibt geprüft: `https:`, keine Zugangsdaten
 * in der Adresse, sonst gilt sie als nicht gesetzt. Ein Wechsel des Dienstes
 * ist auch später eine Zeile – die Adresse steht nur hier, und
 * `main/sicherheit.ts` liest sie von dieser Stelle.
 *
 * ## Warum es nichts freischaltet
 *
 * Die Anwendung soll in den Microsoft Store. Dessen Richtlinien lassen bei
 * kostenlosen Anwendungen einen Verweis auf eine Spendenseite zu, verlangen
 * aber, dass dahinter **keine digitalen Güter und keine Funktionen verkauft**
 * werden. Deshalb schaltet dieser Knopf nichts frei: keinen Pro-Modus, keine
 * Zusatzfunktion, keine Werbefreiheit – es gibt hier keine Werbung, die man
 * abstellen könnte. Wer nichts gibt, hat dieselbe Anwendung wie alle anderen.
 * Das ist nicht bloß eine Store-Auflage, sondern der Grund, warum das Angebot
 * überhaupt vertretbar ist: Eine Prüfungsvorbereitung, die einen Teil ihres
 * Stoffs hinter eine Zahlung legt, benachteiligt genau die Prüflinge, die
 * ohnehin am wenigsten übrig haben.
 *
 * ## Warum es sich nicht von selbst meldet
 *
 * `docs/entscheidung-motivation.md` hält fest, warum es hier keinen Streak
 * und keinen Tagesziel-Ring gibt: Diese Anwendung erzeugt keinen Druck, um
 * Verhalten zu erzeugen. Für eine Spendenbitte gilt dasselbe, nur schärfer –
 * sie hat ein Eigeninteresse. Deshalb gibt es **kein** Einblenden nach der
 * zehnten Frage, keinen Zähler „schon 300 Fragen gelernt“, keine Erinnerung,
 * kein zweites Fragen. Das Angebot steht an einer Stelle, an der ohnehin
 * nachsieht, wer wissen will, woher diese Anwendung kommt und was sie kostet:
 * in „Über diese Software“, unterhalb der Lizenzangaben – und ausdrücklich
 * **nicht** vor dem Rückmeldeweg, der dort zuoberst steht. Wer die Ansicht
 * öffnet, weil er auf eine Barriere gestoßen ist, soll nicht zuerst um Geld
 * gebeten werden.
 *
 * ## Warum die Anwendung dabei keine Verbindung öffnet
 *
 * „Diese Anwendung läuft vollständig offline“ ist eine Zusage, die in „Über
 * diese Software“ ausdrücklich steht. Der Knopf bricht sie nicht: Er lädt
 * nichts, prüft nichts nach und meldet nichts – er übergibt die Adresse an
 * den Hauptprozess, und der reicht sie mit `shell.openExternal` an den
 * Standardbrowser weiter. Das Fenster verlässt dabei niemand unangekündigt:
 * {@link UNTERSTUETZUNG_KNOPF} sagt es in der Beschriftung (WCAG 3.2).
 *
 * Was über die Brücke geht, wird trotzdem geprüft – `main/sicherheit.ts`
 * vergleicht die gewünschte Adresse mit genau dieser Konstanten und öffnet
 * sonst nichts. Eine Adresse mitschicken zu dürfen heißt sonst, auch eine
 * andere mitschicken zu dürfen.
 */

/**
 * Adresse der Unterstützungsseite. **Leer = kein Angebot.**
 *
 * Muss mit `https://` beginnen; alles andere behandelt
 * {@link unterstuetzungsziel} wie „nicht gesetzt“. Wird zugleich von
 * `main/sicherheit.ts` als einzige zulässige Zieladresse gelesen – eine
 * Änderung hier verschiebt also auch, was die Brücke überhaupt öffnen darf.
 */
export const UNTERSTUETZUNG_URL = 'https://ko-fi.com/olafwillerding';

/** Überschrift des Blocks in „Über diese Software“. */
export const UNTERSTUETZUNG_TITEL = 'Diese Arbeit unterstützen';

/**
 * Beschriftung des Knopfes.
 *
 * Sie sagt beides: was geschieht und **dass das Fenster verlassen wird**. Ein
 * Verweis, der unangekündigt den Browser startet, ist genau die Überraschung,
 * die WCAG 3.2 vermeiden will. Die sichtbare Beschriftung ist zugleich der
 * zugängliche Name – es gibt kein `aria-label`, das daneben laufen könnte
 * (WCAG 2.5.3).
 */
export const UNTERSTUETZUNG_KNOPF = 'Unterstützungsseite im Browser öffnen';

/**
 * Die geprüfte Adresse, oder `null`, wenn keine gesetzt ist.
 *
 * Eine reine Funktion mit ausdrücklichem Eingabewert, damit beide Seiten
 * dasselbe rechnen und beide Fälle prüfbar sind – auch der, den es heute noch
 * nicht gibt.
 *
 * Abgelehnt wird alles, was kein `https:` ist. `http:` fiele in der
 * Auslieferung an unbekannte Empfänger auf; `mailto:`, `javascript:` und
 * Ähnliches haben an dieser Stelle nichts verloren. Zugangsdaten in der
 * Adresse (`https://name:wort@…`) gelten ebenfalls als Fehleintrag: Sie
 * gehören in keinen Verweis, den jemand im Browser sieht.
 *
 * Ein Vertipper führt damit zu demselben Ergebnis wie ein leeres Feld – das
 * Angebot entfällt. Eine Fehlermeldung an dieser Stelle wäre für den
 * Lernenden ein Mangel der Anwendung, obwohl es einer des Eintrags ist.
 */
export function unterstuetzungsziel(url: string): string | null {
  const adresse = url.trim();
  if (adresse.length === 0) {
    return null;
  }

  let geprueft: URL;
  try {
    geprueft = new URL(adresse);
  } catch {
    return null;
  }

  if (geprueft.protocol !== 'https:') {
    return null;
  }

  /* Hier stand zusätzlich eine Prüfung auf einen leeren Rechnernamen. Sie ist
     entfernt, weil sie nicht auslösen kann: Für die besonderen Schemata –
     `https:` gehört dazu – verlangt der URL-Standard einen Rechnernamen.
     Nachgemessen mit Node: `https://` wirft `ERR_INVALID_URL` (dann greift der
     `catch` oben), und `https:///pfad` liefert `pfad` als Rechnernamen. Eine
     Bedingung, die nie zutrifft, behauptet einen Schutz, den es nicht gibt –
     dieselbe Überlegung wie bei den stummen Wachen in `sicherheit.test.ts`. */

  if (geprueft.username.length > 0 || geprueft.password.length > 0) {
    return null;
  }

  /* Zurück kommt die eingetragene Schreibweise und nicht `geprueft.href`:
     Angezeigt und geöffnet wird so dieselbe Zeichenkette, und der Vergleich
     im Hauptprozess trifft genau das, was auf dem Bildschirm stand. */
  return adresse;
}
