package com.foxx.androidcast.network.transport;

/*********************************************************************
 * TransportLossStatsBridge.java
 * Created at: Sat 16 May 2026 18:50:36 +0200
 * Updated at: Wed 20 May 2026 15:17:13 +0200 by Anton Afanasyeu <a.afanasieff@gmail.com>
 * Commit: 5d8e82d2e60a21fff3138d2a394ee4e8b4c6dcb8
 * class TransportLossStatsBridge
 * Contributors:
 *    - Anton Afanasyeu <a.afanasieff@gmail.com> (4 commits, 52 lines)
 *    - Cursor Agent (project assistant)
 * Digest: SHA256	a0e2d68b2e6d01631f986b6e85a57a9f134d7a8dd2cc12c3fd6dd25eb99d1189
**********************************************************************/
import com.foxx.androidcast.network.control.NetworkStatsSnapshot;

/** Copies {@link TransportLossStats} into {@link NetworkStatsSnapshot} for overlay / heartbeat. */
public final class TransportLossStatsBridge {
    private TransportLossStatsBridge() {}

    public static void applyTo(NetworkStatsSnapshot s, TransportLossStats loss) {
        if (s == null || loss == null) {
            return;
        }
        synchronized (loss) {
            loss.publishLegacyCounters();
            s.udpDatagramsRx = loss.datagramsReceived;
            s.udpDatagramsTx = loss.datagramsSent;
            s.udpDatagramsInvalid = loss.datagramsInvalid;
            s.udpFragmentsRx = loss.fragmentsReceived;
            s.udpFragmentsDuplicate = loss.fragmentsDuplicate;
            s.udpReassemblyOk = loss.reassemblyCompleted;
            s.udpReassemblyLost = loss.reassemblyIncomplete + loss.reassemblySuperseded;
            s.udpWireDropped = loss.wirePacketsDropped;
            s.udpMalformed = loss.malformedPackets;
            s.droppedPFrames = Math.max(s.droppedPFrames, loss.sendDroppedVideoP);
            s.droppedAudioFrames = loss.sendDroppedAudio;
            s.encodeQueueDepth = Math.max(s.encodeQueueDepth, loss.sendQueueDepth);
            s.recvVideoPackets = loss.recvVideoPackets;
            s.recvAudioPackets = loss.recvAudioPackets;
            s.recvVideoSkippedKey = loss.recvVideoSkippedAwaitingKey;
            s.recvVideoDecodeErrors = loss.recvVideoDecodeErrors;
            s.recvAudioDecodeErrors = loss.recvAudioDecodeErrors;
            s.recvAudioQueueDrops = loss.recvAudioQueueDrops;
            s.recvDamagedVideoFrames = loss.recvDamagedVideoFrames;
            s.protectionMode = loss.protectionMode.name();
            s.fecStubPackets = loss.fecPacketsEncoded;
            s.fecPacketsDecoded = loss.fecPacketsDecoded;
            s.fecDecodeFailures = loss.fecDecodeFailures;
            s.nackStubRequests = loss.nackRequestsSent + loss.nackRequestsReceived;
            long lossEvents = loss.estimatedUdpLossEvents();
            if (loss.datagramsReceived > 0 && lossEvents > 0) {
                s.lossRatio = Math.min(1f, lossEvents / (float) loss.datagramsReceived);
            }
        }
    }
}
