// sc-user-location.js
import { showToast,mylog } from './sc-utilities.js';

/**
 * Eine Klasse zur Verwaltung des Benutzerstandorts.
 * 
 * die redundanz zw. isTrackingActive und getUserPosition sollte geklärt und aufgelöst werden
 * 
 */
export class ScUserLocation {   
    /**
     * @private {boolean} _isTrackingActive - Status, ob das Tracking aktiv ist.
     * @private {number|null} _watchId - ID des watchPosition-callbacks, falls aktiv.
     * @private {L.Map|null} _map - Die Leaflet-Karte, auf der der Standortmarker angezeigt werden soll.
     * @private {L.Marker|null} _userMarker - Der Leaflet-Marker für den aktuellen Benutzerstandort.
     * @private {object|null} _lastKnownPosition - Die zuletzt erfolgreich abgerufene GeolocationPosition.
     * @private {L.divIcon} _userIcon - Das Icon für den Benutzer-Marker.
     * @private {Array<function(boolean)>} _trackingStateChangeListeners - Liste der Callbacks für Statusänderungen.
     * @private {string} _locationPermissionStatus - Aktueller Geolocation-Berechtigungsstatus.
     */
    constructor(map) {
        if (!map || typeof map.setView !== 'function') {
            console.error("ScUserLocation: Ein gültiges Leaflet-Kartenobjekt ist erforderlich.");
            showToast('Fehler: Kartenobjekt nicht verfügbar.', 'Fehler');
            return;
        }

        this._map = map;
        this._userMarker = null;
        this._isManuallyDeactivatedByUser = false;
        this._trackingActive = false;
        this._watchId = null;
        this._lastKnownPosition = null;
        this._trackingStateChangeListeners = [];
        this._locationPermissionStatus = 'prompt';

        this._userIcon = L.divIcon({
            className: 'user-location-emoji',
            html: '📍',
            iconSize: [20, 20],
            iconAnchor: [10, 10]
        });

        mylog("ScUserLocation: Instanziiert.");
    }

    onTrackingStateChange(callback) {
        if (typeof callback === 'function') {
            this._trackingStateChangeListeners.push(callback);
        }
    }

    _notifyTrackingStateChange(isActive) {
        this._trackingStateChangeListeners.forEach(callback => {
            try {
                callback(isActive);
            } catch (e) {
                console.error("Fehler beim Ausführen des TrackingStateChangeListeners:", e);
            }
        });
        mylog(`ScUserLocation: Tracking-Status geändert zu: ${isActive ? 'aktiv' : 'inaktiv'}`);
    }

    _setTrackingActive(active) {
        if (this._trackingActive !== active) {
            this._trackingActive = active;
            this._notifyTrackingStateChange(active);
        }
    }

    isTrackingActive() {
        return this._trackingActive && !this._isManuallyDeactivatedByUser;
    }

    isManuallyDeactivated() {
        return this._isManuallyDeactivatedByUser;
    }

    getUserPosition() {
        if (this._lastKnownPosition) {
            mylog("ScUserLocation: getUserPosition aufgerufen. Letzte bekannte Position:", this._lastKnownPosition.coords.latitude, this._lastKnownPosition.coords.longitude);
            return [this._lastKnownPosition.coords.latitude, this._lastKnownPosition.coords.longitude];
        }
        mylog("ScUserLocation: getUserPosition aufgerufen. Keine bekannte Position vorhanden.");
        return null;
    }

    centerMapOnUser(zoom = 18) {
        if (this._map) {
            if (this.isTrackingActive() && this._lastKnownPosition) {
                const latLng = [this._lastKnownPosition.coords.latitude, this._lastKnownPosition.coords.longitude];
                if (latLng[0] !== 0 || latLng[1] !== 0) {
                    this._map.setView(latLng, zoom);
                    mylog(`ScUserLocation: Karte auf Benutzerposition zentriert (Zoom: ${zoom}).`);
                    return;
                }
            }
            mylog("ScUserLocation: Tracking nicht aktiv oder keine gültige Position bekannt. Zeige Hinweis.");
            showToast('Standort-Tracking ist inaktiv oder Position wird noch abgerufen. Bitte warten.', 'Info');
        } else {
            console.warn("ScUserLocation: Karte nicht verfügbar.");
        }
    }

    /**
     * Startet den Geolocation-Watch-Loop.
     * @private
     * @param {GeolocationPosition} position - Die initial abgerufene Position.
     */
    _startWatchPosition(position) {
        if (this._trackingActive) return;

        this._setTrackingActive(true);
        this._updateUserMarker(position);
        this._map.setView([position.coords.latitude, position.coords.longitude], 16);   // vorher 16

        this._watchId = navigator.geolocation.watchPosition(
            (pos) => this._updateUserMarker(pos),
            (err) => this._handleGeolocationError(err),
            { enableHighAccuracy: true, timeout: 3000, maximumAge: 0 } // bei 2000 gibtes ein warning am pc
        );
        mylog("ScUserLocation: watchPosition-Tracking gestartet.");
    }

