<?php

declare(strict_types=1);

namespace App\Framework\Http;

use App\Framework\DateTime\SystemTimer;
use App\Framework\DateTime\Timer;
use App\Framework\Http\Emitter\AdaptiveStreamEmitter;
use App\Framework\Http\Emitter\HttpEmitter;
use App\Framework\Http\Emitter\SseEmitter;
use App\Framework\Http\Emitter\StreamEmitter;
use App\Framework\Http\Emitter\WebSocketEmitter;

final readonly class ResponseEmitter
{
    public function __construct(
        private readonly ?Timer $timer = null
    ) {
    }

    public function emit(Response $response, int $chunkSize = 8192): void
    {
        $responseType = new ResponseTypeDetector()->detect($response);

        #dd($responseType);

        match ($responseType) {
            ResponseType::SSE => $this->emitSseResponse($response),
            ResponseType::WEBSOCKET => $this->emitWebSocketResponse($response),
            ResponseType::MEDIA_STREAM => $this->emitStreamResponse($response),
            ResponseType::HLS, ResponseType::DASH => $this->emitAdaptiveStreamResponse($response),
            default => $this->emitHttpResponse($response),
        };

        /*if (is_string($body)) {
            // Wenn der Body ein String ist, direkt ausgeben.
            echo $body;
        } elseif (is_resource($body) && get_resource_type($body) === 'stream') {
            // Wenn der Body eine Ressource (Stream) ist, in Chunks lesen und senden.
            // Dies ist speichereffizient für grosse Dateien.
            while (!feof($body)) {
                echo fread($body, $chunkSize);
                // Ggf. Output-Buffer leeren, um den Chunk sofort an den Client zu senden.
                if (ob_get_level() > 0) {
                    ob_flush();
                }
                flush();
            }
            fclose($body);
        }*/
    }

    /**
     * Sendet eine SSE-Response mit Streaming-Unterstützung
     */
    private function emitSseResponse(Response $response): void
    {
        new SseEmitter($this->timer ?? new SystemTimer())->emit($response);
    }

    /**
     * Sendet eine WebSocket-Response und startet die WebSocket-Verbindung
     */
    private function emitWebSocketResponse(Response $response): void
    {
        new WebsocketEmitter()->emit($response);
    }

    private function emitHttpResponse(Response $response): void
    {
        new HttpEmitter()->emit($response);
    }

    private function emitStreamResponse(Response $response): void
    {
        new StreamEmitter()->emit($response);
    }

    private function emitAdaptiveStreamResponse(Response $response): void
    {
        new AdaptiveStreamEmitter()->emit($response);
    }
}
