package com.foxx.androidcast.diagnostics;

/*********************************************************************
 * CastMtuSampler.java
 * Created at: Tue 19 May 2026 12:23:39 +0200
 * Updated at: Wed 20 May 2026 15:17:13 +0200 by Anton Afanasyeu <a.afanasieff@gmail.com>
 * Commit: 5d8e82d2e60a21fff3138d2a394ee4e8b4c6dcb8
 * class CastMtuSampler
 * Contributors:
 *    - Anton Afanasyeu <a.afanasieff@gmail.com> (2 commits, 74 lines)
 *    - Cursor Agent (project assistant)
 * Digest: SHA256	7b7b6e645520691a03083a3dd11215e0c35ecea5c23544ae3ae7fc60cc8e999c
**********************************************************************/
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.LinkProperties;
import android.net.Network;
import android.os.Build;

import com.foxx.androidcast.CastConfig;

/**
 * Link MTU from the OS plus derived cast UDP sizing (see {@link com.foxx.androidcast.network.UdpCastTransport}).
 */
public final class CastMtuSampler {
    /** ACUD header: magic(4) + type(1) + msgId(4) + fragIdx(2) + fragCnt(2) + totalLen(4). */
    public static final int ACUD_HEADER_BYTES = 17;
    private static final int IPV4_UDP_OVERHEAD = 20 + 8;

    public static final class Info {
        public final int linkMtu;
        public final String interfaceName;
        public final int castDatagramBytes;
        public final int castFragPayloadBytes;
        public final int ipv4WireBytes;
        /** {@code linkMtu - ipv4WireBytes}, or {@code -1} when link MTU is unknown. */
        public final int headroomBytes;

        Info(int linkMtu, String interfaceName, int castDatagramBytes, int castFragPayloadBytes,
                int ipv4WireBytes, int headroomBytes) {
            this.linkMtu = linkMtu;
            this.interfaceName = interfaceName != null ? interfaceName : "";
            this.castDatagramBytes = castDatagramBytes;
            this.castFragPayloadBytes = castFragPayloadBytes;
            this.ipv4WireBytes = ipv4WireBytes;
            this.headroomBytes = headroomBytes;
        }
    }

    private CastMtuSampler() {}

    public static Info sample(Context context) {
        int linkMtu = 0;
        String iface = "";
        if (context != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            ConnectivityManager cm = context.getSystemService(ConnectivityManager.class);
            if (cm != null) {
                Network network = cm.getActiveNetwork();
                LinkProperties lp = network != null ? cm.getLinkProperties(network) : null;
                if (lp != null) {
                    linkMtu = lp.getMtu();
                    if (lp.getInterfaceName() != null) {
                        iface = lp.getInterfaceName();
                    }
                }
            }
        }
        return calculate(linkMtu, iface);
    }

    public static Info calculate(int linkMtu, String interfaceName) {
        int datagram = CastConfig.UDP_CHUNK_SIZE;
        int fragPayload = Math.max(0, datagram - ACUD_HEADER_BYTES);
        int wire = datagram + IPV4_UDP_OVERHEAD;
        int headroom = linkMtu > 0 ? linkMtu - wire : -1;
        return new Info(linkMtu, interfaceName, datagram, fragPayload, wire, headroom);
    }
}
