<?php
/**
 * SecNote - PM-Klasse (PageManager / Hauptlogik)
 *
 * Diese Klasse ist das Herzstück der SecNote-Anwendung. Sie verwaltet:
 * - API-Endpunkte für Erstellen, Abrufen, Löschen und Passwort-Versuche
 * - HTML-Rendering des Eingabeformulars und des Viewers
 * - Automatische Löschung abgelaufener Nachrichten
 * - Statistik-Counter (Web, SQL, Passwort, Bild)
 * - Debug-Ausgabe
 *
 * Die Klasse verwendet ein generisches Database-Objekt ($class_obj),
 * das über den Konstruktor dynamisch geladen wird.
 */
class PM {

  // --- Eigenschaften ---

  /** @var object Datenbank-Objekt (wird dynamisch im Konstruktor geladen) */
  public $class_obj;
  /** @var array UI-Nachrichtentexte aus variablen.php */
  private $msg;
  /** @var array Anwendungskonfiguration aus variablen.php */
  private $config;
  /** @var int Aktueller Unix-Zeitstempel */
  private $timestamp;
  /** @var string Formatiertes Datum (Y.m.d) */
  private $datum;
  /** @var string Formatierte Uhrzeit (H-i-s) */
  private $uhrzeit;
  /** @var string Kombination aus Datum und Uhrzeit */
  private $zeit;
  /** @var string Aktuelles Jahr (4-stellig) */
  private $jahr;
  /** @var string Aktueller Monat (2-stellig) */
  private $monat;
  /** @var string Aktueller Tag (2-stellig) */
  private $tag;
  /** @var string Aktuelle Stunde (2-stellig) */
  private $stunde;
  /** @var string Aktuelle Minute (2-stellig) */
  private $minute;
  /** @var int Zählerstand: Gespeicherte Nachrichten gesamt */
  private $sqlcounter;
  /** @var int Zählerstand: Nachrichten mit Passwort */
  private $pwcounter;
  /** @var int Zählerstand: Nachrichten mit Bild */
  private $imgcounter;
  /** @var int Zählerstand: Webseitenaufrufe */
  private $counter;
  /** @var string Text-Inhalt der Nachricht */
  private $text;
  /** @var string Generierter eindeutiger Code für die Nachricht */
  private $code;
  /** @var string Statusmeldung für Benutzer-Feedback */
  private $meldung;

  // === KONSTRUKTOR =============================================================

  /**
   * Konstruktor: Lädt die Datenbank-Klasse dynamisch und erstellt eine Instanz.
   *
   * @param string $class_needed Name der zu ladenden Klasse (z.B. "Database")
   * @param string $file_ending  Dateiendung der Klassendatei (z.B. ".php")
   */
  public function __construct ($class_needed,$file_ending) {
    // Die Klasse wird eingebunden (z.B. "Database.php")
      include($class_needed.$file_ending);
    // Es wird eine Instanz der Klasse erzeugt, und "class_obj" zugewiesen
      $this->class_obj = new $class_needed;
      // Debug-Ausgabe der POST- und GET-Daten (nur wenn Debug-Modus aktiv)
      $this->debug($_POST);
      $this->debug($_GET);
  }

  // === KONFIGURATION ===========================================================

  /**
   * Setzt Konfiguration und Nachrichten, initialisiert Zeitstempel
   * und löscht automatisch abgelaufene Nachrichten.
   *
   * @param array $config  Anwendungskonfiguration
   * @param array $MSG     UI-Nachrichtentexte
   */
  public function config($config, $MSG) {
    $this->msg = $MSG;
    $this->config = $config;

    // Zeitstempel und abgeleitete Datumskomponenten initialisieren
    date_default_timezone_set("Europe/Berlin");

    $this->timestamp = time();
    $this->datum = date("Y.m.d",$this->timestamp);
    $this->uhrzeit = date("H-i-s",$this->timestamp);
    $this->zeit 	= $this->datum."--".$this->uhrzeit;
    $this->jahr 	= substr($this->zeit,0,4);
    $this->monat 	= substr($this->zeit,4,2);
    $this->tag 	= substr($this->zeit,6,2);
    $this->stunde = substr($this->zeit,8,2);
    $this->minute = substr($this->zeit,10,2);

    // Automatische Bereinigung: Alte Nachrichten löschen (älter als userDelDays)
    $this->del_older();
  }