    _stopTracking() {
        if (this._watchId !== null) {
            navigator.geolocation.clearWatch(this._watchId);
            this._watchId = null;
            this._setTrackingActive(false);

            if (this._userMarker) {
                this._map.removeLayer(this._userMarker);
                this._userMarker = null;
            }
         this._lastKnownPosition = null;

        mylog("ScUserLocation: Standort-Tracking beendet und Position geleert.");
        }
    }

    _updateUserMarker(position) {
        if (!position || !position.coords) {
            console.error("FEHLER: _updateUserMarker: Ungültiges Position-Objekt erhalten.");
            return;
        }

        this._lastKnownPosition = position;
        const latlng = [position.coords.latitude, position.coords.longitude];

        if (latlng[0] === 0 && latlng[1] === 0 || isNaN(latlng[0]) || isNaN(latlng[1])) {
            console.warn("ScUserLocation: Ungültige Koordinaten erhalten. Update ignoriert.");
            return;
        }

        if (this._userMarker) {
            this._userMarker.setLatLng(latlng);
        } else {
            const userIcon = L.divIcon({
                className: 'user-location-emoji',
                html: '📍',
                iconSize: [20, 20],
                iconAnchor: [10, 10]
            });
            this._userMarker = L.marker(latlng, { icon: userIcon, zIndexOffset: 1000 }).addTo(this._map);
            this._userMarker.on('click', () => {
                this.centerMapOnUser(this._map.getZoom());
            });
        }
    }

    _handleGeolocationError(error) {
        let message = '';
        let type = 'Fehler';
        switch (error.code) {
            case GeolocationPositionError.PERMISSION_DENIED:
                message = 'Standortzugriff verweigert.';
                this._stopTracking();
                break;
            case GeolocationPositionError.POSITION_UNAVAILABLE:
                message = 'Standortinformationen sind nicht verfügbar.';
                this._stopTracking();
                break;
            case GeolocationPositionError.TIMEOUT:
                if (this._trackingActive) {
                    message = 'Standort konnte nicht aktualisiert werden.';
                    type = 'Warnung';
                } else {
                    message = 'Zeitüberschreitung beim Abrufen des Standorts.';
                    this._stopTracking();
                }
                break;
            default:
                message = `Ein unbekannter Fehler ist aufgetreten: ${error.message || 'Details unbekannt'}`;
                this._stopTracking();
                break;
        }
        showToast(message, type);

            // WICHTIG: Füge diese Zeile hinzu, um die Ausführung fortzusetzen
    if (typeof this._resolvePromise === 'function') {
        this._resolvePromise(false);
        this._resolvePromise = null;
    }
    }
    
    /**
     * Öffentliche Methode, die den Prozess des Abrufs der Berechtigung und des Starts des Trackings kapselt.
     *
     * @returns {Promise<boolean>} Ein Promise, das mit `true` aufgelöst wird, wenn das Tracking gestartet wurde,
     * und mit `false`, wenn es fehlschlägt oder die Berechtigung verweigert wird.
     */
async startTrackingAndHandlePermission() {
    mylog("ScUserLocation: starte Tracking-Prozess...");
    this._isManuallyDeactivatedByUser = false;

    if (!navigator.geolocation) {
        showToast('Geolocation wird von Ihrem Browser nicht unterstützt.', 'Fehler');
        this._setTrackingActive(false);
        return false;
    }

    try {
        // Schritt 1: Geolocation-Berechtigungsstatus prüfen
        const permissionStatus = await navigator.permissions.query({ name: 'geolocation' });

        if (permissionStatus.state === 'denied') {
            // Schritt 2: Wenn verweigert, sofort Fehlermeldung anzeigen und abbrechen
            this._handleGeolocationError({
                code: 1, // entspricht GeolocationPositionError.PERMISSION_DENIED
                message: "Standortzugriff wurde dauerhaft verweigert."
            });
            return false;
        }

        // Schritt 3: Wenn Berechtigung erteilt oder noch nicht abgefragt, normale Abfrage starten
        return new Promise(resolve => {
            navigator.geolocation.getCurrentPosition(
                (position) => {
                    mylog("Geolocation: Initialer Abruf erfolgreich.");
                    this._startWatchPosition(position);
                    resolve(true); 
                },
                (error) => {
                    this._handleGeolocationError(error);
                    resolve(false); 
                },
                {
                    enableHighAccuracy: true,
                    timeout: 5000,
                    maximumAge: 0
                }
            );
        });

    } catch (e) {
        console.error("Fehler beim Abfragen des Berechtigungsstatus:", e);
        showToast('Fehler bei der Berechtigungsabfrage.', 'Fehler');
        return false;
    }
}

    stopLocationTracking() {
        mylog("ScUserLocation: stopLocationTracking aufgerufen.");
        this._isManuallyDeactivatedByUser = true;
        this._stopTracking();
    }
}
