/**
 * VideoKonverter TV - AVPlay Bridge v1.0
 * Abstraktionsschicht fuer Samsung AVPlay API (Tizen WebApps).
 * Ermoeglicht Direct-Play von MKV/WebM/MP4 mit Hardware-Decodern.
 *
 * AVPlay kann: H.264, HEVC, AV1, VP9, EAC3, AC3, AAC, Opus
 * AVPlay kann NICHT: DTS (seit Samsung 2022 entfernt)
 *
 * Wird nur geladen wenn Tizen-Umgebung erkannt wird.
 */

const AVPlayBridge = {
    available: false,
    _playing: false,
    _duration: 0,
    _listener: null,
    _displayEl: null,     // <object> Element fuer AVPlay-Rendering
    _timeUpdateId: null,  // Interval fuer periodische Zeit-Updates

    /**
     * Initialisierung: Prueft ob AVPlay API verfuegbar ist
     * @returns {boolean} true wenn AVPlay nutzbar
     */
    init() {
        try {
            this.available = typeof webapis !== "undefined"
                && typeof webapis.avplay !== "undefined";
        } catch (e) {
            this.available = false;
        }
        if (this.available) {
            console.info("[AVPlay] API verfuegbar");
        }
        return this.available;
    },

    /**
     * Prueft ob ein Video direkt abgespielt werden kann (ohne Transcoding)
     * @param {Object} videoInfo - Video-Infos vom Server
     * @returns {boolean} true wenn Direct-Play moeglich
     */
    canPlay(videoInfo) {
        if (!this.available) return false;

        // Video-Codec pruefen
        const vc = (videoInfo.video_codec_normalized || "").toLowerCase();
        const supportedVideo = ["h264", "hevc", "av1", "vp9"];
        if (!supportedVideo.includes(vc)) {
            console.info(`[AVPlay] Video-Codec '${vc}' nicht unterstuetzt`);
            return false;
        }

        // Container pruefen
        const container = (videoInfo.container || "").toLowerCase();
        const supportedContainers = ["mkv", "matroska", "mp4", "webm", "avi", "ts"];
        if (container && !supportedContainers.some(c => container.includes(c))) {
            console.info(`[AVPlay] Container '${container}' nicht unterstuetzt`);
            return false;
        }

        // Audio-Codecs pruefen - DTS ist nicht unterstuetzt
        const audioCodecs = videoInfo.audio_codecs || [];
        const unsupported = ["dts", "dca", "dts_hd", "dts-hd", "truehd"];
        const hasUnsupported = audioCodecs.some(
            ac => unsupported.includes(ac.toLowerCase())
        );
        if (hasUnsupported) {
            console.info("[AVPlay] DTS-Audio erkannt -> kein Direct-Play");
            return false;
        }

        console.info(`[AVPlay] Direct-Play moeglich: ${vc}/${container}`);
        return true;
    },

    /**
     * Video abspielen via AVPlay
     * @param {string} url - Direct-Stream-URL
     * @param {Object} opts - {seekMs, onTimeUpdate, onComplete, onError, onBuffering}
     */
    play(url, opts = {}) {
        if (!this.available) return false;

        try {
            // Vorherige Session bereinigen
            this.stop();

            // Display-Element setzen
            this._displayEl = document.getElementById("avplayer");
            if (this._displayEl) {
                this._displayEl.style.display = "block";
            }

            // AVPlay oeffnen
            webapis.avplay.open(url);

            // Display-Bereich setzen (Vollbild)
            webapis.avplay.setDisplayRect(
                0, 0, window.innerWidth, window.innerHeight
            );

            // Event-Listener registrieren
            this._listener = opts;
            webapis.avplay.setListener({
                onbufferingstart: () => {
                    console.debug("[AVPlay] Buffering gestartet");
                    if (this._listener && this._listener.onBuffering) {
                        this._listener.onBuffering(true);
                    }
                },
                onbufferingcomplete: () => {
                    console.debug("[AVPlay] Buffering abgeschlossen");
                    if (this._listener && this._listener.onBuffering) {
                        this._listener.onBuffering(false);
                    }
                },
                oncurrentplaytime: (ms) => {
                    // Wird von AVPlay periodisch aufgerufen
                    if (this._listener && this._listener.onTimeUpdate) {
                        this._listener.onTimeUpdate(ms);
                    }
                },
                onstreamcompleted: () => {
                    console.info("[AVPlay] Wiedergabe abgeschlossen");
                    this._playing = false;
                    if (this._listener && this._listener.onComplete) {
                        this._listener.onComplete();
                    }
                },
                onerror: (eventType) => {
                    console.error("[AVPlay] Fehler:", eventType);
                    this._playing = false;
                    if (this._listener && this._listener.onError) {
                        this._listener.onError(eventType);
                    }
                },
                onevent: (eventType, eventData) => {
                    console.debug("[AVPlay] Event:", eventType, eventData);
                },
                onsubtitlechange: (duration, text, dataSize, jsonData) => {
                    // Untertitel-Events (optional)
                    console.debug("[AVPlay] Subtitle:", text);
                },
            });

            // Async vorbereiten und starten
            webapis.avplay.prepareAsync(
                () => {
                    // Erfolg: Wiedergabe starten
                    this._duration = webapis.avplay.getDuration();
                    console.info(`[AVPlay] Bereit, Dauer: ${this._duration}ms`);

                    // Seeking vor dem Start
                    if (opts.seekMs && opts.seekMs > 0) {
                        webapis.avplay.seekTo(opts.seekMs,
                            () => {
                                console.info(`[AVPlay] Seek zu ${opts.seekMs}ms`);
                                webapis.avplay.play();
                                this._playing = true;
                                this._startTimeUpdates();
                            },
                            (e) => {
                                console.warn("[AVPlay] Seek fehlgeschlagen:", e);
                                webapis.avplay.play();
                                this._playing = true;
                                this._startTimeUpdates();
                            }
                        );
                    } else {
                        webapis.avplay.play();
                        this._playing = true;
                        this._startTimeUpdates();
                    }

                    // Buffering-Ende signalisieren
                    if (this._listener && this._listener.onBuffering) {
                        this._listener.onBuffering(false);
                    }
                    if (this._listener && this._listener.onReady) {
                        this._listener.onReady();
                    }
                },
                (error) => {
                    console.error("[AVPlay] Prepare fehlgeschlagen:", error);
                    if (this._listener && this._listener.onError) {
                        this._listener.onError(error);
                    }
                }
            );

            return true;
        } catch (e) {
            console.error("[AVPlay] Fehler beim Starten:", e);
            if (this._listener && this._listener.onError) {
                this._listener.onError(e.message || e);
            }
            return false;
        }
    },

    /**
     * Pause/Resume umschalten
     */
    togglePlay() {
        if (!this.available) return;
        try {
            const state = webapis.avplay.getState();
            if (state === "PLAYING") {
                webapis.avplay.pause();
                this._playing = false;
            } else if (state === "PAUSED" || state === "READY") {
                webapis.avplay.play();
                this._playing = true;
            }
        } catch (e) {
            console.error("[AVPlay] togglePlay Fehler:", e);
        }
    },

    pause() {
        if (!this.available) return;
        try {
            if (this._playing) {
                webapis.avplay.pause();
                this._playing = false;
            }
        } catch (e) {
            console.error("[AVPlay] pause Fehler:", e);
        }
    },

    resume() {
        if (!this.available) return;
        try {
            webapis.avplay.play();
            this._playing = true;
        } catch (e) {
            console.error("[AVPlay] resume Fehler:", e);
        }
    },

    /**
     * Seeking zu Position in Millisekunden
     * @param {number} positionMs - Zielposition in ms
     * @param {function} onSuccess - Callback bei Erfolg
     * @param {function} onError - Callback bei Fehler
     */
    seek(positionMs, onSuccess, onError) {
        if (!this.available) return;
        try {
            webapis.avplay.seekTo(
                Math.max(0, Math.floor(positionMs)),
                () => {
                    console.debug(`[AVPlay] Seek zu ${positionMs}ms`);
                    if (onSuccess) onSuccess();
                },
                (e) => {
                    console.warn("[AVPlay] Seek Fehler:", e);
                    if (onError) onError(e);
                }
            );
        } catch (e) {
            console.error("[AVPlay] seek Fehler:", e);
            if (onError) onError(e);
        }
    },

    /**
     * Wiedergabe stoppen und AVPlay bereinigen
     */
    stop() {
        this._stopTimeUpdates();
        this._playing = false;
        try {
            const state = webapis.avplay.getState();
            if (state !== "IDLE" && state !== "NONE") {
                webapis.avplay.stop();
            }
            webapis.avplay.close();
        } catch (e) {
            // Ignorieren wenn bereits gestoppt
        }
        if (this._displayEl) {
            this._displayEl.style.display = "none";
        }
    },

    /**
     * Aktuelle Wiedergabeposition in Millisekunden
     * @returns {number} Position in ms
     */
    getCurrentTime() {
        if (!this.available) return 0;
        try {
            return webapis.avplay.getCurrentTime();
        } catch (e) {
            return 0;
        }
    },

    /**
     * Gesamtdauer in Millisekunden
     * @returns {number} Dauer in ms
     */
    getDuration() {
        if (!this.available) return 0;
        try {
            return this._duration || webapis.avplay.getDuration();
        } catch (e) {
            return 0;
        }
    },

    /**
     * Prueft ob gerade abgespielt wird
     * @returns {boolean}
     */
    isPlaying() {
        return this._playing;
    },

    /**
     * Periodische Zeit-Updates starten (fuer Progress-Bar)
     */
    _startTimeUpdates() {
        this._stopTimeUpdates();
        this._timeUpdateId = setInterval(() => {
            if (this._playing && this._listener && this._listener.onTimeUpdate) {
                this._listener.onTimeUpdate(this.getCurrentTime());
            }
        }, 500);
    },

    _stopTimeUpdates() {
        if (this._timeUpdateId) {
            clearInterval(this._timeUpdateId);
            this._timeUpdateId = null;
        }
    },
};
