/**
 * AppShellCoordinator.js
 * Verwaltet die Zustände und Events der primären AppShellUI.
 * * Verantwortlichkeiten:
 * - Event-Weiterleitung von UI-Elementen (Settings, Search-Trigger, Admin-Trigger)
 * - Steuerung des UI-Sichtbarkeitszustands (Preloader, Map, Controls)
 */
import { mylog } from "./sc-utilities";
import { setupAdminModeDetector } from './sc-admin-mode.js';

/**
 * Aktualisiert das Suchfeld mit der übergebenen Adresse oder setzt den Standardtext.
 * WICHTIG: Diese Funktion wurde hierher verschoben, da sie direkt die AppShell-UI manipuliert.
 * @param {string|null} address - Die Adresse, die angezeigt werden soll.
 */
export function updateSearchFieldWithAddress(address = null) {
    const searchAddressPlaceholder = document.getElementById('search-address-placeholder-text');
    const DEFAULT_ADDRESS_TEXT = "Adresse oder Name ";
    if (searchAddressPlaceholder) {
        if (address && address !== DEFAULT_ADDRESS_TEXT) {
            searchAddressPlaceholder.textContent = address;
            // Setzt den Text auf fett, wenn eine Adresse angezeigt wird.
            searchAddressPlaceholder.style.fontWeight = 'bold';
        } else {
            searchAddressPlaceholder.textContent = DEFAULT_ADDRESS_TEXT;
            // Setzt den Text auf normal, wenn der Standardtext angezeigt wird.
            searchAddressPlaceholder.style.fontWeight = 'normal';
        }
    }
}

export class AppShellCoordinator {
    
    // ZENTRALE PRIVATE FELDER (Abhängigkeiten und Zustand)
    /** @type {AppShellUI} */
    #appShellUI; 
    /** @type {Map | null} */
    #mapInstance = null; 

    // PRIVATE FELDER FÜR CALLBACKS
    #onSettingsClickedCallbacks = [];
    #onSearchTriggeredCallbacks = [];
    #onLocationPermissionGrantedCallbacks = [];
    #adminTriggerCallbacks = [];

    /**
     * @param {AppShellUI} appShellUI - Die Instanz der AppShellUI.
     */
    constructor(appShellUI) {
        this.#appShellUI = appShellUI; 
        this.#setupEventListeners(); 
    }

