#!/usr/bin/env python3
"""
Vereinfacht die OSRM-Polylines in lg-roadnet.json via Douglas-Peucker
(~100 m Toleranz). Reduziert die Dateigroesse von ~9 MB auf ~1 MB, ohne
dass die Kurvenfuehrung auf Europa-Zoomstufen sichtbar leidet.

Dazu: Berlin-Kopenhagen manuell reparieren — OSRM Auto-Profil kennt die
Fähre Rostock-Gedser nicht und umrundet die Ostsee (1027 km). Wir setzen
die Route auf Berlin->Rostock (Land, OSRM) + Rostock-Gedser (Fähre, direkt)
+ Gedser->Kopenhagen (Land, OSRM), Distanz = 450 km analog Realfahrt.
"""
import json
import math
import ssl
import time
import urllib.request
from pathlib import Path

ROADNET = Path(__file__).resolve().parents[3] / "assets" / "data" / "lg-roadnet.json"
TOLERANCE_DEG = 0.001          # ~110 m — glatt genug auf Europa-Zoom 4-8
OSRM = "https://router.project-osrm.org/route/v1/driving/{coords}?overview=full&geometries=geojson"

SSL_CTX = ssl.create_default_context()
SSL_CTX.check_hostname = False
SSL_CTX.verify_mode = ssl.CERT_NONE


def perpendicular_distance(pt, a, b):
    """Abstand pt zu Gerade a-b (in lat/lon-Einheiten, nicht metrisch, ok fuer RDP)."""
    dx = b[0] - a[0]
    dy = b[1] - a[1]
    if dx == 0 and dy == 0:
        return math.hypot(pt[0] - a[0], pt[1] - a[1])
    t = ((pt[0] - a[0]) * dx + (pt[1] - a[1]) * dy) / (dx * dx + dy * dy)
    t = max(0.0, min(1.0, t))
    proj_x = a[0] + t * dx
    proj_y = a[1] + t * dy
    return math.hypot(pt[0] - proj_x, pt[1] - proj_y)


def rdp(points, epsilon):
    """Douglas-Peucker-Vereinfachung."""
    if len(points) < 3:
        return list(points)
    # Max-deviation Punkt finden
    max_d = 0.0
    idx = 0
    for i in range(1, len(points) - 1):
        d = perpendicular_distance(points[i], points[0], points[-1])
        if d > max_d:
            max_d = d
            idx = i
    if max_d <= epsilon:
        return [points[0], points[-1]]
    left  = rdp(points[:idx + 1], epsilon)
    right = rdp(points[idx:], epsilon)
    return left[:-1] + right


def fetch_route(waypoints):
    coords = ";".join(f"{w[1]},{w[0]}" for w in waypoints)
    url = OSRM.format(coords=coords)
    with urllib.request.urlopen(url, timeout=30, context=SSL_CTX) as resp:
        data = json.load(resp)
    route = data["routes"][0]
    geo = route["geometry"]["coordinates"]
    polyline = [[round(c[1], 5), round(c[0], 5)] for c in geo]
    distance_km = route["distance"] / 1000.0
    return polyline, distance_km


def main():
    net = json.loads(ROADNET.read_text(encoding="utf-8"))

    # 1) Berlin-Kopenhagen (Faehre Rostock-Gedser) neu bauen
    print("Berlin-Kopenhagen (Faehre rekonstruieren):")
    rostock = [54.09, 12.14]
    gedser  = [54.58, 11.93]
    berlin  = [52.52, 13.405]
    kph     = [55.6761, 12.5683]
    try:
        poly1, d1 = fetch_route([berlin, rostock])
        time.sleep(1.1)
        poly3, d3 = fetch_route([gedser, kph])
        # Faehren-Segment: gerade Linie mit zwei Zwischenpunkten fuer Animation
        poly2 = [rostock, [54.33, 12.03], gedser]
        combined = poly1 + poly2[1:] + poly3[1:]
        # Land-Strecke + Faehre-Distanz (Rostock-Gedser ca. 48 km Luftlinie ueber Ostsee)
        total_km = d1 + 48 + d3
        print(f"  Berlin->Rostock {d1:.0f} km, Faehre 48 km, Gedser->KPH {d3:.0f} km = {total_km:.0f} km")
        for edge in net["edges"]:
            if edge["id"] == "berlin-kopenhagen":
                edge["polyline"] = combined
                edge["distanceKmOsrm"] = round(total_km, 1)
                break
    except Exception as e:
        print(f"  FEHLER: {e} — behalte bisherige Polyline.")

    # 2) Alle Polylines vereinfachen
    print(f"\nDouglas-Peucker mit Tolerance {TOLERANCE_DEG}° (~{int(TOLERANCE_DEG*111*1000)} m):")
    for edge in net["edges"]:
        before = len(edge.get("polyline") or [])
        if before < 3:
            continue
        simplified = rdp(edge["polyline"], TOLERANCE_DEG)
        edge["polyline"] = simplified
        after = len(simplified)
        ratio = after / before * 100
        print(f"  {edge['id']}: {before} -> {after} Punkte ({ratio:.1f}%)")

    ROADNET.write_text(
        json.dumps(net, ensure_ascii=False, separators=(",", ":"),
                   indent=None),
        encoding="utf-8",
    )
    new_size = ROADNET.stat().st_size / 1024 / 1024
    print(f"\nFertig — {new_size:.2f} MB")


if __name__ == "__main__":
    main()