  // === HTML-RENDERING ==========================================================

  /**
   * Rendert das Eingabeformular zum Erstellen einer neuen Nachricht.
   * Enthält: Textarea, optionaler Bild-Upload, optionale Passwort-Funktion.
   * Nach dem Erstellen wird das Formular ausgeblendet und der Ergebnis-Container angezeigt.
   *
   * @param string $msg Anleitungstext, der über dem Formular angezeigt wird
   */
  public function schreiben($msg) {
    // Auswahl-Optionen für Passwort-Fehlversuche (0-3)
    $typen=array("0"=>"0","1"=>"1","2"=>"2","3"=>"3", );

    // --- Formular-Container ---
    echo "<div id=\"schreiben\">\n";
    echo "  <span id=\"text1\">$msg</span>\n";
    echo "  <form id=\"secnote-form\" method=\"post\" enctype=\"multipart/form-data\">\n";
    echo "    <textarea id=\"secnote-text\" name=\"text\" cols=\"40\" rows=\"10\"></textarea>\n<br/><br />\n";

    // Optionaler Bild-Upload (nur wenn in Konfiguration aktiviert)
    if ($this->config['bild_upload']) {
      echo "<label for=\"secnote-bild\">".$this->msg['bild_label']."</label><br />\n";
      echo "<input type=\"file\" name=\"bild\" id=\"secnote-bild\" accept=\"image/*\" /><br /><br />\n";
    }

    // Absende-Button
    echo "    <input type=\"submit\" id=\"secnote-submit\" name=\"text_neu\" value=\"".$this->msg['link_erstellen']."\">\n";

    // Optionale Passwort-Funktion (nur wenn in Konfiguration aktiviert)
    if ($this->config['passwort_funktion']) {
      echo "<hr />\n";
      echo "zus&auml;tzliche Optionen:<br /><br />\n";
      // Passwort-Eingabefeld
      echo "<label for \"pw\">Passwort</label>  <input id=\"pw\" type=\"password\" name=\"passwort\" size=\"8\" />\n";
      // Checkbox zum Anzeigen/Verstecken des Passworts
      echo "    <input id=\"check\" type=\"checkbox\" />\n";
      echo "<label for \"check\"> ".$this->msg['zeigen']."</label><br />\n";
      echo "<span id=\"passworthinweisSender\">".$this->msg['passworthinweisSender']."</span><br />\n";
      // Dropdown für erlaubte Passwort-Fehlversuche
      echo "<label for \"fehlversuche\">M&ouml;gliche Passwortfehlversuche des Empf&auml;nger erlauben.</label>\n";$this->select($typen, "fehlversuche",$this->config['Passwortfehlversuche']);
      // Inline-Script: Passwort-Sichtbarkeit per Checkbox umschalten
      echo "<script>\n";
      echo "	var check = document.getElementById(\"check\"),\n";
      echo "		pw = document.getElementById(\"pw\");\n";
      echo "	check.onclick = function() {\n";
      echo "		pw.type = this.checked ? \"text\" : \"password\";\n";
      echo "	};\n";
      echo "</script>\n";
    }
    echo "  </form>\n";
    echo "\n";
    echo "</div>\n";

    // --- Ergebnis-Container (wird erst nach erfolgreichem Erstellen per JS eingeblendet) ---
    echo "<div id=\"secnote-result\" style=\"display:none;\">\n";
    echo "  <div id=\"gespeichert\">\n";
    echo "    ".$this->msg['gespeichert1']."\n";
    // Hinweis-Text (wird per JS befüllt)
    echo "    <b><span id=\"hinweis\"></span><br /><br /></b>\n";
    // URL-Box: Zeigt den generierten Link mit Schlüssel an
    echo "    <div id=\"urlbox\">\n";
    echo "      <span id=\"url\"></span><br />\n";
    echo "    </div>\n";
    // Kopier-Button (nutzt Clipboard.js)
    echo "    <br />\n";
    echo "    <button class=\"btn btn-green\" data-clipboard-target=\"#url\">".$this->msg['clipboard']."</button>\n";
    echo "    <br /><br /><br /><br />\n";
    // Link zum Erstellen einer weiteren Nachricht
    echo "    <a class=\"btn-neue-nachricht\" href=\"index.php\">".$this->msg['link_weitere']."</a>\n";
    echo "  </div>\n";
    echo "</div>\n";
  }

