package de.gecheckt.pdf.umbenenner.adapter.in.gui;

import java.awt.AWTException;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.TrayIcon;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;

import javax.imageio.ImageIO;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import javafx.application.Platform;
import javafx.stage.Stage;

/**
 * Verwaltet das Windows System-Tray-Icon für den PDF-Umbenenner.
 * <p>
 * Wird das Hauptfenster geschlossen, bleibt die Anwendung im Hintergrund aktiv und zeigt
 * ein Tray-Icon in der Windows-Taskleiste. Über das Kontextmenü kann das Fenster wieder
 * geöffnet oder die Anwendung vollständig beendet werden.
 * <p>
 * Alle Stage-Operationen werden auf dem JavaFX Application Thread ausgeführt, da AWT-Events
 * auf dem AWT Event Dispatch Thread eintreffen.
 */
class SystemTrayManager {

    private static final Logger LOG = LogManager.getLogger(SystemTrayManager.class);

    private final Stage stage;
    private TrayIcon trayIcon;
    private boolean installed;

    /**
     * Erstellt einen neuen {@code SystemTrayManager} für die angegebene Stage.
     *
     * @param stage das primäre Fenster; darf nicht {@code null} sein
     */
    SystemTrayManager(Stage stage) {
        this.stage = stage;
    }

    /**
     * Installiert das System-Tray-Icon.
     * <p>
     * Schlägt die Installation fehl (System-Tray nicht unterstützt oder Icon-Bild nicht ladbar),
     * wird {@code false} zurückgegeben und kein Tray-Icon angezeigt.
     *
     * @return {@code true} wenn das Icon erfolgreich installiert wurde, sonst {@code false}
     */
    boolean install() {
        if (!SystemTray.isSupported()) {
            LOG.warn("GUI: System-Tray wird auf diesem System nicht unterstützt.");
            return false;
        }
        BufferedImage image = loadTrayImage();
        if (image == null) {
            return false;
        }
        PopupMenu menu = buildContextMenu();
        trayIcon = new TrayIcon(image, "PDF-Umbenenner", menu);
        trayIcon.setImageAutoSize(true);
        // Doppelklick öffnet das Fenster
        trayIcon.addActionListener(e -> Platform.runLater(this::showWindow));
        try {
            SystemTray.getSystemTray().add(trayIcon);
            installed = true;
            LOG.info("GUI: System-Tray-Icon erfolgreich installiert.");
            return true;
        } catch (AWTException e) {
            LOG.warn("GUI: System-Tray-Icon konnte nicht installiert werden: {}", e.getMessage(), e);
            return false;
        }
    }

    /**
     * Entfernt das Tray-Icon aus dem System-Tray.
     * Ist kein Icon installiert, wird der Aufruf ignoriert.
     */
    void remove() {
        if (installed && trayIcon != null) {
            SystemTray.getSystemTray().remove(trayIcon);
            installed = false;
            LOG.info("GUI: System-Tray-Icon entfernt.");
        }
    }

    /**
     * Gibt an, ob das Tray-Icon aktiv installiert ist.
     *
     * @return {@code true} wenn das Icon im System-Tray sichtbar ist
     */
    boolean isInstalled() {
        return installed;
    }

    private BufferedImage loadTrayImage() {
        try (InputStream stream = getClass().getResourceAsStream("/icons/Icon16.png")) {
            if (stream == null) {
                LOG.warn("GUI: Tray-Icon-Ressource '/icons/Icon16.png' nicht gefunden.");
                return null;
            }
            return ImageIO.read(stream);
        } catch (IOException e) {
            LOG.warn("GUI: Tray-Icon-Bild konnte nicht geladen werden: {}", e.getMessage(), e);
            return null;
        }
    }

    private PopupMenu buildContextMenu() {
        PopupMenu menu = new PopupMenu();

        MenuItem openItem = new MenuItem("Öffnen");
        openItem.addActionListener(e -> Platform.runLater(this::showWindow));

        MenuItem exitItem = new MenuItem("Beenden");
        exitItem.addActionListener(e -> {
            remove();
            Platform.exit();
            System.exit(0);
        });

        menu.add(openItem);
        menu.addSeparator();
        menu.add(exitItem);
        return menu;
    }

    private void showWindow() {
        stage.show();
        stage.toFront();
    }
}
