// Copyright (c) 2025-2026 Defense Unicorns, Inc.
// SPDX-License-Identifier: Apache-2.0

//! Wire format constants and error types.
//!
//! Defines markers and error handling for over-the-air message encoding.

use crate::canned::MAX_CANNED_ACKS;

/// Marker byte for canned message events on the wire.
///
/// Format: `0xAF` followed by message payload.
/// This allows receivers to distinguish canned messages from other data.
pub const CANNED_MESSAGE_MARKER: u8 = 0xAF;

/// Size of an Ed25519 signature in bytes.
pub const SIGNATURE_SIZE: usize = 64;

/// Size of unsigned CannedMessageEvent wire format.
///
/// Format: `[marker:1][msg_code:1][src:4][tgt:4][timestamp:8][seq:4] = 22 bytes`
pub const CANNED_MESSAGE_UNSIGNED_SIZE: usize = 22;

/// Size of signed CannedMessageEvent wire format.
///
/// Format: `[marker:1][msg_code:1][src:4][tgt:4][timestamp:8][seq:4][signature:64] = 86 bytes`
pub const CANNED_MESSAGE_SIGNED_SIZE: usize = CANNED_MESSAGE_UNSIGNED_SIZE + SIGNATURE_SIZE;

/// Maximum encoded size for [`CannedMessageAckEvent`](crate::CannedMessageAckEvent).
///
/// 24 bytes base + (12 bytes per ACK entry × MAX_CANNED_ACKS).
pub const CANNED_ACK_EVENT_MAX_SIZE: usize = 24 + MAX_CANNED_ACKS * 12;

/// Wire format error types.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum WireError {
    /// Data too short to contain required fields.
    TooShort,
    /// Invalid marker byte.
    InvalidMarker,
    /// Unknown message code.
    UnknownCode,
    /// Checksum mismatch.
    ChecksumMismatch,
    /// Buffer capacity exceeded.
    BufferFull,
    /// Invalid or missing signature.
    InvalidSignature,
}

#[cfg(feature = "std")]
impl std::fmt::Display for WireError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::TooShort => write!(f, "data too short"),
            Self::InvalidMarker => write!(f, "invalid marker byte"),
            Self::UnknownCode => write!(f, "unknown message code"),
            Self::ChecksumMismatch => write!(f, "checksum mismatch"),
            Self::BufferFull => write!(f, "buffer capacity exceeded"),
            Self::InvalidSignature => write!(f, "invalid or missing signature"),
        }
    }
}

#[cfg(feature = "std")]
impl std::error::Error for WireError {}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_marker_value() {
        // Verify marker is in the "reserved" range and unlikely to collide
        assert_eq!(CANNED_MESSAGE_MARKER, 0xAF);
    }
}
