#!/usr/bin/env python3

import sys
import os
import numpy as np
import pygame
from datetime import datetime
import math

# Displaygröße
Nx = int(sys.argv[1])  # Breite des Displays (z.B. 80)
Ny = int(sys.argv[2])  # Höhe des Displays (z.B. 40)

# Initialize pygame
pygame.init()
pygame.font.init()

# Pfad zur Pixelfont im Verzeichnis "apps"
font_path = os.path.join('.', 'PressStart2P-Regular.ttf')  # Pfad zur Schriftart

# Schriftart mit optimierter Größe laden (z.B. 16px bis 20px)
font_size = 16  # Geeignete Schriftgröße wählen
font = pygame.font.Font(font_path, font_size)

clock = pygame.time.Clock()
time_elapsed = 0  # Zeit-Tracker für den Farbverlauf

# Feste Farbe für den Rand (Türkis)
border_color = (64, 224, 208)  # RGB-Werte für Türkis

# Funktion zur Berechnung der RGB-Farbe basierend auf der Zeit und der Position des Zeichens
def calculate_color(time_elapsed, position, total_length):
    """Berechnet eine RGB-Farbe basierend auf der verstrichenen Zeit und der Position des Zeichens."""
    frequency = 2 * math.pi / total_length  # Frequenz für den Regenbogenverlauf
    phase_shift = position * frequency  # Verschiebung der Phase pro Zeichen

    r = int((math.sin(time_elapsed + phase_shift) + 1) * 127.5)
    g = int((math.sin(time_elapsed + phase_shift + 2 * math.pi / 3) + 1) * 127.5)
    b = int((math.sin(time_elapsed + phase_shift + 4 * math.pi / 3) + 1) * 127.5)

    return (r, g, b)

# Funktion zum Rendern des Rahmens
def render_border(display_surface, Nx, Ny, border_color):
    """Zeichnet den Rahmen mit einer festen Farbe."""
    # Obere Linie des Rahmens
    for x in range(Nx):
        display_surface.set_at((x, 0), border_color)  # Oben

    # Rechte Linie des Rahmens
    for y in range(1, Ny - 1):
        display_surface.set_at((Nx - 1, y), border_color)  # Rechts

    # Untere Linie des Rahmens
    for x in range(Nx - 1, -1, -1):
        display_surface.set_at((x, Ny - 1), border_color)  # Unten

    # Linke Linie des Rahmens
    for y in range(Ny - 2, 0, -1):
        display_surface.set_at((0, y), border_color)  # Links

# Funktion zum Zeichnen der Uhrzeit
def render_time(display_surface, Nx, Ny, font, current_time, time_elapsed):
    """Zeichnet die aktuelle Uhrzeit mittig auf das Display."""
    # Reduzierter Zeichenabstand (85% der Schriftgröße)
    character_spacing = font_size * 0.95  
    # Breite des gesamten Textes berechnen
    text_width = len(current_time) * character_spacing  
    
    # Horizontale und vertikale Zentrierung
    x_offset = (Nx - text_width) // 2  
    y_offset = (Ny - font_size) // 2   

    # Zeichnen der Uhrzeit
    for i, char in enumerate(current_time):
        # Berechne die Farbe für das aktuelle Zeichen
        text_color = calculate_color(time_elapsed, i, len(current_time))
        # Rendern des Zeichens
        text = font.render(char, True, text_color)
        text_rect = text.get_rect(topleft=(x_offset + i * character_spacing, y_offset))
        # Zeichen auf das Display zeichnen
        display_surface.blit(text, text_rect)

# Hauptprogramm zur Anzeige der Uhrzeit
while True:
    # Zeit seit Beginn des Programms
    time_elapsed += clock.get_time() / 1000.0  # in Sekunden

    # Aktuelle Zeit abrufen
    now = datetime.now()
    current_time = now.strftime("%H:%M")  # Uhrzeit im Format HH:MM

    # Ein leeres Display für die Uhrzeit erstellen
    display_surface = pygame.Surface((Nx, Ny))
    display_surface.fill((0, 0, 0))  # Hintergrund schwarz

    # Rahmen zeichnen
    render_border(display_surface, Nx, Ny, border_color)

    # Uhrzeit zeichnen (Aufruf der neuen Funktion)
    render_time(display_surface, Nx, Ny, font, current_time, time_elapsed)

    # Sicherstellen, dass das Bild die korrekten Dimensionen hat und der Framebuffer vollständig ist
    out = pygame.surfarray.array3d(display_surface).transpose((1, 0, 2)).astype(np.uint8).tobytes()

    # Framebuffer zum Server senden
    os.write(1, out)

    clock.tick(30)  # 30 FPS für flüssigen Farbverlauf

