//! Reticulum packet header and address primitives (`ARCHITECTURE.md` §3.1).
//!
//! These are the byte-level shapes the gateway is wire-compatible over. Values
//! that are protocol constants are encoded here directly; values the spec
//! defines only by reference (the `RESOURCE_*` family) are left as documented
//! gaps to be filled from the Reticulum manual and `RNS/Packet.py` during
//! Phase 1, rather than guessed.

/// Packet type — the two low bits of the flags byte.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum PacketType {
    /// Application / link data.
    Data = 0,
    /// Identity/destination announce.
    Announce = 1,
    /// Link establishment request.
    LinkRequest = 2,
    /// Proof of receipt.
    Proof = 3,
}

/// Destination type — bits 3–2 of the flags byte.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum DestinationType {
    /// Single recipient identified by an `Identity` (asymmetric).
    Single = 0,
    /// Group with a pre-shared symmetric key.
    Group = 1,
    /// Unencrypted plaintext destination.
    Plain = 2,
    /// An established encrypted link.
    Link = 3,
}

/// Propagation type — **a single bit** (bit 4) of the flags byte.
///
/// The on-wire field is one bit: broadcast vs. transport. This corrects
/// ARCHITECTURE.md §3.1, which listed four values — `Relay`/`Tunnel` are not
/// representable here. Authoritative: Reticulum manual, "Wire Format".
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum TransportType {
    /// Local broadcast (bit clear).
    Broadcast = 0,
    /// Routed via transport nodes (bit set).
    Transport = 1,
}

/// Header type — bit 6 of the flags byte. `H2` carries a transport id.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum HeaderType {
    /// 19-byte header, no transport id.
    H1 = 0,
    /// 35-byte header, includes a 16-byte transport id.
    H2 = 1,
}

/// The packet context byte (`ARCHITECTURE.md` §3.1).
///
/// A handful of values are protocol constants and are provided as associated
/// constants. The `RESOURCE_*` / `REQUEST` / `RESPONSE` / `CHANNEL` family is
/// declared by name in the architecture but its numeric values are spec-defined
/// and intentionally **not** invented here; they land in Phase 1.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ContextByte(pub u8);

impl ContextByte {
    /// No special context.
    pub const NONE: Self = Self(0x00);
    /// Link keepalive.
    pub const KEEPALIVE: Self = Self(0xFA);
    /// Link identification.
    pub const LINKIDENTIFY: Self = Self(0xFB);
    /// Link close.
    pub const LINKCLOSE: Self = Self(0xFC);
    /// Link proof.
    pub const LINKPROOF: Self = Self(0xFD);
    /// Link request round-trip-time measurement.
    pub const LRRTT: Self = Self(0xFE);
    /// Link request proof.
    pub const LRPROOF: Self = Self(0xFF);
}

/// A truncated 128-bit (16-byte) destination/identity/link hash.
///
/// The width is a protocol constant; it is deliberately **not** parameterized.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct AddressHash([u8; 16]);

impl AddressHash {
    /// Wrap an existing 16-byte hash.
    #[must_use]
    pub const fn new(bytes: [u8; 16]) -> Self {
        Self(bytes)
    }

    /// Borrow the raw 16 bytes.
    #[must_use]
    pub const fn as_bytes(&self) -> &[u8; 16] {
        &self.0
    }
}

/// A decoded Reticulum packet header (`ARCHITECTURE.md` §3.1).
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PacketHeader {
    /// Interface-access-code framing flag (header bit 7).
    pub ifac: bool,
    /// Header type (H1/H2).
    pub header_type: HeaderType,
    /// Context-flag bit.
    pub context_flag: bool,
    /// Transport propagation type.
    pub transport_type: TransportType,
    /// Destination type.
    pub destination_type: DestinationType,
    /// Packet type.
    pub packet_type: PacketType,
    /// Hop count.
    pub hops: u8,
    /// Transport id — present iff `header_type == HeaderType::H2`.
    pub transport_id: Option<AddressHash>,
    /// Destination address hash.
    pub destination: AddressHash,
    /// Context byte.
    pub context: ContextByte,
}

/// H1 header size in bytes: `flags(1) + hops(1) + destination(16) + context(1)`.
pub const HEADER_SIZE_H1: usize = 1 + 1 + 16 + 1;
/// H2 header size in bytes: H1 plus a 16-byte transport id.
pub const HEADER_SIZE_H2: usize = 1 + 1 + 16 + 16 + 1;
/// Reticulum link MTU.
pub const MTU: usize = 500;
