/**
 * Packet-size constants for the fragmentation layer.
 *
 * The target transport MTU is 1200 bytes (Quake / Source / Glenn Fiedler's
 * Networked Physics recommend ~1200 to stay under typical PMTU after IP/UDP
 * headers; ethernet 1500 - 40 IPv6 - 8 UDP = 1452 in the best case, but
 * intermediate hops with tunnelling, IPv6 extension headers, or DSLite
 * routinely shave this down — 1200 is the safe number).
 *
 * Above this, the application's logical payload must be split into chunks
 * via {@link send_fragmented} and reassembled on the receiver via
 * {@link FragmentAssembler}.
 *
 * Header overhead breakdown for a fragment packet, from the transport's
 * point of view:
 *   - {@link Channel} adds 8 bytes (seq + ack_latest + ack_bitfield).
 *   - The FRAGMENT packet type byte = 1 byte.
 *   - Fragment header (message_id uint16 + chunk_index uint8 + total_chunks
 *     uint8) = 4 bytes.
 * Total overhead per fragment = 13 bytes; payload capacity per fragment =
 * 1200 - 13 = 1187 bytes.
 *
 * For a logical message that fits in a single packet (no fragmentation
 * needed), only the Channel header overhead applies — the payload starts
 * with its own packet-type byte (e.g. ACTION_STREAM) and is sent directly.
 *
 * @author Alex Goldring
 * @copyright Company Named Limited (c) 2026
 */

/** Target transport MTU. */
export const MTU_BYTES = 1200;

/** Channel layer's per-packet header size. */
export const CHANNEL_HEADER_BYTES = 8;

/**
 * Bytes the Channel reserves for the actual payload (no fragmentation):
 * MTU minus the channel header.
 */
export const MAX_CHANNEL_PAYLOAD_BYTES = MTU_BYTES - CHANNEL_HEADER_BYTES;

/**
 * Fragment header bytes within the channel payload:
 *   - 1 byte for the FRAGMENT packet-type marker
 *   - 2 bytes for message_id (uint16)
 *   - 1 byte for chunk_index (uint8)
 *   - 1 byte for total_chunks (uint8)
 */
export const FRAGMENT_HEADER_BYTES = 5;

/** Maximum number of payload bytes per fragment packet. */
export const MAX_FRAGMENT_CHUNK_BYTES = MAX_CHANNEL_PAYLOAD_BYTES - FRAGMENT_HEADER_BYTES;

/** Maximum number of chunks in a single logical message (limited by uint8 total_chunks). */
export const MAX_CHUNKS_PER_MESSAGE = 255;

/** Largest single logical payload supportable by this fragmentation scheme. */
export const MAX_LOGICAL_MESSAGE_BYTES = MAX_FRAGMENT_CHUNK_BYTES * MAX_CHUNKS_PER_MESSAGE;

/**
 * NACK retransmit timing.
 *
 *   FRAGMENT_NACK_INITIAL_DELAY_MS  — how long the receiver waits after the
 *     first chunk of a message arrives before NACKing the missing chunks.
 *     Trades off latency-of-recovery against premature NACKs for chunks
 *     that were just slightly late.
 *   FRAGMENT_NACK_RESEND_INTERVAL_MS — period between NACK retries when a
 *     message remains incomplete.
 *   FRAGMENT_NACK_MAX_ROUNDS — after this many NACK rounds without
 *     completion, the receiver drops the message; the sender's retention
 *     ages out independently.
 *
 * 75 ms initial delay is sized for the consumer mobile RTT bands measured
 * across US / EU / China in 2024–2025: 5G median 15–45 ms, 4G median
 * 30–55 ms, per-path jitter <10 ms for the majority of long-lived
 * connections. 75 ms sits comfortably above worst-case (4G median + jitter
 * + wire time for a small burst) so legitimate stragglers land before the
 * NACK fires, while keeping recovery latency on real loss to ~75 ms + 1
 * RTT. On worst-case paths the receiver may occasionally NACK chunks
 * still in transit; the receiver-side dedup absorbs the duplicate
 * retransmits.
 */
export const FRAGMENT_NACK_INITIAL_DELAY_MS = 75;
export const FRAGMENT_NACK_RESEND_INTERVAL_MS = 75;
export const FRAGMENT_NACK_MAX_ROUNDS = 3;

/**
 * Sender-side retention bounds. The sender keeps a copy of each fragmented
 * message's bytes so it can satisfy NACK retransmits. Retention is
 * FIFO-evicted at `FRAGMENT_RETENTION_MAX_MESSAGES` and age-evicted at
 * `FRAGMENT_RETENTION_MAX_AGE_MS`.
 *
 * Worst-case memory per peer: `FRAGMENT_RETENTION_MAX_MESSAGES *
 * max_message_size` bytes. With the FragmentAssembler default of 64 KiB,
 * that's 1 MiB per peer at saturation; steady-state retention is empty
 * because steady traffic fits in one packet and bypasses fragmentation.
 */
export const FRAGMENT_RETENTION_MAX_AGE_MS = 1500;
export const FRAGMENT_RETENTION_MAX_MESSAGES = 16;
export const FRAGMENT_RETENTION_MAX_RETRIES = 3;
