/**
 * Einstiegspunkt des Main-Prozesses.
 */

import { app, BrowserWindow, dialog } from 'electron';

import type { CspModus } from '../shared/csp';
import { energieUeberwachen, energieVergessen } from './energie';
import { hauptfensterErstellen } from './fenster';
import { hilfsmittelBeobachten, ipcAbmelden, ipcRegistrieren } from './ipc';
import { menueEinrichten } from './menue';
import { fehlerZeile, protokollEinrichten, protokollieren } from './protokoll';
import { sicherheitEinrichten } from './sicherheit';
import { datenbankStatus } from './datenbank';

const MODUS: CspModus = app.isPackaged ? 'production' : 'development';

app.setName('Waffensachkunde Lernsoftware');

/*
  Die Taskleisten-Identität unter Windows.

  Ohne sie trägt das laufende Fenster eine andere Kennung als die
  Verknüpfung, die das Installationsprogramm anlegt: Windows gruppiert das
  Programm dann nicht zuverlässig mit dem angehefteten Symbol, und „An
  Taskleiste anheften“ kann ein zweites, doppeltes Symbol erzeugen. Die
  Kennung muss dieselbe sein wie `appId` in `electron-builder.yml` – deshalb
  steht sie hier wörtlich und nicht abgeleitet: Zwei Stellen, aber nur eine
  davon liest der Bau, und ein Auseinanderlaufen fiele erst am fertigen
  Paket auf. `tests/paketstand.test.ts` vergleicht beide.

  Nur außerhalb des Store-Pakets: Dort vergibt Windows die Identität aus dem
  AppX-Manifest, und ein eigener Aufruf überschriebe sie mit einer falschen.
*/
if (process.platform === 'win32' && !process.windowsStore) {
  app.setAppUserModelId('de.willerding.waffensachkunde');
}

// Nur eine Instanz: eine zweite Instanz fokussiert das bestehende Fenster.
if (!app.requestSingleInstanceLock()) {
  app.quit();
} else {
  app.on('second-instance', () => {
    const [fenster] = BrowserWindow.getAllWindows();
    if (fenster) {
      if (fenster.isMinimized()) {
        fenster.restore();
      }
      fenster.focus();
    }
  });

  /*
    Was sonst niemand sähe, kommt in eine Datei.

    Fehler des Hauptprozesses landeten bis 0.22.0 ausschließlich in der
    Konsole – die im gepackten Programm niemand sieht. Wer „es stürzt manchmal
    ab“ melden wollte, hatte nichts in der Hand. Die Datei geht nirgendwohin;
    sie liegt neben dem Lernstand und wird von Hand mitgeschickt oder gar
    nicht. Einzelheiten und die Reinigungsregel stehen in `protokoll.ts`.

    Vor `whenReady`, damit auch ein Fehler beim Hochfahren noch hineinkommt.
  */
  protokollEinrichten(app.getPath('userData'));

  process.on('uncaughtException', (fehler: unknown) => {
    console.error('[fehler] Unbehandelte Ausnahme:', fehler);
    protokollieren('fehler', `Unbehandelte Ausnahme: ${fehlerZeile(fehler)}`);
  });

  process.on('unhandledRejection', (grund: unknown) => {
    console.error('[fehler] Unbehandeltes Versprechen:', grund);
    protokollieren('fehler', `Unbehandeltes Versprechen: ${fehlerZeile(grund)}`);
  });

  app.whenReady().then(
    () => {
      sicherheitEinrichten(MODUS);
      menueEinrichten();
      ipcRegistrieren();
      hilfsmittelBeobachten();
      energieUeberwachen();

      // Rauchtest für better-sqlite3 einmal beim Start protokollieren.
      const status = datenbankStatus();
      console.info(`[datenbank] ${status.meldung}`);

      hauptfensterErstellen();

      app.on('activate', () => {
        if (BrowserWindow.getAllWindows().length === 0) {
          hauptfensterErstellen();
        }
      });
    },
    (fehler: unknown) => {
      /*
        Nicht wortlos beenden.

        Vorher stand der Grund nur in der Konsole – die niemand sieht, der
        das Programm über sein Symbol startet. Ein Fenster, das aufgeht und
        sofort wieder verschwindet, ist keine Fehlermeldung. `showErrorBox`
        geht auch ohne fertige Anwendung und wird vom Screenreader gelesen.
      */
      const grund = fehler instanceof Error ? fehler.message : String(fehler);
      console.error('[start] Anwendung konnte nicht initialisiert werden:', fehler);
      protokollieren('start', `Anwendung konnte nicht starten: ${fehlerZeile(fehler)}`);
      dialog.showErrorBox(
        'Waffensachkunde – Lernsoftware',
        [
          'Das Programm konnte nicht gestartet werden.',
          grund,
          'Ihr Lernstand ist davon nicht betroffen; er liegt als Datei auf Ihrer Festplatte.',
        ].join('\n\n'),
      );
      app.quit();
    },
  );

  app.on('window-all-closed', () => {
    if (process.platform !== 'darwin') {
      app.quit();
    }
  });

  app.on('will-quit', () => {
    energieVergessen();
    ipcAbmelden();
  });
}