    /**
     * Registriert die Event-Listener für die Kernelemente (Search, Settings, Grant-Button).
     * @private
     */
    #setupEventListeners() {
        if (this.#appShellUI.settingsIconElement) { 
            this.#appShellUI.settingsIconElement.addEventListener('click', () => {
                mylog("AppShellCO: Settings-Icon geklickt.");
                this.#onSettingsClickedCallbacks.forEach(callback => callback());
            });
        }
        
       if (this.#appShellUI.searchTriggerElement) { 
            this.#appShellUI.searchTriggerElement.addEventListener('click', (event) => { 
                event.stopPropagation();
                
                mylog("AppShellCO: Search-Trigger geklickt.");
                this.#onSearchTriggeredCallbacks.forEach(callback => callback());
            });
        }
        
        // Button zur Freigabe des Standorts
        const grantButton = document.getElementById('grant-location-button');
        if (grantButton) {
            grantButton.addEventListener('click', async () => {
                mylog("AppShellCO: Standort-Freigabe erteilt.");
                this.#appShellUI.locationPermissionOverlay.classList.add('hidden');
                
                // Signal an die Hauptanwendung senden
                this.#onLocationPermissionGrantedCallbacks.forEach(callback => callback());
            });
        }
    }
    
    // ===============================================
    // ÖFFENTLICHE API (Event-Registrierung)
    // ===============================================
    
    /**
     * Registriert einen Callback für das Klicken auf das Settings-Icon.
     * @param {function(): void} callback 
     */
    onSettingsClicked(callback) {
        this.#onSettingsClickedCallbacks.push(callback);
    }
    
    /**
     * Registriert einen Callback für das Klicken auf den Such-Trigger.
     * @param {function(): void} callback 
     */
    onSearchTriggered(callback) {
        this.#onSearchTriggeredCallbacks.push(callback);
    }

    /**
     * Registriert einen Callback, wenn der Benutzer auf "Stolpersteine anzeigen" klickt.
     * @param {function(): Promise<void>} callback 
     */
    onLocationPermissionGranted(callback) {
        this.#onLocationPermissionGrantedCallbacks.push(callback);
    }
    
    /**
     * Registriert einen Callback für den Admin-Modus-Trigger (für den ApplicationCoordinator).
     * @param {function(): void} callback
     */
    onAdminTriggered(callback) {
        this.#adminTriggerCallbacks.push(callback);
    }
    
    // ===============================================
    // ÖFFENTLICHE API (Initialisierung des Admin-Triggers)
    // ===============================================

    /**
     * Stellt den Admin-Modus-Erkenner bereit und abonniert das Tap-Event.
     * Diese Methode muss vom ApplicationCoordinator aufgerufen werden.
     * @public
     */
    setupAdminModeDetection() {
        const adminTriggerElement = document.getElementById('tz');

        if (adminTriggerElement) {
            setupAdminModeDetector(adminTriggerElement, () => {
                mylog("AppShellCoord: Tap-Sequenz erfolgreich erkannt, löse abstraktes Event aus.");
                this.#adminTriggerCallbacks.forEach(callback => callback());
            });
        } else {
            console.warn("AppShellCoord: Admin-Trigger-Element 'tz' nicht gefunden.");
        }
    }


    // ===============================================
    // ÖFFENTLICHE API (Zustandssteuerung)
    // ===============================================

    /**
     * Setzt die Map-Instanz, nachdem sie von der Map-Initialisierung erstellt wurde.
     * @param {Map} map 
     */
    setMapInstance(map) {
        this.#mapInstance = map;
    }
    
    /**
     * Zeigt die Hauptkarte und die Steuerelemente an und blendet den Preloader aus.
     */
    showMapAndControls() {
        if (this.#appShellUI.mapElement) { 
            this.#appShellUI.mapElement.classList.remove('hidden');
        }
        if (this.#appShellUI.settingsIconElement) { 
            this.#appShellUI.settingsIconElement.classList.remove('hidden');
        }
        if (this.#appShellUI.searchTriggerElement) { 
            this.#appShellUI.searchTriggerElement.classList.remove('hidden');
        }
        
        const bgContainer = document.getElementById('background-image-container');
        if (bgContainer) {
            bgContainer.classList.add('fade-out');
        }

        if (this.#mapInstance && this.#mapInstance.invalidateSize) {
            this.#mapInstance.invalidateSize(); 
        }
        mylog("AppShellCO: Karte und Steuerelemente sind jetzt sichtbar.");
    }
    
    /**
     * Macht die Ladeanzeige (Spinner) sichtbar.
     */
    showLoadingSpinner() {
        document.getElementById('loading-spinner-content')?.classList.remove('fade-out');
        document.getElementById('loading-spinner-content')?.classList.remove('hidden');
        mylog("AppShellCO: Haupt-Spinner wurde sichtbar gemacht.");
    }
    
    /**
     * Blendet die Ladeanzeige (Spinner) aus.
     */
    hideLoadingSpinner() {
         document.getElementById('loading-spinner-content')?.classList.add('fade-out');
    }
    
    /**
     * Zeigt den Standort-Berechtigungs-Overlay an.
     */
    showLocationPermissionOverlay() {
         document.getElementById('location-permission-overlay')?.classList.remove('hidden');
    }
    
    /**
     * Aktualisiert den Text der Ladeanzeige.
     * @param {string} text 
     */
    updateLoadingText(text) {
        const loadingTextElement = document.getElementById('estimated-time-display');
        if (loadingTextElement) {
            loadingTextElement.textContent = text || "Lade Daten...";
        }
    }
    
    /**
     * Startet den Ladevorgang des Hintergrundbildes.
     * WICHTIG: Diese Funktion blockiert NICHT die weitere Initialisierung des ApplicationCoordinators.
     * @returns {Promise<void>} - Löst auf, sobald das Bild geladen oder der Versuch beendet ist.
     */
    async  preloadBackground() {
        const BG_IMAGE_URL = 'StolperCleanBackground.jpg?v=' + Date.now();
        const bgContainer = document.getElementById('background-image-container');

        // 1. Hintergrundbild laden
        try {
            const response = await fetch(BG_IMAGE_URL, { cache: 'no-cache' });
            if (!response.ok) throw new Error(`HTTP-Fehler ${response.status} beim Laden des Hintergrundbildes.`);
            const blob = await response.blob();
            const imageUrl = URL.createObjectURL(blob);
            
            // 2. Hintergrundbild setzen und Container sichtbar machen
            const imgElement = new Image();
            imgElement.src = imageUrl;
            imgElement.alt = 'Hintergrundbild';
            imgElement.style.width = '100%';
            imgElement.style.height = '100%';
            imgElement.style.objectFit = 'cover';
            if(bgContainer) {
                 bgContainer.appendChild(imgElement);
                 bgContainer.style.opacity = 1; // Hintergrund wird sichtbar
            }
            mylog("AppShellCO: Hintergrundbild erfolgreich geladen (im Hintergrund).");

        } catch (error) {
            console.error("FEHLER beim Laden des Hintergrundbildes (Laufzeitfehler ignoriert):", error);
            if(bgContainer) bgContainer.style.opacity = 1;
        }
    }
}