<%*
/*
  ----------------------------------------------------------------------
  TEMPLATER SCRIPT: Koordinaten aus Clipboard + Reverse-Geocoding (OSM)
  ----------------------------------------------------------------------

  Zweck
  1. Koordinaten aus dem Clipboard lesen (z. B. aus Obsidian Maps)
  2. Über Nominatim (OpenStreetMap) Reverse-Geocoding machen
  3. Frontmatter der aktuell geöffneten Notiz aktualisieren:
     - coordinates: [lat, lon]  (als Liste von Strings)
     - adresse:     display_name (lesbare Gesamtadresse)
     - ort:         Name des konkreten Ortes/POI (z. B. "St.Ulrich")
     - ort_type:    OSM-Typ des Objekts (z. B. "kindergarten")
     - stadt:       Stadt / Town / Village usw.
     - region:      Bundesland/Kanton/State (Fallback: County)
     - land:        Land

  Hinweise
  - Nominatim ist ein freier Dienst mit Fair-Use. Für manuelle Nutzung ok.
  - Ohne Internet klappt nur das Setzen der Koordinaten, Adresse bleibt leer.
  - Das Script überschreibt vorhandene Felder, wenn es neue Werte hat.
*/


// ------------------------------------------------------------
// 1) Clipboard lesen und Koordinaten extrahieren
// ------------------------------------------------------------

// Clipboard als String lesen (await ist bei einigen Templater-Versionen nötig)
const clip = '' + await tp.system.clipboard();

// Aus dem Clipboard alle Zahlen extrahieren (robust gegen Formate wie:
// "49.21, 8.70", "Lat: 49.21 Lng: 8.70", "(49.21 8.70)" usw.)
const nums = clip.match(/-?\d+(?:\.\d+)?/g) ?? [];

// Wir nehmen die ersten zwei gefundenen Zahlen als lat/lon
const lat = nums[0];
const lon = nums[1];

// Wenn wir nicht mindestens zwei Zahlen haben, brechen wir ab
if (!lat || !lon) {
  new Notice("Keine gültigen Koordinaten im Clipboard gefunden");
  return;
}


// ------------------------------------------------------------
// 2) Reverse Geocoding über Nominatim (OpenStreetMap)
// ------------------------------------------------------------

// Zielvariablen, die wir später ins Frontmatter schreiben
let adresse = "";
let ort = "";
let ort_type = "";
let stadt = "";
let region = "";
let land = "";

try {
  // zoom=18: eher detailreich (POIs/Gebäude) statt nur Stadt/Gemeinde
  // addressdetails=1: liefert den address-Block
  // jsonv2: gut strukturiert
  const url =
    `https://nominatim.openstreetmap.org/reverse?format=jsonv2` +
    `&lat=${encodeURIComponent(lat)}` +
    `&lon=${encodeURIComponent(lon)}` +
    `&zoom=18` +
    `&addressdetails=1`;

  // Obsidian stellt requestUrl global bereit
  const res = await requestUrl({
    url,
    method: "GET",
    headers: {
      // Fair-Use: eigener User-Agent ist wichtig
      "User-Agent": "Obsidian-Templater"
    }
  });

  const data = res.json;
  const a = data?.address ?? {};

  // 2a) Ganze Adresse als lesbarer String
  // display_name ist oft lang, aber praktisch als "volle" Adresse
  if (typeof data?.display_name === "string") {
    adresse = data.display_name;
  }

  // 2b) ort_type: Der "type" Wert aus Nominatim
  // Beispiele: kindergarten, restaurant, wine_cellar, railway_station, ...
  // Das ist NICHT die Kategorie (category), sondern das spezifischere Feld.
  if (typeof data?.type === "string") {
    ort_type = data.type;
  }

  // 2c) Ort/POI Namen extrahieren
  //
  // Problem: Nominatim ist nicht in allen Antworten gleich.
  // Manchmal steht der Name in data.name, manchmal in address.<addresstype>.
  //
  // addresstype beschreibt, welches Feld in address den "Hauptnamen" enthält.
  // In deinem Beispiel:
  //   addresstype = "amenity"
  //   address.amenity = "St.Ulrich"
  //
  // Daher nutzen wir eine robuste Reihenfolge:
  // 1) data.name (wenn vorhanden)
  // 2) address[data.addresstype] (falls addresstype vorhanden)
  // 3) bekannte Felder als Fallback (amenity/tourism/shop/...)
  const addresstype = data?.addresstype;

  ort =
    (typeof data?.name === "string" ? data.name : "") ||
    (addresstype && typeof a?.[addresstype] === "string" ? a[addresstype] : "") ||
    (typeof a?.amenity === "string" ? a.amenity : "") ||
    (typeof a?.tourism === "string" ? a.tourism : "") ||
    (typeof a?.shop === "string" ? a.shop : "") ||
    (typeof a?.leisure === "string" ? a.leisure : "") ||
    (typeof a?.building === "string" ? a.building : "") ||
    (typeof a?.railway === "string" ? a.railway : "") ||
    "";

  // 2d) Stadt ermitteln
  // Je nach Gegend wird es als city, town, village oder hamlet geliefert.
  stadt =
    a.city ||
    a.town ||
    a.village ||
    a.hamlet ||
    "";

  // 2e) Region ermitteln (Bundesland/Kanton/State)
  // Fallback: county (Landkreis)
  region =
    a.state ||
    a.region ||
    a.county ||
    "";

  // 2f) Land ermitteln
  land = a.country || "";

} catch (e) {
  // Wenn die Abfrage fehlschlägt (offline, Timeout, API blockiert),
  // setzen wir trotzdem die Koordinaten. Adresse-Felder bleiben leer.
  console.error(e);
  new Notice("Adresse konnte nicht geladen werden (Internet/API)");
}


// ------------------------------------------------------------
// 3) Frontmatter der aktuellen Notiz aktualisieren
// ------------------------------------------------------------

// Aktuelle Datei ermitteln
const file = tp.file.find_tfile(tp.file.path(true));

// processFrontMatter kümmert sich darum, YAML korrekt zu schreiben
await app.fileManager.processFrontMatter(file, (frontmatter) => {

  // Koordinaten als Liste speichern. Strings sind ok und stabil in YAML.
  frontmatter.coordinates = [lat, lon];

  // Adresse nur setzen, wenn wir wirklich etwas bekommen haben
  if (adresse) frontmatter.adresse = adresse;

  // Ort und Ort-Typ setzen, wenn vorhanden
  if (ort) frontmatter.ort = ort;
  if (ort_type) frontmatter.ort_type = ort_type;

  // Strukturierte Felder sind später sehr nützlich für Bases/Dataview
  if (stadt) frontmatter.stadt = stadt;
  if (region) frontmatter.region = region;
  if (land) frontmatter.land = land;
});


// ------------------------------------------------------------
// 4) Rückmeldung
// ------------------------------------------------------------

new Notice("Koordinaten, Ort und Adresse wurden gesetzt");
%>