<?php

/*
ET-Chat Copyright by SEDesign | ET-Chat v3.x.x Lizenz: CCPL | Autor: Evgeni Tcherkasski (info@s-e-d.de)
ET-Chat_T-FISH-MOD Weiterentwicklungen, Optimierungen und Ergänzungen am Code sind das geistige Eigentum von Tommy (Thomas Kuhn) und Harlekin (Bernd Witte).

Die darauf folgende Optimierungen und Ergänzungen am Code sind das Geistige Eigentum von Powermen (Christian K.) 
PHP 8/9 Ready, XML Parser, PDO Prepared Statements Get Set sicherheit usw.
*/

$GLOBALS["path"] = "./../";

$CACHE_DIR = __DIR__ . "/cache";
$CACHE_TIME = 30; // Sekunden Cache

function radio_getCacheFile(string $key): string
{
    global $CACHE_DIR;
    return $CACHE_DIR . "/radio_" . md5($key) . ".cache";
}

function radio_getCached(string $key): ?string
{
    global $CACHE_TIME;

    $file = radio_getCacheFile($key);
    if (!file_exists($file)) {
        return null;
    }

    $data = json_decode(file_get_contents($file), true);
    if (!$data || !isset($data["time"], $data["value"])) {
        return null;
    }

    if (time() - $data["time"] > $CACHE_TIME) {
        return null;
    }

    return $data["value"];
}

function radio_setCache(string $key, string $value): void
{
    global $CACHE_DIR;

    if (!is_dir($CACHE_DIR)) {
        mkdir($CACHE_DIR, 0777, true);
    }

    $file = radio_getCacheFile($key);
    $data = [
        "time" => time(),
        "value" => $value,
    ];
    file_put_contents($file, json_encode($data));
}

spl_autoload_register(function ($class_name) {
    require_once $GLOBALS["path"] . "class/" . $class_name . ".class.php";
});

function radio_cleanupCache(int $maxAgeSeconds = 86400): void
{
    $dir = __DIR__ . "/cache";
    if (!is_dir($dir)) {
        return;
    }

    $files = glob($dir . "/*.cache");
    if (!$files) {
        return;
    }

    $limit = time() - $maxAgeSeconds;

    foreach ($files as $file) {
        if (is_file($file) && filemtime($file) < $limit) {
            @unlink($file);
        }
    }
}

/* === Gelegentlich aufräumen (ca. 1% der Starts) === */
if (mt_rand(1, 100) === 1) {
    radio_cleanupCache(86400);
}

