(function (ns) {
  'use strict';

  const WATCH_OPTIONS = Object.freeze({
    enableHighAccuracy: true,
    timeout: 20000,
    maximumAge: 5000
  });
  let watchId = null;

  function geolocation() {
    return globalThis.navigator?.geolocation;
  }

  function normalize(position) {
    return {
      lat: position.coords.latitude,
      lon: position.coords.longitude,
      accuracy: position.coords.accuracy,
      altitude: position.coords.altitude,
      heading: position.coords.heading,
      speed: position.coords.speed,
      timestamp: position.timestamp
    };
  }

  function unsupportedError() {
    return new Error('Dieses Gerät unterstützt keine Geolokalisierung.');
  }

  ns.Geo = {
    current() {
      return new Promise((resolve, reject) => {
        const service = geolocation();
        if (!service) {
          reject(unsupportedError());
          return;
        }

        service.getCurrentPosition(
          position => resolve(normalize(position)),
          reject,
          {
            ...WATCH_OPTIONS,
            timeout: ns.Config.geolocationTimeoutMs,
            maximumAge: 30000
          }
        );
      });
    },

    start(callback, onError) {
      this.stop();
      const service = geolocation();
      if (!service) {
        onError?.(unsupportedError());
        return;
      }

      watchId = service.watchPosition(
        position => callback(normalize(position)),
        onError,
        WATCH_OPTIONS
      );
    },

    stop() {
      const service = geolocation();
      if (watchId != null) service?.clearWatch(watchId);
      watchId = null;
    }
  };
}(globalThis.Wegwichtel));
