package com.foxx.androidcast.network.transport;

/*********************************************************************
 * RetransmitCache.java
 * Created at: Sun 17 May 2026 22:49:49 +0200
 * Updated at: Wed 20 May 2026 15:17:13 +0200 by Anton Afanasyeu <a.afanasieff@gmail.com>
 * Commit: 5d8e82d2e60a21fff3138d2a394ee4e8b4c6dcb8
 * class RetransmitCache
 * Contributors:
 *    - Anton Afanasyeu <a.afanasieff@gmail.com> (3 commits, 60 lines)
 *    - Cursor Agent (project assistant)
 * Digest: SHA256	410e0a7afeb307c0221d8866c4cda59e112d4db6ef2771e89028cf686e5976be
**********************************************************************/
import java.util.LinkedHashMap;
import java.util.Map;

/** Ring buffer of recent UDP logical messages for NACK retransmission. */
public final class RetransmitCache {
    /** VP9+FEC uses 7 message ids per frame; must cover several seconds of in-flight shards. */
    private static final int DEFAULT_CAPACITY = 4096;

    private final int capacity;
    private final LinkedHashMap<Integer, CachedMessage> map;

    public RetransmitCache() {
        this(DEFAULT_CAPACITY);
    }

    public RetransmitCache(int capacity) {
        this.capacity = Math.max(8, capacity);
        this.map = new LinkedHashMap<Integer, CachedMessage>(capacity + 1, 0.75f, true) {
            @Override
            protected boolean removeEldestEntry(Map.Entry<Integer, CachedMessage> eldest) {
                return size() > RetransmitCache.this.capacity;
            }
        };
    }

    public void put(int messageId, byte wireType, byte[] body) {
        if (body == null) {
            return;
        }
        synchronized (map) {
            map.put(messageId, new CachedMessage(wireType, body.clone()));
        }
    }

    public CachedMessage get(int messageId) {
        synchronized (map) {
            CachedMessage e = map.get(messageId);
            return e != null ? new CachedMessage(e.wireType, e.body.clone()) : null;
        }
    }

    public static final class CachedMessage {
        public final byte wireType;
        public final byte[] body;

        CachedMessage(byte wireType, byte[] body) {
            this.wireType = wireType;
            this.body = body;
        }
    }
}
