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

import java.util.Optional;

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

import javafx.application.Application;

/**
 * Entry point for the JavaFX desktop GUI inbound adapter.
 * <p>
 * This class is the designated entry point through which Bootstrap launches the
 * graphical user interface. It acts as the inbound adapter boundary: it receives
 * control from Bootstrap and delegates to the JavaFX application lifecycle via
 * {@link PdfUmbenennerGuiApplication}.
 * <p>
 * Responsibilities of this adapter:
 * <ul>
 *   <li>Accept the GUI start signal from Bootstrap</li>
 *   <li>Launch the JavaFX application lifecycle via {@link Application#launch}</li>
 *   <li>Ensure that all UI operations are dispatched on the JavaFX Application Thread</li>
 *   <li>Ensure that all blocking operations (file I/O, network, database) run on
 *       background worker threads and never block the UI thread</li>
 * </ul>
 * <p>
 * This class must not be instantiated or called by any module other than Bootstrap.
 * Domain, application, CLI adapter, and outbound adapter modules must remain
 * free of dependencies on this class and on JavaFX in general.
 * <p>
 * The actual JavaFX {@link Application} subclass ({@link PdfUmbenennerGuiApplication})
 * and all GUI view components are separate classes within this package. This entry
 * point class coordinates the hand-off from the Bootstrap layer into the JavaFX lifecycle.
 *
 * <h2>Current scope</h2>
 * <p>
 * The adapter launches the editor shell with the unloaded start state, an optional startup
 * notice, and a file-loading callback supplied by Bootstrap. File I/O and save behavior remain
 * outside the current GUI step.
 */
public class GuiAdapter {

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

    /**
     * Creates a new {@code GuiAdapter} instance.
     * <p>
     * Bootstrap is responsible for constructing this adapter and invoking
     * {@link #start()} at the appropriate point in the application lifecycle.
     * No JavaFX initialization is performed during construction; the JavaFX
     * runtime is only started when {@link #start()} is called.
     */
    public GuiAdapter() {
        // Bootstrap constructs this adapter before deciding to start the GUI.
        // JavaFX initialization is deferred to start() to ensure the headless
        // path is never burdened with premature JavaFX class loading.
    }

    /**
     * Starts the JavaFX GUI and blocks until the user closes the window.
     * <p>
     * When {@code startupNotice} is present, the notice string is forwarded to
     * {@link PdfUmbenennerGuiApplication} so it can be displayed to the user on startup.
     * This is used when Bootstrap has detected a problem with the supplied
     * {@code --config} path (e.g. the file was not found) and wishes to inform the
     * user before the normal GUI shell is shown.
     * <p>
     * This method delegates to {@link Application#launch(Class, String...)} with
     * {@link PdfUmbenennerGuiApplication} as the application class. The call blocks
     * until the JavaFX application terminates (typically when the user closes the
     * main window).
     * <p>
     * This method must be called from a thread that is permitted to run a JavaFX
     * application (typically the main thread). It must not be called on the JavaFX
     * Application Thread itself, and must not be called more than once per JVM process.
     * <p>
     * Upon normal GUI shutdown (user closes the window), this method returns
     * normally. Bootstrap is responsible for deriving the appropriate exit code
     * from the return.
     *
     * @param startupNotice an optional message to display to the user in the GUI on startup;
     *                      when empty, no notice is shown; must not be {@code null}
     * @throws IllegalStateException if the JavaFX runtime cannot be initialised
     *                               or if the platform is not supported
     */
    public void start(Optional<String> startupNotice) {
        start(GuiStartupContext.blank(startupNotice));
    }

    /**
     * Starts the JavaFX GUI with the supplied startup context.
     *
     * @param startupContext startup data for the GUI; must not be {@code null}
     */
    public void start(GuiStartupContext startupContext) {
        LOG.info("GUI-Adapter: JavaFX-Start wird eingeleitet.");
        GuiStartupContextHolder.install(startupContext);
        try {
            Application.launch(PdfUmbenennerGuiApplication.class);
        } finally {
            GuiStartupContextHolder.clear();
            LOG.info("GUI-Adapter: JavaFX-Anwendung wurde beendet.");
        }
    }
}