class RadioBox extends DbConectionMaker
{
    public function __construct()
    {
        parent::__construct();

        // Session starten, damit $_SESSION Werte verfügbar sind
        if (session_status() === PHP_SESSION_NONE) {
            session_start();
        }

        unset($GLOBALS["path"]);

        $desei = $this->dbObj->sqlGet(
            "SELECT etchat_config_id, etchat_config_radio_name, etchat_config_style FROM {$this->_prefix}etchat_config WHERE etchat_config_id = '1'"
        );
        $radio = $this->dbObj
            ->sqlGet("SELECT etchat_radio_id , etchat_radio_horst, etchat_radio_port, etchat_radio_typ, etchat_radio_stream, etchat_radio_name, etchat_radio_color, etchat_radio_bit, etchat_radio_box, etchat_radio_player, etchat_on_air, etchat_system_titel_an,
		etchat_titel_an FROM {$this->_prefix}etchat_radio_box WHERE etchat_radio_id = '1'");
        ?>

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta content="de" http-equiv="Content-Language" />
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<link href="player.css" rel="stylesheet" type="text/css">
<?php
if (is_array($desei)) {
    foreach ($desei as $data) {
        echo "<link href=\"../styles/$data[2]/style.css\" rel=\"stylesheet\" type=\"text/css\"/>";
    }
}
if (is_array($radio)) {
    foreach ($radio as $data_radio) {
        $horst1 = $data_radio[1];
        $port1 = $data_radio[2];
        $pass1 = $data_radio[3];
        $stream1 = $data_radio[4];
        $rname1 = $data_radio[5];
        $rcolor1 = $data_radio[6];
        $rbit1 = $data_radio[7];
        $radio_box = $data_radio[8];
        $radio_player = $data_radio[9];
        $radio_on_air = $data_radio[10];
    }
}
?>

<title><?php echo htmlspecialchars($desei[0][1] ?? "Radio"); ?></title>
</head>
<body id="body">

<?php
if ($radio_box == "1") {

    $type = $data_radio[3] ?? "shoutcast"; // shoutcast oder icecast

    $xml_data = false;
    $json_data = false;
    $listeners = 0;
    $max = 0;
    $title1 = "";
    $name = "";
	$title = ""; 

    $protocols = ["https", "http"];

    // Cache Key je Stream
    $cacheKey = "radio_metrics_" . $horst1 . "_" . $port1 . "_" . $type;

    // Cache prüfen
    $cached = radio_getCached($cacheKey);
	$cacheWasUpdated = false;
    if ($cached !== null) {
        $data = json_decode($cached, true);
        if (is_array($data)) {
            $title = $data["title"] ?? "";
            $listeners = $data["listeners"] ?? 0;
            $max = $data["max"] ?? 0;
            $name = $data["name"] ?? "";
        }
    } else {
		
		$cacheWasUpdated = true;
		
        switch ($type) {
            case "lautfm":
                $station = $horst1;
                $url = "https://api.laut.fm/station/{$station}/current_song";
                $context = stream_context_create(["http" => ["timeout" => 3]]);
                $json_data = @file_get_contents($url, false, $context);

                if ($json_data !== false) {
                    $data = json_decode($json_data, true);
                    if ($data && isset($data["title"])) {
                        $title1 = $data["title"] ?? "";
                        $name = $data["artist"]["name"] ?? "";
                        $title = "$name - $title1";
                    } else {
                        $title = "Fehler beim Parsen der laut.fm-Daten.";
                    }
                } else {
                    $title = "laut.fm-Station nicht erreichbar.";
                }

                $url = "https://api.laut.fm/station/$horst1/listeners";
                $listeners = @file_get_contents($url);
                if ($listeners === false) {
                    error_log("Konnte $url nicht laden");
                    $listeners = 0;
                } else {
                    $listeners = (int) $listeners;
                }
                $max = 100;
                break;

            case "icecast":
                foreach ($protocols as $proto) {
                    $url = "$proto://$horst1:$port1/status-json.xsl";
                    $context = stream_context_create([
                        "http" => ["timeout" => 3],
                    ]);
                    $json_data = @file_get_contents($url, false, $context);

                    if ($json_data !== false) {
                        $data = json_decode($json_data, true);
                        if ($data && isset($data["icestats"]["source"])) {
                            $source = $data["icestats"]["source"];
                            if (isset($source[0])) {
                                $source = $source[0];
                            }
                            $title = $source["title"] ?? "";
                            $listeners = $source["listeners"] ?? 0;
                            $max = $source["listener_peak"] ?? 0;
                            $name = $source["server_name"] ?? "Icecast Stream";
                            break;
                        }
                    }
                }
                if ($json_data === false) {
                    $title = "Icecast-Server nicht erreichbar.";
                }
                break;

            case "shoutcast":
            default:
                foreach ($protocols as $proto) {
                    $url = "$proto://$horst1:$port1/stats?sid=1&mode=xml";
                    $context = stream_context_create([
                        "http" => ["timeout" => 3],
                    ]);
                    $xml_data = @file_get_contents($url, false, $context);

                    if ($xml_data !== false) {
                        $xml = simplexml_load_string($xml_data);
                        if ($xml && $xml->STREAMSTATUS == 1) {
                            $listeners = (int) $xml->CURRENTLISTENERS;
                            $title = (string) $xml->SONGTITLE;
                            $name = (string) $xml->SERVERTITLE;
                            $max = (string) $xml->MAXLISTENERS;
                            break;
                        }
                    }
                }
                if ($xml_data === false) {
                    $title = "Shoutcast-Server nicht erreichbar.";
                }
        }

        // Cache nur speichern wenn gültige Daten vorhanden sind
		if (!empty($title) && stripos($title, "nicht erreichbar") === false) {

			radio_setCache(
				$cacheKey,
				json_encode([
					"title" => $title,
					"listeners" => $listeners,
					"max" => $max,
					"name" => $name,
				])
			);

		}
    }
    ?>

<script>
setInterval(function() {
    var xhr = new XMLHttpRequest();
    xhr.open("GET", "radio-box.php?metrics=true", true);
    xhr.onreadystatechange = function() {
        if (xhr.readyState === 4 && xhr.status === 200) {
            document.getElementById("dj-on").innerHTML = xhr.responseText;
        }
    }
    xhr.send();
}, 30000);
</script>

<div id="dj-on">
<table class="player" style="width:100%; border-collapse:collapse;">
<tbody>
<tr style="height: 2px;">
<td style="width: 70px; white-space: nowrap;">DJ OnAir:</td>
<td style="width: 2px"></td>
<td colspan="2">

<?php
// === Radio-Titel aus Stream auslesen ===
$title = $title ?? "";

$song1 = "";
$artist = "";
$djName = "Auto DJ";

if (strpos($title, " - ") !== false) {
    $parts = explode(" - ", $title, 2);
    $artist = trim($parts[0] ?? "");
    $song1 = trim($parts[1] ?? "");
} else {
    $song1 = trim($title);
    $artist = "Fehlerhafte Angabe";
}

if (strpos($song1, "|") !== false) {
    $djParts = explode("|", $song1, 2);

    $song1 = trim($djParts[0] ?? "");
    $possibleDj = trim($djParts[1] ?? "");

    // === Mindestlänge prüfen (mind. 3 Zeichen) ===
    if (mb_strlen($possibleDj) >= 3) {
        $djName = $possibleDj;
    } else {
        $djName = "Auto DJ";
    }
}

$isAutoDJ = (mb_strlen($djName) < 3 || $djName === "Auto DJ");

if ($cacheWasUpdated) {

$systemId = 1;
$ts = time();

$config = $this->dbObj->sqlGet("SELECT etchat_config_loeschen_nach
								FROM {$this->_prefix}etchat_config
								WHERE etchat_config_id = 1");
$daysToKeep = max(30, (int) ($config[0][0] ?? 365));
$timeLimit = time() - $daysToKeep * 86400;

$this->dbObj->sqlSet("
	DELETE FROM {$this->_prefix}etchat_radio_history
	WHERE etchat_played_at < $timeLimit
");

$lastEntry = $this->dbObj->sqlGet("
    SELECT etchat_dj_name, etchat_song_title
    FROM {$this->_prefix}etchat_radio_history
    ORDER BY etchat_id DESC
    LIMIT 1
");

$lastDj = $lastEntry[0][0] ?? "Auto DJ";
$lastSongTitle = $lastEntry[0][1] ?? "";

if ($song1 && ($song1 !== $lastSongTitle || $djName !== $lastDj)) {
    // Radio-Historie einfügen
	$this->dbObj->sqlSet(
		"INSERT INTO {$this->_prefix}etchat_radio_history
		(etchat_song_title, etchat_song_artist, etchat_dj_name, etchat_played_at)
		VALUES (?, ?, ?, ?)",
		[$song1, $artist, $djName, $ts]
	);

    // Systemnachricht posten (optional)
    if (!empty($data_radio[11]) && (int) $data_radio[11] === 1) {
        $msg =
            "🎵 Neuer Titel: <b>" .
            addslashes($artist) .
            "</b> - <b>" .
            addslashes($song1) .
            "</b>";
        if ($djName !== "Auto DJ") {
            $msg .= " <b>(mit DJ " . addslashes($djName) . ")</b>";
        }
        $sysColor =
            $_SESSION["etchat_" . $this->_prefix . "syscolor"] ?? "00ff02";
        $msgCss =
            "color:#" . $sysColor . ";font-weight:bold;font-style:normal;";
		$this->dbObj->sqlSet(
			"INSERT INTO {$this->_prefix}etchat_messages
			(etchat_user_fid, etchat_text, etchat_text_css, etchat_timestamp, etchat_fid_room, etchat_privat, etchat_user_ip)
			VALUES (1, ?, ?, ?, 1, 0, '127.0.0.1')",
			[$msg, $msgCss, $ts]
		);
    }
}

// ===============================
// Chat-Status setzen oder zurücksetzen
// ===============================

$statusImg = "status_onair";
$statusText = "On Air";

// Prüfen, ob Auto DJ ist

if ($radio_on_air == "1") {
    // Aktuell alle OnAir-Felder auslesen
    $currentOnAir = $this->dbObj->sqlGet("
    SELECT uo.etchat_onlineuser_fid, u.etchat_username
    FROM {$this->_prefix}etchat_useronline uo
    INNER JOIN {$this->_prefix}etchat_user u
        ON uo.etchat_onlineuser_fid = u.etchat_user_id
    WHERE uo.etchat_user_online_user_status_img = '$statusImg'
");

    // Letzten Stream-DJ aus der History auslesen
    $lastDj = $this->dbObj->sqlGet("
    SELECT etchat_dj_name
    FROM {$this->_prefix}etchat_radio_history
    ORDER BY etchat_played_at DESC
    LIMIT 1
");
    $lastDjName = $lastDj[0][0] ?? "";

    // === LOGIK FÜR ON-AIR ===
    if ($isAutoDJ) {
        // Auto DJ übernimmt: alle On-Air löschen
        if (!empty($currentOnAir)) {
            $this->dbObj->sqlSet("
            UPDATE {$this->_prefix}etchat_useronline
            SET etchat_user_online_user_status_img  = '',
                etchat_user_online_user_status_text = ''
            WHERE etchat_user_online_user_status_img = '$statusImg'
        ");
        }
    } else {
        // Moderatoren übernehmen: nur ändern, wenn sich Stream-DJ geändert hat
        if ($djName !== $lastDjName) {
            // Stream-DJ hat sich geändert: alte On-Air-Einträge löschen
            if (!empty($currentOnAir)) {
                $this->dbObj->sqlSet("
                UPDATE {$this->_prefix}etchat_useronline
                SET etchat_user_online_user_status_img  = '',
                    etchat_user_online_user_status_text = ''
                WHERE etchat_user_online_user_status_img = '$statusImg'
            ");
            }
        }

        // Stream-DJ auf On-Air setzen
        $user = $this->dbObj->sqlGet(
            "
        SELECT etchat_user_id
        FROM {$this->_prefix}etchat_user
        WHERE etchat_username = '" .
                addslashes($djName) .
                "'
          AND etchat_userprivilegien IN ('mod','admin')
        LIMIT 1
    "
        );
        if ($user && isset($user[0][0])) {
            $userId = (int) $user[0][0];
            $this->dbObj->sqlSet("
            UPDATE {$this->_prefix}etchat_useronline
            SET etchat_user_online_user_status_img  = '$statusImg',
                etchat_user_online_user_status_text = '$statusText'
            WHERE etchat_onlineuser_fid = $userId
        ");
        }
    }
}
}
// === AUSGABE IM RADIO-BLOCK ===
$isPrivileged = false;
if (!$isAutoDJ) {
    $check = $this->dbObj->sqlGet(
        "
        SELECT etchat_user_id
        FROM {$this->_prefix}etchat_user
        WHERE etchat_username = '" .
            addslashes($djName) .
            "'
          AND etchat_userprivilegien IN ('mod','admin')
        LIMIT 1
    "
    );
    $isPrivileged = $check && isset($check[0][0]);
}

echo htmlspecialchars($isPrivileged ? $djName : "Auto DJ");

$this->dbObj->close();
?>

</td>
</tr>
<tr style="height: 2px;">
<td style="width: 70px">Zuh&ouml;rer:</td>
<td style="width: 2px"></td>
<td><?php echo $listeners; ?> / <?php echo $max; ?></td>

<td rowspan="2" style=" text-align: center;">
<?php

if (!$isPrivileged) {
    echo '<img src="../avatar/autodj.jpg" width="75" height="75" alt="autodj">';
} else {
    $name = $djName;
    $result = "mod_ohne_pic.png";
    $avatarDir = "../avatar/";
    $extensions = ["jpg", "jpeg", "gif", "png"];

    foreach ($extensions as $ext) {
        $files = glob(
            $avatarDir . $name . "-*." . $ext,
            GLOB_BRACE | GLOB_NOCHECK
        );
        if (!empty($files)) {
            foreach ($files as $file) {
                if (is_file($file)) {
                    $result = basename($file);
                    break 2;
                }
            }
        }
    }

    echo '<img src="../avatar/' .
        $result .
        '" width="75" height="75" alt="' .
        htmlspecialchars($name) .
        '">';
}
?>
</td>
</tr>
<tr style="height: 2px;">
<td style="width: 70px">Bitrate:</td>
<td style="width: 2px"></td>
<td><?php echo htmlspecialchars($rbit1 ?? "0"); ?> kb/s</td>
</tr>
<tr style="height: 2px;">
<td style="width: 70px">Titel:</td>
<td style="width: 2px"></td>
<td colspan="2">
<marquee scrollamount="10" scrolldelay="300">
<?php
echo htmlspecialchars($artist);
echo ' - ';
echo htmlspecialchars($song1);
?>
</marquee></td>
</tr>
</tbody>
</table>
</div>

<?php
}
if ($radio_player == "1") { ?>
<div class="player_play" id="player">
  <button id="playPauseBtn">&#9654;</button>
  <div class="title">
    <div class="scroll-text" id="streamTitle">Drücke Play...</div>
  </div>
<div class="time" id="timeDisplay">00:00</div>
  <div class="volume-container" id="volumeContainer">
    <button class="volume" id="muteBtn">&#128266;</button>
    <div class="volume-slider above" id="volumeSlider">
      <input type="range" id="volumeControl" min="0" max="1" step="0.01" value="0.1">
    </div>
  </div>
</div>

<audio id="audio" preload="none" data-stream="<?php echo htmlspecialchars(
    $stream1
); ?>"></audio>

<script src="player.js"></script>

<?php }
    }
}
new RadioBox();
?>
</body>
</html>