  // === API-METHODEN (JSON-Antworten) ==========================================

  /**
   * API: Neue Nachricht speichern (POST).
   *
   * Empfängt bereits clientseitig verschlüsselte Daten (msg, img),
   * generiert einen eindeutigen Code und speichert alles in der Datenbank.
   *
   * POST-Parameter:
   * - csrf_token: CSRF-Schutz-Token
   * - msg: Verschlüsselter Nachrichtentext (Base64)
   * - img: Verschlüsseltes Bild (Base64, optional)
   * - passwort: 0 oder 1 (ob zusätzliches Passwort gesetzt wurde)
   * - fehler: Erlaubte Passwort-Fehlversuche (0-3)
   *
   * JSON-Antwort bei Erfolg: {success: true, id: "...", url: "..."}
   * JSON-Antwort bei Fehler: {success: false, error: "..."}
   */
  public function api_eintragen() {
    // CSRF-Token validieren (Schutz gegen Cross-Site-Request-Forgery)
    if (!isset($_POST['csrf_token']) || !hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])) {
      echo json_encode(array('success' => false, 'error' => 'CSRF-Token ungueltig.'));
      return;
    }

    // POST-Daten auslesen
    $msg = isset($_POST['msg']) ? $_POST['msg'] : '';
    $img = isset($_POST['img']) ? $_POST['img'] : '';
    $passwort = isset($_POST['passwort']) ? intval($_POST['passwort']) : 0;
    $fehler = isset($_POST['fehler']) ? intval($_POST['fehler']) : 0;

    // Fehlversuche auf gültigen Bereich begrenzen (0-3)
    if ($fehler < 0 || $fehler > 3) { $fehler = 0; }

    // Mindestens Text oder Bild muss vorhanden sein
    if ($msg === '' && $img === '') {
      echo json_encode(array('success' => false, 'error' => $this->msg['eingabe_leer']));
      return;
    }

    // Eindeutigen Zugangscode generieren (z.B. 8 alphanumerische Zeichen)
    $this->genCode($this->config['codelenght']);

    // Daten-Array für das Prepared Statement zusammenstellen
    $arr = array();
    $arr[] = $this->code;          // rid: Eindeutiger Nachrichten-Code
    $arr[] = $msg;                 // msg: Verschlüsselter Text (Base64)
    $arr[] = $this->timestamp;     // datum: Erstellungszeitpunkt (Unix)
    $arr[] = "";                   // rdatum: Lesezeitpunkt (leer, wird beim Abruf gesetzt)
    $arr[] = $passwort;            // passwort: 0=kein Passwort, 1=Passwort gesetzt
    $arr[] = $fehler;              // fehler: Verbleibende Passwort-Fehlversuche
    $arr[] = ($img !== '') ? $img : null;  // img: Verschlüsseltes Bild oder NULL

    // In Datenbank einfügen
    if ($this->class_obj->insert("INSERT INTO nachrichten (rid, msg, datum, rdatum, passwort, fehler, img) VALUES (?,?,?,?,?,?,?)", $arr)) {
      // Statistik-Counter aktualisieren
      $this->update_sqlcounter();
      if ($passwort == 1) {
        $this->update_pwcounter();
      }
      if ($img !== '') {
        $this->update_imgcounter();
      }
      // Erfolg: ID und vollständige URL (ohne Schlüssel) zurückgeben
      // Der Schlüssel wird clientseitig als URL-Fragment (#key) angehängt
      echo json_encode(array(
        'success' => true,
        'id' => $this->code,
        'url' => $this->config['URL'] . $this->code
      ));
    } else {
      echo json_encode(array('success' => false, 'error' => 'Datenbankfehler.'));
    }
  }

  /**
   * API: Verschlüsselte Nachricht abrufen (GET).
   *
   * Gibt die verschlüsselten Daten einer Nachricht zurück.
   * Die Entschlüsselung erfolgt clientseitig im Browser.
   * Hinweis: Die Nachricht wird hier nur gelesen, nicht gelöscht.
   * Das Löschen erfolgt über api_delete() nach erfolgreicher Entschlüsselung.
   *
   * @param string $id Der eindeutige Nachrichten-Code (rid)
   *
   * JSON-Antwort: {found: true/false, msg: "...", img: "...", passwort: 0/1, fehler: N}
   */
  public function api_fetch($id) {
    // Nachricht anhand des Codes aus der Datenbank laden
    $selected = $this->class_obj->select("SELECT id,rid,msg,passwort,fehler,img FROM nachrichten WHERE rid = ?", array($id));

    // Nachricht nicht gefunden (bereits gelöscht oder ungültiger Code)
    if (count($selected) === 0) {
      echo json_encode(array('found' => false));
      return;
    }

    // Verschlüsselte Daten als JSON zurückgeben
    $row = $selected[0];
    echo json_encode(array(
      'found' => true,
      'msg' => $row['msg'] !== null ? $row['msg'] : '',       // Verschlüsselter Text
      'img' => $row['img'] !== null ? $row['img'] : '',       // Verschlüsseltes Bild
      'passwort' => intval($row['passwort']),                  // Passwort-Flag (0 oder 1)
      'fehler' => intval($row['fehler'])                       // Verbleibende Fehlversuche
    ));
  }

  /**
   * API: Nachricht löschen (POST).
   *
   * Wird vom Client nach erfolgreicher Entschlüsselung aufgerufen,
   * um die Nachricht unwiderruflich vom Server zu entfernen.
   * Dadurch kann jede Nachricht nur einmal gelesen werden.
   *
   * POST-Parameter:
   * - csrf_token: CSRF-Schutz-Token
   * - id: Nachrichten-Code (rid)
   *
   * JSON-Antwort: {success: true/false}
   */
  public function api_delete() {
    // CSRF-Token validieren
    if (!isset($_POST['csrf_token']) || !hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])) {
      echo json_encode(array('success' => false, 'error' => 'CSRF-Token ungueltig.'));
      return;
    }
    $id = isset($_POST['id']) ? $_POST['id'] : '';
    if ($id === '') {
      echo json_encode(array('success' => false));
      return;
    }
    // Nachricht aus der Datenbank löschen
    $this->class_obj->delete("DELETE FROM nachrichten WHERE rid = ?", array($id));
    echo json_encode(array('success' => true));
  }

  /**
   * API: Passwort-Fehlversuch registrieren (POST).
   *
   * Wird aufgerufen, wenn der Empfänger ein falsches Passwort eingibt.
   * Reduziert den Fehlversuch-Zähler um 1. Wenn keine Versuche mehr
   * übrig sind, wird die Nachricht automatisch gelöscht.
   *
   * POST-Parameter:
   * - csrf_token: CSRF-Schutz-Token
   * - id: Nachrichten-Code (rid)
   *
   * JSON-Antwort: {remaining: N, deleted: true/false}
   */
  public function api_attempt() {
    // CSRF-Token validieren
    if (!isset($_POST['csrf_token']) || !hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])) {
      echo json_encode(array('success' => false, 'error' => 'CSRF-Token ungueltig.'));
      return;
    }
    $id = isset($_POST['id']) ? $_POST['id'] : '';
    if ($id === '') {
      echo json_encode(array('success' => false));
      return;
    }

    // Aktuelle Fehlversuche aus der Datenbank laden
    $selected = $this->class_obj->select("SELECT id,fehler FROM nachrichten WHERE rid = ?", array($id));
    if (count($selected) === 0) {
      // Nachricht existiert nicht mehr
      echo json_encode(array('remaining' => 0, 'deleted' => true));
      return;
    }

    $row = $selected[0];
    $remaining = intval($row['fehler']) - 1;

    if ($remaining < 0) {
      // Keine Versuche mehr übrig -> Nachricht löschen
      $this->class_obj->delete("DELETE FROM nachrichten WHERE id = ?", array($row['id']));
      echo json_encode(array('remaining' => 0, 'deleted' => true));
    } else {
      // Fehlversuch-Zähler dekrementieren
      $this->class_obj->update("UPDATE nachrichten SET fehler = ? WHERE id = ?", array($remaining, $row['id']));
      echo json_encode(array('remaining' => $remaining, 'deleted' => false));
    }
  }

  // === VIEWER (HTML-Hülle) ====================================================

  /**
   * Rendert den Viewer-Container für die Nachrichtenanzeige.
   *
   * Gibt nur eine leere HTML-Hülle mit Platzhalter-Divs aus.
   * Die eigentliche Entschlüsselung und Darstellung übernimmt
   * das JavaScript-Modul (secnote-app.js).
   *
   * Container:
   * - viewer-loading: Ladeindikator (sichtbar beim Laden)
   * - viewer-password: Passwort-Eingabeformular (bei passwortgeschützten Nachrichten)
   * - viewer-content: Entschlüsselter Nachrichteninhalt
   * - viewer-error: Fehlermeldungen
   */
  public function viewer() {
    echo "<div id=\"viewer-container\">\n";
    echo "  <div id=\"viewer-loading\">".$this->msg['nachricht_laden']."</div>\n";
    echo "  <div id=\"viewer-password\" style=\"display:none;\"></div>\n";
    echo "  <div id=\"viewer-content\" style=\"display:none;\"></div>\n";
    echo "  <div id=\"viewer-error\" style=\"display:none;\"></div>\n";
    echo "</div>\n";
  }

  // === NACHRICHTEN-BEREINIGUNG ================================================

  /**
   * Löscht alle Nachrichten, die älter als die konfigurierte Anzahl Tage sind.
   *
   * Wird automatisch bei jedem Seitenaufruf in config() aufgerufen.
   * Vergleicht den Erstellungszeitpunkt (datum) jeder Nachricht mit
   * dem aktuellen Zeitpunkt minus 'userDelDays' Tage.
   */
  public function del_older() {
     // Alle Nachrichten aus der Datenbank laden
     $selected = $this->class_obj->select("SELECT id,rid,msg,datum,rdatum,passwort FROM nachrichten");
     $rowCount = $this->class_obj->rowCount();

     // Jede Nachricht auf Ablauf prüfen
     for ($i=0; $i < $rowCount; $i++) {
       if (count($selected) > 0) {
         // Wenn das Erstellungsdatum älter ist als (jetzt - X Tage), löschen
         if($selected[$i]['datum'] < strtotime("-".$this->config['userDelDays']." days")) {
           $this->class_obj->delete("DELETE FROM nachrichten WHERE id = ?", array($selected[$i]['id']));
         }
       }
     }
  }

  // === HILFSMETHODEN ==========================================================

  /**
   * Gibt einen Link zum Erstellen einer eigenen Nachricht aus.
   * Wird am Ende der Nachrichtenanzeige eingeblendet.
   */
  private function msg_link() {
     echo "<a href=\"index.php\" class=\"mein-btn\">".$this->msg['selbstNachricht']."</a>";
  }

  /**
   * Generiert einen zufälligen alphanumerischen Code als eindeutige Nachrichten-ID.
   *
   * Verwendet random_int() für kryptographisch sichere Zufallszahlen.
   * Der Code wird in $this->code gespeichert und als URL-Parameter verwendet.
   *
   * @param int $characters Gewünschte Länge des Codes (Standard: 8 aus Konfiguration)
   * @return string Der generierte Code
   */
  private	function genCode($characters) {
    $possible = '1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $this->code = '';
    $i = 0;
    while ($i < $characters) {
      $this->code .= $possible[random_int(0, strlen($possible)-1)];
      $i++;
    }
    return $this->code;
  }

  // === STATISTIK-COUNTER ======================================================

  /**
   * Inkrementiert den SQL-Counter (Gesamtzahl gespeicherter Nachrichten).
   * Wird nach jeder erfolgreichen Nachrichtenerstellung aufgerufen.
   */
  private function update_sqlcounter() {
    $neuerwert=0;
    $wert = $this->sqlcounter();
    $neuerwert = $wert + 1;
        if ($this->class_obj->update("UPDATE sqlcounter SET sqlcounter=? WHERE id = ? ", array($neuerwert,1))) {
          $updatedRows = $this->class_obj->rowCount();
          $this->meldung=" wurde erfolgreich ge&auml;ndert.\n";
        } else {
          $this->meldung = "Beim &auml;ndern gab es einen Fehler.\n";
        }
    }

  /**
   * Inkrementiert den Bild-Counter (Anzahl Nachrichten mit Bild-Anhang).
   * Wird aufgerufen, wenn eine Nachricht mit Bild erstellt wird.
   */
  private function update_imgcounter() {
    $neuerwert=0;
    $wert = $this->imgcounter();
    $neuerwert = $wert + 1;
        if ($this->class_obj->update("UPDATE imgcounter SET imgcounter=? WHERE id = ? ", array($neuerwert,1))) {
          $updatedRows = $this->class_obj->rowCount();
          $this->meldung=" wurde erfolgreich ge&auml;ndert.\n";
        } else {
          $this->meldung = "Beim &auml;ndern gab es einen Fehler.\n";
        }
    }

  /**
   * Inkrementiert den Passwort-Counter (Anzahl passwortgeschützter Nachrichten).
   * Wird aufgerufen, wenn eine Nachricht mit Passwort erstellt wird.
   */
  private function update_pwcounter() {
    $neuerwert=0;
    $wert = $this->pwcounter();
    $neuerwert = $wert + 1;
        if ($this->class_obj->update("UPDATE pwcounter SET pwcounter=? WHERE id = ? ", array($neuerwert,1))) {
          $updatedRows = $this->class_obj->rowCount();
          $this->meldung=" wurde erfolgreich ge&auml;ndert.\n";
        } else {
          $this->meldung = "Beim &auml;ndern gab es einen Fehler.\n";
        }
    }

  /**
   * Liest den aktuellen SQL-Counter aus der Datenbank.
   * @return int Gesamtzahl erstellter Nachrichten
   */
  public function sqlcounter() {
    $counter = $this->class_obj->select("SELECT sqlcounter FROM sqlcounter WHERE id='1'");
    $this->sqlcounter = $counter[0]['sqlcounter'];
    return $this->sqlcounter ;
  }

  /**
   * Liest den aktuellen Passwort-Counter aus der Datenbank.
   * @return int Anzahl passwortgeschützter Nachrichten
   */
  public function pwcounter() {
    $counter = $this->class_obj->select("SELECT pwcounter FROM pwcounter WHERE id='1'");
    $this->pwcounter = $counter[0]['pwcounter'];
    return $this->pwcounter ;
  }

  /**
   * Liest den aktuellen Bild-Counter aus der Datenbank.
   * @return int Anzahl Nachrichten mit Bild-Anhang
   */
  public function imgcounter() {
    $counter = $this->class_obj->select("SELECT imgcounter FROM imgcounter WHERE id='1'");
    $this->imgcounter = $counter[0]['imgcounter'];
    return $this->imgcounter ;
  }

  /**
   * Liest den aktuellen Webcounter (Seitenaufrufe) aus der Datenbank.
   * @return int Anzahl eindeutiger Seitenaufrufe
   */
  public function webcounter() {
    $counter = $this->class_obj->select("SELECT counter FROM counter WHERE id='1'");
    $this->counter = $counter[0]['counter'];
    $this->debug($this->counter);
    return $this->counter ;
  }

  /**
   * Inkrementiert den Webcounter um 1.
   * Wird einmal pro Session aufgerufen (gesteuert durch $_SESSION['counter_ip']).
   */
  public function update_webcounter() {
    $neuerwert = $this->webcounter() + 1;
    $this->class_obj->update("UPDATE counter SET counter=? WHERE id = ?", array($neuerwert, 1));
  }

  // === UI-HILFSMETHODEN =======================================================

  /**
   * Rendert ein HTML-<select>-Dropdown.
   *
   * Wird für die Auswahl der erlaubten Passwort-Fehlversuche verwendet.
   *
   * @param array  $werte        Assoziatives Array mit Optionen (key => value)
   * @param string $name         Name-Attribut des Select-Elements
   * @param string $selected     Vorausgewählter Wert
   * @param int    $default      Wenn 1, wird eine Standard-Option vorangestellt
   * @param string $beschriftung Text der Standard-Option
   * @param int    $KeyOrVal     0=Key als value, 1=Val als value
   */
  private function select($werte, $name, $selected="", $default=0, $beschriftung="", $KeyOrVal=0) {
    echo "<select size=\"1\" name=\"$name\" id=\"secnote-fehler\">\n";
    // Optionale Standard-Option einfügen
    if (isset($default)AND ($default==1)) { echo "<option ";
      if($selected == 0 ) echo "selected";
      echo " value=\"0\">$beschriftung</option>\n";}
    // Optionen aus dem Array rendern
    foreach ($werte as $key => $val) {
      echo '<option ';
      if ($key == $selected) { echo " selected "; }
      echo " value=\"";
      $ausgabe = ($KeyOrVal ==0 ? $key : $val);
      echo $ausgabe;
      echo "\">".$val."</option>\n";
    }
    echo "</select>\n";
  }

  /**
   * Debug-Hilfsfunktion: Gibt Variablen formatiert aus, wenn der Debug-Modus aktiv ist.
   *
   * Prüft $_SESSION['debug'] und gibt Strings rot markiert aus,
   * Arrays werden mit print_r() in <pre>-Tags formatiert.
   * Alle Ausgaben werden XSS-sicher mit htmlspecialchars() escaped.
   *
   * @param mixed $ausgabe  Auszugebende Variable (String oder Array)
   * @param bool  $array    Wenn true, werden Arrays formatiert ausgegeben
   */
  private function debug ($ausgabe="", $array=true) {
  	if ($ausgabe !="") {
  		if (isset($_SESSION['debug']) and ($_SESSION['debug'] == true)) {
  			// String-Ausgabe: Rot markiert in Klammern
  			if (is_string($ausgabe)) {
  				echo "<font color=\"#FF0000\">(" . htmlspecialchars($ausgabe, ENT_QUOTES, 'UTF-8') . ")</font><br>\n";
  			}
  			// Array-Ausgabe: Formatiert mit print_r() in <pre>-Tags
          if (is_array($ausgabe)) {
  			  if ($array) {
  				  echo "<pre>\n";
  				  echo htmlspecialchars(print_r($ausgabe, true), ENT_QUOTES, 'UTF-8');
  				  echo "</pre>\n";
  			  }
				}
  		}
  	}
  }

// === KLASSE ENDE ==============================================================
}
?>
