#!/usr/bin/env /home/dn2ane/sun_venv/bin/python3
import math
import subprocess
import pandas as pd
import pvlib

# Standortkonfiguration (München)
LATITUDE = 48.173333
LONGITUDE = 11.635
ALTITUDE = 520

# Aktuelle Sonnenposition berechnen
now = pd.Timestamp.now(tz="Europe/Berlin")
solpos = pvlib.solarposition.get_solarposition(
    time=now,
    latitude=LATITUDE,
    longitude=LONGITUDE,
    altitude=ALTITUDE,
    method="nrel_numpy",
)

elevation = solpos["apparent_elevation"].iloc[0]
azimuth = solpos["azimuth"].iloc[0]

alt_rad = math.radians(elevation)
az_rad = math.radians(azimuth)

# POV-Ray Raum-Koordinaten (Blick von Süd nach Nord auf die Wand):
# -X = West (links), +X = Ost (rechts), +Y = Oben, +Z = Nord (in die Wand)
# Azimut 180° = Süd, 270° = West (-X)
# Lichtvektor Vektor zur Sonne: Nachmittags (-X). 
# POV-Ray light_source strahlt VON dieser Position Richtung Ursprung.
sun_x = -math.sin(az_rad) * math.cos(alt_rad)
sun_y = math.sin(alt_rad)
sun_z = -math.cos(az_rad) * math.cos(alt_rad)

# Zeitzonen-Kürzel & Datum
is_dst = now.dst() != pd.Timedelta(0)
tz_name = "MESZ" if is_dst else "MEZ"
target_meridian = 30.0 if is_dst else 15.0  # 30° E für UTC+2, 15° E für UTC+1

# Zeitgleichung (Equation of Time in Minuten)
b_rad = math.radians((360 / 365) * (now.dayofyear - 81))
eot_minutes = (
    9.87 * math.sin(2 * b_rad) - 7.53 * math.cos(b_rad) - 1.5 * math.sin(b_rad)
)

weekdays_de = {
    "Monday": "Montag",
    "Tuesday": "Dienstag",
    "Wednesday": "Mittwoch",
    "Thursday": "Donnerstag",
    "Friday": "Freitag",
    "Saturday": "Samstag",
    "Sunday": "Sonntag",
}
weekday_str = weekdays_de[now.strftime("%A")]
date_str = f"{weekday_str}, {now.strftime('%d.%m.%Y')}"
time_str = now.strftime(f"%H:%M:%S {tz_name}")

sun_info_str = f"Azimut: {azimuth:.1f} DEG   Elev: {elevation:.1f} DEG"
pos_info_str = f"Vertikale Suedwand (MESZ-Skala) - Muenchen ({LATITUDE:.4f} N, {LONGITUDE:.4f} E)"

# Sonnenbeleuchtung
if sun_z < 0 and sun_y > 0:
    light_code = f"""
    light_source {{
        <{sun_x:.6f}, {sun_y:.6f}, {sun_z:.6f}> * 10000
        color rgb <1.5, 1.45, 1.3>
    }}
    """
else:
    light_code = """
    light_source {
        <0, 500, -500>
        color rgb <0.1, 0.1, 0.2>
        shadowless
    }
    """

# Polstab (Gnomon) Definition - zeigt nach Süden (-Z) und unten (-Y) parallel zur Erdachse
gnomon_length = 2.5
lat_rad = math.radians(LATITUDE)
gnomon_end_y = -gnomon_length * math.sin(lat_rad)
gnomon_end_z = -gnomon_length * math.cos(lat_rad)

# Längengrad-Korrektur in Grad + Zeitgleichung
longitude_offset_deg = target_meridian - LONGITUDE
eot_offset_deg = eot_minutes / 4.0

# Berechnung der MESZ-Stundenlinien auf der vertikalen Wand (6 bis 19 Uhr)
dial_elements = []
line_length = 3.2

