package vassistent.controller;

import vassistent.bootstrap.ApplicationContext;
import vassistent.bootstrap.ApplicationShutdownManager;
import vassistent.model.AppState;
import vassistent.ui.AppWindow;
import vassistent.ui.DashboardView;
import vassistent.ui.PixelStreamingView;
import vassistent.util.Logger;

import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Objects;

/**
 * Controls the main window lifecycle and synchronizes UI elements with app state.
 */
public class AppWindowController {

    private final ApplicationContext context;
    private final ApplicationShutdownManager shutdownManager;

    private AppWindow window;

    /**
     * Creates a controller for the main application window.
     *
     * @param context initialized application context with required services
     * @param shutdownManager shutdown coordinator shared with application bootstrap
     */
    public AppWindowController(
            ApplicationContext context,
            ApplicationShutdownManager shutdownManager
    ) {
        this.context = Objects.requireNonNull(context);
        this.shutdownManager = Objects.requireNonNull(shutdownManager);
        subscribeAppState();
    }

    /**
     * Builds the window, wires child controllers, and makes the UI visible.
     */
    public void createAndShowWindow() {

        window = new AppWindow();

        DashboardView dashboardView = window.getDashboardView();
        PixelStreamingView pixelStreamingView = window.getStreamingView();

        DashboardController dashboardController =
                new DashboardController(
                        context.getStatisticsService(),
                        dashboardView,
                        context.getAppState()
                );

        StreamingController previewController = new StreamingController(pixelStreamingView);

        window.addWindowListener(new WindowAdapter() {
            /**
             * Triggers application shutdown when the window close button is pressed.
             *
             * @param e window event provided by Swing
             */
            @Override
            public void windowClosing(WindowEvent e) {
                shutdown();
            }
        });

        window.setVisible(true);
    }

    /**
     * Runs application shutdown sequence and exits the process.
     */
    private void shutdown() {

        shutdownManager.shutdown();

        if (window != null)
            window.dispose();

        System.exit(0);
    }

    /**
     * Registers an observer to propagate {@link AppState} changes to the UI.
     */
    private void subscribeAppState() {

        Logger.info("Controller",
                "Starting AppState observer subscription");

        AppState state = context.getAppState();

        state.addListener(this::onStateChanged);

        Logger.info("Controller",
                "AppState observer registered");
    }

    /**
     * Reacts to state updates and refreshes problem level and MQTT status labels.
     *
     * @param appState latest application state snapshot
     */
    private void onStateChanged(AppState appState) {

        if (window == null) {
            Logger.warn("Controller",
                    "Window is null, UI update skipped");
            return;
        }

        SwingUtilities.invokeLater(() -> {

            window.updateProblemLevel(
                    appState.getProblemLevel().name()
            );

            window.updateMqttStatus(
                    appState.isMqttConnected()
            );

            Logger.debug("Controller",
                    "Problem level UI updated -> "
                            + appState.getProblemLevel());
        });
    }
}
