/**
 * VideoKonverter TV - VKNative Bridge v2.0
 * Einheitliches Interface fuer native Video-Player auf allen Plattformen.
 *
 * Modus 1 - Tizen iframe (postMessage):
 *   Laeuft im iframe auf Tizen-TV. Kommuniziert per postMessage mit dem
 *   Parent-Frame (tizen-app/index.html), der AVPlay steuert.
 *   webapis.avplay ist im iframe NICHT verfuegbar.
 *
 * Modus 2 - Tizen direkt (legacy, falls webapis doch verfuegbar):
 *   Direkter Zugriff auf webapis.avplay (Fallback).
 *
 * Android: window.VKNative wird von der Kotlin-App per @JavascriptInterface injiziert.
 *          Diese Bridge erkennt das und ueberspringt sich selbst.
 *
 * Interface: window.VKNative
 * Callbacks: window._vkOnReady, _vkOnTimeUpdate, _vkOnComplete,
 *            _vkOnError, _vkOnBuffering, _vkOnPlayStateChanged
 */

(function() {
    "use strict";

    // Bereits von Android injiziert? Dann nichts tun
    if (window.VKNative) {
        console.info("[VKNative] Bridge bereits vorhanden (platform: " + window.VKNative.platform + ")");
        return;
    }

    // Tizen-Erkennung (User-Agent, auch im iframe gueltig)
    var isTizen = /Tizen/i.test(navigator.userAgent);
    if (!isTizen) {
        // Kein Tizen -> Bridge nicht noetig (Desktop/Handy nutzt HLS)
        return;
    }

    // Im iframe? (Parent-Frame hat AVPlay)
    var inIframe = (window.parent !== window);

    // AVPlay direkt verfuegbar? (nur im Parent-Frame oder bei altem Redirect-Ansatz)
    var avplayDirect = false;
    try {
        avplayDirect = typeof webapis !== "undefined" && typeof webapis.avplay !== "undefined";
    } catch (e) {
        avplayDirect = false;
    }

    // === MODUS 1: iframe + postMessage ===
    if (inIframe && !avplayDirect) {
        console.info("[VKNative] Tizen iframe-Modus: postMessage Bridge wird initialisiert");

        var _parentReady = false;
        var _videoCodecs = ["h264", "hevc", "av1", "vp9"];
        var _audioCodecs = ["aac", "opus", "ac3", "eac3", "flac", "mp3", "vorbis", "pcm"];
        var _playing = false;
        var _currentTimeMs = 0;
        var _durationMs = 0;

        // Unterstuetzte/Nicht-unterstuetzte Codecs (fuer canDirectPlay)
        var UNSUPPORTED_AUDIO = ["dts", "dca", "dts_hd", "dts-hd", "truehd"];
        var SUPPORTED_CONTAINERS = ["mkv", "matroska", "mp4", "webm", "avi", "ts"];

        // Events vom Parent empfangen
        window.addEventListener("message", function(event) {
            // Nur Nachrichten vom Parent akzeptieren
            if (event.source !== window.parent) return;

            var data = event.data;
            if (!data || !data.type) return;

            switch (data.type) {
                case "vknative_ready":
                    // Parent bestaetigt: AVPlay ist verfuegbar
                    _parentReady = true;
                    if (data.videoCodecs) _videoCodecs = data.videoCodecs;
                    if (data.audioCodecs) _audioCodecs = data.audioCodecs;
                    console.info("[VKNative] Parent bereit, Codecs: " +
                        _videoCodecs.join(",") + " / " + _audioCodecs.join(","));
                    break;

                case "vknative_event":
                    _handleParentEvent(data.event, data.detail || {});
                    break;

                case "vknative_stats":
                    // AVPlay-Stats vom Parent (Antwort auf requestStats)
                    if (data.stats) window.VKNative._lastStats = data.stats;
                    break;

                case "vknative_keyevent":
                    // Key-Event vom Parent weitergeleitet -> als KeyboardEvent dispatchen
                    if (data.keyCode) {
                        // keyCode -> key-Name Mapping (KeyboardEvent setzt key nicht automatisch)
                        var keyNameMap = {
                            13: "Enter", 37: "ArrowLeft", 38: "ArrowUp",
                            39: "ArrowRight", 40: "ArrowDown", 27: "Escape",
                            8: "Backspace", 32: " ",
                            // Samsung-spezifische keyCodes (Media + Farbtasten)
                            10009: "Escape", 10182: "Escape",
                            415: "Play", 19: "Pause", 413: "Stop",
                            417: "FastForward", 412: "Rewind", 10252: "Play",
                            403: "ColorRed", 404: "ColorGreen",
                            405: "ColorYellow", 406: "ColorBlue",
                        };
                        var keyEvt = new KeyboardEvent("keydown", {
                            keyCode: data.keyCode,
                            which: data.keyCode,
                            key: keyNameMap[data.keyCode] || "",
                            bubbles: true,
                        });
                        document.dispatchEvent(keyEvt);
                    }
                    break;
            }
        });

        // Events vom Parent an die Callbacks weiterleiten
        function _handleParentEvent(event, detail) {
            switch (event) {
                case "ready":
                    _playing = true;
                    if (window._vkOnReady) window._vkOnReady();
                    break;

                case "timeupdate":
                    _currentTimeMs = detail.ms || 0;
                    if (window._vkOnTimeUpdate) window._vkOnTimeUpdate(_currentTimeMs);
                    break;

                case "complete":
                    _playing = false;
                    if (window._vkOnComplete) window._vkOnComplete();
                    break;

                case "error":
                    _playing = false;
                    if (window._vkOnError) window._vkOnError(detail.msg || "Unbekannter Fehler");
                    break;

                case "buffering":
                    if (window._vkOnBuffering) window._vkOnBuffering(detail.buffering);
                    break;

                case "playstatechanged":
                    _playing = !!detail.playing;
                    if (window._vkOnPlayStateChanged) window._vkOnPlayStateChanged(_playing);
                    break;

                case "stopped":
                    _playing = false;
                    _currentTimeMs = 0;
                    if (window._vkOnPlayStateChanged) window._vkOnPlayStateChanged(false);
                    // Zurueck-Navigation ausloesen (Return-Taste auf Fernbedienung)
                    if (window._vkOnStopped) window._vkOnStopped();
                    break;

                case "duration":
                    _durationMs = detail.ms || 0;
                    break;
            }
        }

        // Nachricht an Parent senden
        function _callParent(method, args) {
            window.parent.postMessage({
                type: "vknative_call",
                method: method,
                args: args || [],
            }, "*");
        }

        // Probe senden: "Bist du bereit?"
        function _probeParent() {
            window.parent.postMessage({ type: "vknative_probe" }, "*");
        }

        // === VKNative Interface (postMessage-Modus) ===
        window.VKNative = {
            platform: "tizen",
            version: "2.0.0",

            getSupportedVideoCodecs: function() {
                return _videoCodecs.slice();
            },

            getSupportedAudioCodecs: function() {
                return _audioCodecs.slice();
            },

            canDirectPlay: function(videoInfo) {
                // Video-Codec pruefen
                var vc = (videoInfo.video_codec_normalized || "").toLowerCase();
                if (_videoCodecs.indexOf(vc) === -1) {
                    console.info("[VKNative] Video-Codec '" + vc + "' nicht unterstuetzt");
                    return false;
                }

                // Container pruefen
                var container = (videoInfo.container || "").toLowerCase();
                if (container) {
                    var containerOk = false;
                    for (var i = 0; i < SUPPORTED_CONTAINERS.length; i++) {
                        if (container.indexOf(SUPPORTED_CONTAINERS[i]) !== -1) {
                            containerOk = true;
                            break;
                        }
                    }
                    if (!containerOk) {
                        console.info("[VKNative] Container '" + container + "' nicht unterstuetzt");
                        return false;
                    }
                }

                // Audio-Codecs pruefen - DTS/TrueHD blockieren
                var audioCodecs = videoInfo.audio_codecs || [];
                for (var j = 0; j < audioCodecs.length; j++) {
                    var ac = audioCodecs[j].toLowerCase();
                    if (UNSUPPORTED_AUDIO.indexOf(ac) !== -1) {
                        console.info("[VKNative] Audio-Codec '" + ac + "' nicht unterstuetzt -> kein Direct-Play");
                        return false;
                    }
                }

                // Tizen AVPlay: Opus mit >2 Kanaelen hat Tonausfaelle -> HLS Fallback
                var audioTracks = videoInfo.audio_tracks || [];
                for (var k = 0; k < audioTracks.length; k++) {
                    var track = audioTracks[k];
                    var trackCodec = (track.codec || "").toLowerCase();
                    var trackChannels = track.channels || 2;
                    if (trackCodec === "opus" && trackChannels > 2) {
                        console.info("[VKNative] Opus " + trackChannels + "ch auf Tizen -> HLS Fallback (Tonausfaelle bei AVPlay)");
                        return false;
                    }
                }

                console.info("[VKNative] Direct-Play moeglich: " + vc + "/" + container);
                return true;
            },

            play: function(url, videoInfo, opts) {
                console.info("[VKNative] play() per postMessage: " + url);
                _callParent("play", [url, videoInfo, opts]);
                return true;
            },

            togglePlay: function() {
                _callParent("togglePlay");
            },

            pause: function() {
                _callParent("pause");
            },

            resume: function() {
                _callParent("resume");
            },

            seek: function(positionMs) {
                _callParent("seek", [positionMs]);
            },

            getCurrentTime: function() {
                // Letzte bekannte Position (wird per timeupdate-Event aktualisiert)
                return _currentTimeMs;
            },

            getDuration: function() {
                return _durationMs;
            },

            isPlaying: function() {
                return _playing;
            },

            stop: function() {
                _playing = false;
                _currentTimeMs = 0;
                _callParent("stop");
            },

            /**
             * HLS-Stream ueber AVPlay abspielen (Fallback fuer Opus-Surround etc.)
             * AVPlay spielt HLS nativ inkl. AAC 5.1 Surround.
             */
            playHLS: function(playlistUrl, opts) {
                console.info("[VKNative] playHLS() per postMessage: " + playlistUrl);
                _callParent("playHLS", [playlistUrl, opts]);
                return true;
            },

            setAudioTrack: function(index) {
                console.info("[VKNative] Audio-Track-Wechsel auf Tizen nicht moeglich");
                return false;
            },

            setSubtitleTrack: function(index) {
                return false;
            },

            setPlaybackSpeed: function(speed) {
                _callParent("setPlaybackSpeed", [speed]);
                return true;
            },

            /** AVPlay-Stats vom Parent abfragen (async, Ergebnis in _lastStats) */
            requestStats: function() {
                window.parent.postMessage({ type: "vknative_get_stats" }, "*");
            },
            _lastStats: null,
        };

        // Parent proben (wiederholt, falls Parent noch nicht bereit)
        _probeParent();
        var _probeRetries = 0;
        var _probeInterval = setInterval(function() {
            if (_parentReady || _probeRetries > 20) {
                clearInterval(_probeInterval);
                if (!_parentReady) {
                    console.warn("[VKNative] Parent hat nach 10s nicht geantwortet");
                }
                return;
            }
            _probeRetries++;
            _probeParent();
        }, 500);

        console.info("[VKNative] Tizen postMessage Bridge bereit");
        return;
    }

    // === MODUS 2: Direkter AVPlay-Zugriff (Legacy-Fallback) ===
    if (avplayDirect) {
        console.info("[VKNative] Tizen Direct-AVPlay Bridge wird initialisiert");

        var _playing2 = false;
        var _duration2 = 0;
        var _displayEl2 = null;
        var _timeUpdateId2 = null;

        var SUPPORTED_VIDEO = ["h264", "hevc", "av1", "vp9"];
        var SUPPORTED_AUDIO = ["aac", "opus", "ac3", "eac3", "flac", "mp3", "vorbis", "pcm"];
        var UNSUPPORTED_AUDIO2 = ["dts", "dca", "dts_hd", "dts-hd", "truehd"];
        var SUPPORTED_CONTAINERS2 = ["mkv", "matroska", "mp4", "webm", "avi", "ts"];

        function _startTimeUpdates2() {
            _stopTimeUpdates2();
            _timeUpdateId2 = setInterval(function() {
                if (_playing2 && window._vkOnTimeUpdate) {
                    try {
                        window._vkOnTimeUpdate(webapis.avplay.getCurrentTime());
                    } catch (e) {}
                }
            }, 500);
        }

        function _stopTimeUpdates2() {
            if (_timeUpdateId2) {
                clearInterval(_timeUpdateId2);
                _timeUpdateId2 = null;
            }
        }

        function _resolveUrl2(url) {
            if (url.indexOf("://") !== -1) return url;
            return window.location.origin + url;
        }

        window.VKNative = {
            platform: "tizen",
            version: "2.0.0",

            getSupportedVideoCodecs: function() { return SUPPORTED_VIDEO.slice(); },
            getSupportedAudioCodecs: function() { return SUPPORTED_AUDIO.slice(); },

            canDirectPlay: function(videoInfo) {
                var vc = (videoInfo.video_codec_normalized || "").toLowerCase();
                if (SUPPORTED_VIDEO.indexOf(vc) === -1) return false;
                var container = (videoInfo.container || "").toLowerCase();
                if (container) {
                    var ok = false;
                    for (var i = 0; i < SUPPORTED_CONTAINERS2.length; i++) {
                        if (container.indexOf(SUPPORTED_CONTAINERS2[i]) !== -1) { ok = true; break; }
                    }
                    if (!ok) return false;
                }
                var ac2 = videoInfo.audio_codecs || [];
                for (var j = 0; j < ac2.length; j++) {
                    if (UNSUPPORTED_AUDIO2.indexOf(ac2[j].toLowerCase()) !== -1) return false;
                }
                // Tizen AVPlay: Opus mit >2 Kanaelen hat Tonausfaelle -> HLS Fallback
                var audioTracks = videoInfo.audio_tracks || [];
                for (var k = 0; k < audioTracks.length; k++) {
                    var trk = audioTracks[k];
                    var trkCodec = (trk.codec || "").toLowerCase();
                    var trkCh = trk.channels || 2;
                    if (trkCodec === "opus" && trkCh > 2) {
                        console.info("[VKNative] Opus " + trkCh + "ch auf Tizen -> HLS Fallback");
                        return false;
                    }
                }
                return true;
            },

            play: function(url, videoInfo, opts) {
                opts = opts || {};
                var seekMs = opts.seekMs || 0;
                var fullUrl = _resolveUrl2(url);

                try {
                    this.stop();
                    _displayEl2 = document.getElementById("avplayer");
                    if (_displayEl2) _displayEl2.style.display = "block";
                    var videoEl = document.getElementById("player-video");
                    if (videoEl) videoEl.style.display = "none";

                    webapis.avplay.open(fullUrl);
                    webapis.avplay.setDisplayRect(0, 0, window.innerWidth, window.innerHeight);

                    webapis.avplay.setListener({
                        onbufferingstart: function() { if (window._vkOnBuffering) window._vkOnBuffering(true); },
                        onbufferingcomplete: function() { if (window._vkOnBuffering) window._vkOnBuffering(false); },
                        oncurrentplaytime: function(ms) { if (window._vkOnTimeUpdate) window._vkOnTimeUpdate(ms); },
                        onstreamcompleted: function() {
                            _playing2 = false;
                            if (window._vkOnPlayStateChanged) window._vkOnPlayStateChanged(false);
                            if (window._vkOnComplete) window._vkOnComplete();
                        },
                        onerror: function(evt) {
                            _playing2 = false;
                            if (window._vkOnError) window._vkOnError(String(evt));
                        },
                        onevent: function() {},
                        onsubtitlechange: function() {},
                    });

                    function _start() {
                        try {
                            webapis.avplay.play();
                            _playing2 = true;
                            _startTimeUpdates2();
                            if (window._vkOnPlayStateChanged) window._vkOnPlayStateChanged(true);
                            if (window._vkOnReady) window._vkOnReady();
                        } catch (e) {
                            _playing2 = false;
                            if (window._vkOnError) window._vkOnError(e.message || String(e));
                        }
                    }

                    webapis.avplay.prepareAsync(
                        function() {
                            try { _duration2 = webapis.avplay.getDuration(); } catch (e) { _duration2 = 0; }
                            if (seekMs > 0) {
                                try {
                                    webapis.avplay.seekTo(seekMs, function() { _start(); }, function() { _start(); });
                                } catch (e) { _start(); }
                            } else {
                                _start();
                            }
                        },
                        function(err) { if (window._vkOnError) window._vkOnError(String(err)); }
                    );
                    return true;
                } catch (e) {
                    if (window._vkOnError) window._vkOnError(e.message || String(e));
                    return false;
                }
            },

            togglePlay: function() {
                try {
                    var state = webapis.avplay.getState();
                    if (state === "PLAYING") {
                        webapis.avplay.pause(); _playing2 = false;
                        if (window._vkOnPlayStateChanged) window._vkOnPlayStateChanged(false);
                    } else if (state === "PAUSED" || state === "READY") {
                        webapis.avplay.play(); _playing2 = true;
                        if (window._vkOnPlayStateChanged) window._vkOnPlayStateChanged(true);
                    }
                } catch (e) {}
            },

            pause: function() {
                try { if (_playing2) { webapis.avplay.pause(); _playing2 = false; if (window._vkOnPlayStateChanged) window._vkOnPlayStateChanged(false); } } catch (e) {}
            },
            resume: function() {
                try { webapis.avplay.play(); _playing2 = true; if (window._vkOnPlayStateChanged) window._vkOnPlayStateChanged(true); } catch (e) {}
            },
            seek: function(ms) {
                try { webapis.avplay.seekTo(Math.max(0, Math.floor(ms)), function(){}, function(){}); } catch (e) {}
            },
            getCurrentTime: function() { try { return webapis.avplay.getCurrentTime(); } catch (e) { return 0; } },
            getDuration: function() { try { return _duration2 || webapis.avplay.getDuration(); } catch (e) { return 0; } },
            isPlaying: function() { return _playing2; },
            stop: function() {
                _stopTimeUpdates2(); _playing2 = false;
                try { var s = webapis.avplay.getState(); if (s !== "IDLE" && s !== "NONE") webapis.avplay.stop(); webapis.avplay.close(); } catch (e) {}
                if (_displayEl2) { _displayEl2.style.display = "none"; _displayEl2 = null; }
                var v = document.getElementById("player-video"); if (v) v.style.display = "";
            },
            /** HLS ueber AVPlay abspielen (Fallback fuer Opus-Surround) */
            playHLS: function(playlistUrl, opts) {
                opts = opts || {};
                var seekMs = opts.seekMs || 0;
                var fullUrl = _resolveUrl2(playlistUrl);
                try {
                    this.stop();
                    _displayEl2 = document.getElementById("avplayer");
                    if (_displayEl2) _displayEl2.style.display = "block";
                    var videoEl = document.getElementById("player-video");
                    if (videoEl) videoEl.style.display = "none";

                    webapis.avplay.open(fullUrl);
                    webapis.avplay.setDisplayRect(0, 0, window.innerWidth, window.innerHeight);

                    webapis.avplay.setListener({
                        onbufferingstart: function() { if (window._vkOnBuffering) window._vkOnBuffering(true); },
                        onbufferingcomplete: function() { if (window._vkOnBuffering) window._vkOnBuffering(false); },
                        oncurrentplaytime: function(ms) { if (window._vkOnTimeUpdate) window._vkOnTimeUpdate(ms); },
                        onstreamcompleted: function() {
                            _playing2 = false;
                            if (window._vkOnPlayStateChanged) window._vkOnPlayStateChanged(false);
                            if (window._vkOnComplete) window._vkOnComplete();
                        },
                        onerror: function(evt) {
                            _playing2 = false;
                            if (window._vkOnError) window._vkOnError(String(evt));
                        },
                        onevent: function() {},
                        onsubtitlechange: function() {},
                    });

                    webapis.avplay.prepareAsync(
                        function() {
                            try { _duration2 = webapis.avplay.getDuration(); } catch (e) { _duration2 = 0; }
                            try {
                                webapis.avplay.play();
                                _playing2 = true;
                                _startTimeUpdates2();
                                if (window._vkOnPlayStateChanged) window._vkOnPlayStateChanged(true);
                                if (window._vkOnReady) window._vkOnReady();
                            } catch (e) {
                                _playing2 = false;
                                if (window._vkOnError) window._vkOnError(e.message || String(e));
                            }
                        },
                        function(err) { if (window._vkOnError) window._vkOnError(String(err)); }
                    );
                    return true;
                } catch (e) {
                    if (window._vkOnError) window._vkOnError(e.message || String(e));
                    return false;
                }
            },
            setAudioTrack: function() { return false; },
            setSubtitleTrack: function() { return false; },
            setPlaybackSpeed: function(speed) {
                try { webapis.avplay.setSpeed(speed); return true; } catch (e) { return false; }
            },
        };

        console.info("[VKNative] Tizen Direct-AVPlay Bridge bereit");
        return;
    }

    // Weder iframe noch AVPlay verfuegbar -> kein VKNative
    console.warn("[VKNative] Tizen erkannt, aber weder iframe-Parent noch webapis.avplay verfuegbar");
})();
