var currentVencCodec = 96; // 96=H.264, 265=H.265

function browserSupportsH265WebRTC() {
    var ua = navigator.userAgent;
    if (/Chrome/i.test(ua) && !/Edg\//i.test(ua)) return true;
    if (/Safari/i.test(ua) && !/Chrome/i.test(ua)) return true;
    return false;
}

function DisplayWebRTC(){
    // 根据当前码流配置判断是否需要显示 WebRTC 预览（H.264/H.265 且 WebRTC 预览开启，且浏览器支持对应编码）
    $.ajax({
        type: "GET",
        url: "/get_output?input=" + input + "&output=" + output,
        dataType: "xml",
        cache: false,
        success: function (data) {
            var venc_codec = $(data).find("venc_codec").text();
            var webrtcStatus = $(data).find("webrtc_p2p_http_enable").text();
            var canPreview = (venc_codec == 96) || (venc_codec == 265 && browserSupportsH265WebRTC());

            if (canPreview && webrtcStatus == 1) {
                currentVencCodec = parseInt(venc_codec);
                $("#osdWebRTCBox_card").removeClass("display_off");
                connect();
            } else {
                webrtcWant = false;   // 主动隐藏:停止任何待执行的重连
                cancelReconnect();
                $("#osdWebRTCBox_card").addClass("display_off");
                if (pc) {
                    pc.close();
                    pc = null;
                }
                var videoEl = document.getElementById("video");
                if (videoEl) {
                    videoEl.srcObject = null;
                }
            }
        }
    });
}

function InitOsdWebRTCContent(){
    var $container = $('.page-body .container-xl');
    if (!$container.length) return;
    if ($('#osdWebRTCBox_card').length) return;

    var title = 'osd.webrtcPreview';
    if (typeof i18n !== 'undefined' && typeof i18n.t === 'function') {
        title = i18n.t('osd.webrtcPreview');
    }

    var content = '';
    content += "<div id='osdWebRTCBox_card' class='card mb-3 display_off'>";
    content += "  <div class='card-header'>";
    content += "    <h3 class='card-title' data-i18n='osd.webrtcPreview'>" + title + "</h3>";
    content += "  </div>";
    content += "  <div class='card-body'>";
    content += "    <div id='osdWebRTCBox_div' class='video-container'>";
    content += "      <video id='video' autoplay playsinline muted></video>";
    content += "    </div>";
    content += "  </div>";
    content += "</div>";

    $container.prepend(content);

    // 只翻译新插入的卡片，避免重复初始化整页语言选择器
    var card = document.getElementById('osdWebRTCBox_card');
    if (card && typeof i18n !== 'undefined') {
        if (typeof i18n.translate === 'function') {
            i18n.translate(card);
        } else if (typeof i18n.init === 'function') {
            i18n.init();
        }
    }
}

let pc = null;

// 自动重连状态
let reconnectTimer = null;   // 待执行的重连
let disconnectTimer = null;  // disconnected 自愈观察期
const RECONNECT_STEPS = [1000, 3000, 5000, 10000];  // 重连退避序列(ms),用尽后恒定取最后一档
let reconnectStep = 0;       // 当前退避档位,连接成功后复位
let webrtcWant = false;      // 是否期望保持连接;主动隐藏预览时置 false,避免后台无限重连

function cancelReconnect() {
    if (reconnectTimer) { clearTimeout(reconnectTimer); reconnectTimer = null; }
    if (disconnectTimer) { clearTimeout(disconnectTimer); disconnectTimer = null; }
}

// 安排一次重连:仅在仍期望连接时执行;先关旧连接,按退避延时重建,已排期则跳过避免叠加
function scheduleReconnect() {
    if (!webrtcWant || reconnectTimer) return;
    if (disconnectTimer) { clearTimeout(disconnectTimer); disconnectTimer = null; }
    if (pc) { pc.close(); pc = null; }
    const v = document.getElementById('video');
    if (v) v.srcObject = null;
    const wait = RECONNECT_STEPS[reconnectStep];
    reconnectTimer = setTimeout(() => {
        reconnectTimer = null;
        if (webrtcWant) connect();
    }, wait);
    reconnectStep = Math.min(reconnectStep + 1, RECONNECT_STEPS.length - 1);
}

async function connect() {
    if (pc) return;
    webrtcWant = true;

    const group = typeof input !== 'undefined' ? input : 0;
    const stream = typeof output !== 'undefined' ? output : 0;

    try {
        pc = new RTCPeerConnection({
            iceServers: []
        });

        // ICE 状态:failed 立即重连;disconnected 给 3s 自愈观察期;连上则复位退避
        pc.oniceconnectionstatechange = () => {
            if (!pc) return;
            const state = pc.iceConnectionState;
            if (state === 'connected' || state === 'completed') {
                reconnectStep = 0;
                if (disconnectTimer) { clearTimeout(disconnectTimer); disconnectTimer = null; }
            } else if (state === 'failed') {
                scheduleReconnect();
            } else if (state === 'disconnected') {
                if (!disconnectTimer && !reconnectTimer) {
                    disconnectTimer = setTimeout(() => {
                        disconnectTimer = null;
                        if (pc && (pc.iceConnectionState === 'disconnected' ||
                                   pc.iceConnectionState === 'failed')) {
                            scheduleReconnect();
                        }
                    }, 3000);
                }
            }
        };

        pc.ontrack = (event) => {
            const video = document.getElementById('video');
            if (event.streams && event.streams[0]) {
                video.srcObject = event.streams[0];
            }
        };

        pc.addTransceiver('video', { direction: 'recvonly' });
        pc.addTransceiver('audio', { direction: 'recvonly' });

        let offer = await pc.createOffer();

        // Modify SDP to prefer the configured codec (H264 or H265)
        let sdp = offer.sdp;
        const lines = sdp.split('\r\n');
        let mLineIndex = -1;
        let preferredPayloadTypes = [];
        const codecName = (currentVencCodec == 265) ? 'H265' : 'H264';
        const codecRegex = new RegExp('^a=rtpmap:(\\d+) ' + codecName + '/');

        for (let i = 0; i < lines.length; i++) {
            if (lines[i].startsWith('m=video')) {
                mLineIndex = i;
            }
            const match = lines[i].match(codecRegex);
            if (match) {
                preferredPayloadTypes.push(match[1]);
            }
        }

        if (mLineIndex >= 0 && preferredPayloadTypes.length > 0) {
            const mLine = lines[mLineIndex];
            const parts = mLine.split(' ');
            const proto = parts.slice(0, 3).join(' ');
            const allPTs = parts.slice(3);
            const otherPTs = allPTs.filter(pt => !preferredPayloadTypes.includes(pt));
            const newPTs = [...preferredPayloadTypes, ...otherPTs];
            lines[mLineIndex] = proto + ' ' + newPTs.join(' ');
            sdp = lines.join('\r\n');
        }

        offer = { type: 'offer', sdp: sdp };
        await pc.setLocalDescription(offer);

        await new Promise((resolve) => {
            if (pc.iceGatheringState === 'complete') {
                resolve();
            } else {
                pc.onicegatheringstatechange = () => {
                    if (pc.iceGatheringState === 'complete') {
                        resolve();
                    }
                };
                setTimeout(resolve, 3000);
            }
        });

        const url = '/webrtc_stream?group=' + group + '&stream=' + stream + '&action=offer';

        const response = await fetch(url, {
            method: 'POST',
            headers: { 'Content-Type': 'text/plain' },
            body: pc.localDescription.sdp
        });

        const result = await response.json();

        if (result.error) {
            throw new Error(result.error);
        }

        const answer = { type: 'answer', sdp: result.sdp };
        await pc.setRemoteDescription(answer);

    } catch (error) {
        // 建链失败:走退避重连(scheduleReconnect 会自行关闭旧连接)
        scheduleReconnect();
    }
}