for hour in range(6, 20):
    # Stundenwinkel bezogen auf Zonenzeit (MESZ)
    gamma_civil_deg = (hour - 12) * 15

    # Korrektur für Längengraddifferenz zu 30° E sowie Zeitgleichung
    gamma_true_deg = gamma_civil_deg + longitude_offset_deg - eot_offset_deg
    gamma_rad = math.radians(gamma_true_deg)

    # Winkel alpha auf der Wand gegenüber der Vertikalen
    alpha_rad = math.atan(math.tan(gamma_rad) * math.cos(lat_rad))

    # KORREKTE ZUORDNUNG:
    # Vormittag (hour < 12 -> gamma < 0) -> links (-X)
    # Nachmittag (hour > 12 -> gamma > 0) -> rechts (+X)
    end_x = math.sin(alpha_rad) * line_length
    end_y = -math.cos(alpha_rad) * line_length

    dial_elements.append(f"""
    cylinder {{
        <0, 0, -0.005>, <{end_x:.4f}, {end_y:.4f}, -0.005>, 0.015
        pigment {{ DarkPigment }}
        finish {{ DarkFinish }}
    }}
    """)

    text_x = math.sin(alpha_rad) * (line_length + 0.3) - (
        0.15 if hour >= 10 else 0.08
    )
    text_y = -math.cos(alpha_rad) * (line_length + 0.3) - 0.1

    dial_elements.append(f"""
    text {{
        ttf FontFile
        "{hour}"
        0.02, 0
        pigment {{ DarkPigment }}
        finish {{ DarkFinish }}
        scale <0.4, 0.4, 0.4>
        translate <{text_x:.4f}, {text_y:.4f}, -0.01>
    }}
    """)

dial_code = "\n".join(dial_elements)

pov_content = f"""#version 3.7;
#include "screen.inc"

global_settings {{
    assumed_gamma 1.0
}}

Set_Camera(<0, -0.5, -8.5>, <0, -1.2, 0>, 48)

{light_code}

sky_sphere {{
    pigment {{
        gradient y
        color_map {{
            [0.0 color rgb <0.6, 0.7, 0.9>] 
            [1.0 color rgb <0.2, 0.4, 0.8>] 
        }}
    }}
}}

// Vertikale Wand
plane {{
    z, 0
    texture {{
        pigment {{ color rgb <0.92, 0.90, 0.85> }}
        finish {{ ambient 0.2 diffuse 0.8 }}
    }}
}}

// Polstab (Schattenwerfer)
cylinder {{
    <0, 0, 0>, <0, {gnomon_end_y:.4f}, {gnomon_end_z:.4f}>, 0.04
    texture {{
        pigment {{ color rgb <0.2, 0.2, 0.2> }}
        finish {{ ambient 0.1 diffuse 0.7 metallic }}
    }}
}}

#declare DarkFinish = finish {{ ambient 0.2 diffuse 0.8 }};
#declare DarkPigment = pigment {{ color rgb <0.15, 0.15, 0.15> }};
#declare TextPigment = pigment {{ color rgb <0.1, 0.2, 0.4> }};
#declare FontFile = "/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf";

{dial_code}

#declare Aspect = image_width / image_height;

#declare InfoText0 = text {{ ttf FontFile "{date_str}" 0.01, 0 pigment {{ TextPigment }} finish {{ ambient 1.0 diffuse 0.0 }} scale <0.028, 0.028, 0.028> }};
#declare InfoText1 = text {{ ttf FontFile "{time_str}" 0.01, 0 pigment {{ TextPigment }} finish {{ ambient 1.0 diffuse 0.0 }} scale <0.032, 0.032, 0.032> }};
#declare InfoText2 = text {{ ttf FontFile "{sun_info_str}" 0.01, 0 pigment {{ TextPigment }} finish {{ ambient 1.0 diffuse 0.0 }} scale <0.024, 0.024, 0.024> }};
#declare InfoText3 = text {{ ttf FontFile "{pos_info_str}" 0.01, 0 pigment {{ TextPigment }} finish {{ ambient 1.0 diffuse 0.0 }} scale <0.024, 0.024, 0.024> }};

Screen_Object(InfoText0, <0.02, 0.96>, <0, 0>, Aspect, 1.0)
Screen_Object(InfoText1, <0.02, 0.92>, <0, 0>, Aspect, 1.0)
Screen_Object(InfoText2, <0.02, 0.88>, <0, 0>, Aspect, 1.0)
Screen_Object(InfoText3, <0.02, 0.84>, <0, 0>, Aspect, 1.0)
"""

with open("render.pov", "w") as f:
    f.write(pov_content)

output_file = "/var/www/html/pov/uhr.png"
subprocess.run(
    [
        "povray",
        "+Irender.pov",
        f"+O{output_file}",
        "+W1024",
        "+H576",
        "+A0.1",
        "-D",
    ],
    check=True,
)
print(f"Rendering erfolgreich abgeschlossen: {output_file}")
